File indexing completed on 2024-04-21 15:55:45
0001 /***************************************************************************************** 0002 Copyright (C) 2005 by Holger Danielsson (holger.danielsson@t-online.de) 0003 2010-2022 by Michel Ludwig (michel.ludwig@kdemail.net) 0004 ******************************************************************************************/ 0005 0006 /*************************************************************************** 0007 * * 0008 * This program is free software; you can redistribute it and/or modify * 0009 * it under the terms of the GNU General Public License as published by * 0010 * the Free Software Foundation; either version 2 of the License, or * 0011 * (at your option) any later version. * 0012 * * 0013 ***************************************************************************/ 0014 0015 #include "latexcmd.h" 0016 0017 #include <KConfigGroup> 0018 // #include <KLocalizedString> 0019 0020 #include "kiledebug.h" 0021 0022 namespace KileDocument 0023 { 0024 0025 // BEGIN LatexCommands 0026 0027 LatexCommands::LatexCommands(KConfig *config, KileInfo *info) : m_config(config), m_ki(info) 0028 { 0029 m_envGroupName = "Latex Environments"; 0030 m_cmdGroupName = "Latex Commands"; 0031 0032 LatexCommands::resetCommands(); 0033 } 0034 0035 void LatexCommands::resetCommands() 0036 { 0037 // description of the fields for environments 0038 // 0: standard entry (+,-) 0039 // 1: environmenty type (a,m,l,t,v) 0040 // 2: including starred version (*) 0041 // 3: eol character (\\\\) 0042 // 4: need mathmode ($) or displaymathmode ($$) 0043 // 5: standard tabulator (tabulator string, f.e. &=& or &=) 0044 // 6: optional parameter 0045 // 7: parameter group(s) 0046 0047 QStringList envlist; 0048 envlist 0049 // list environments 0050 << "itemize,+,l,*,,,,," 0051 << "enumerate,+,l,*,,,,," 0052 << "description,+,l,*,,,,," 0053 << "Bitemize,+,l,,,,,," 0054 << "Benumerate,+,l,,,,,," 0055 << "Bdescription,+,l,,,,,," 0056 << "labeling,+,l,,,,,[ ],{ }" 0057 // tabular environments 0058 << "tabular,+,t,*,\\\\,,&,[tcb]," 0059 << "tabularx,+,t,,\\\\,,&,,{w}" 0060 << "tabbing,+,t,,\\\\,,\\>,," 0061 << "longtable,+,t,,\\\\,,&,[tcb]," 0062 << "ltxtable,+,t,,\\\\,,&,[tcb],{w}" 0063 << "supertabular,+,t,*,\\\\,,&,," 0064 << "mpsupertabular,+,t,*,\\\\,,&,," 0065 << "xtabular,+,t,*,\\\\,,&,," 0066 << "mpxtabular,+,t,*,\\\\,,&,," 0067 // math environments 0068 << "displaymath,+,m,,,,,," 0069 << "equation,+,m,*,,,,," 0070 << "eqnarray,+,m,*,\\\\,,&=&,," 0071 << "array,+,m,,\\\\,$,&,[tcb]," 0072 << "matrix,+,m,,\\\\,$,&,," 0073 << "pmatrix,+,m,,\\\\,$,&,," 0074 << "bmatrix,+,m,,\\\\,$,&,," 0075 << "Bmatrix,+,m,,\\\\,$,&,," 0076 << "vmatrix,+,m,,\\\\,$,&,," 0077 << "Vmatrix,+,m,,\\\\,$,&,," 0078 // amsmath environments 0079 << "multline,+,a,*,\\\\,,,," 0080 << "gather,+,a,*,\\\\,,,," 0081 << "split,+,a,,\\\\,$$,,," // needs surrounding environment 0082 << "align,+,a,*,\\\\,,&=,," 0083 << "flalign,+,a,*,\\\\,,&=,," 0084 << "alignat,+,a,*,\\\\,,&=,,{n}" 0085 << "aligned,+,a,,\\\\,$,&=,[tcb]," 0086 << "gathered,+,a,,\\\\,$,,[tcb]," 0087 << "alignedat,+,a,,\\\\,$,&=,[tcb],{n}" 0088 //<< "xalignat,+,a,*,\\\\,,&=,,{n}" // obsolet 0089 //<< "xxalignat,+,a,*,\\\\,,&=,,{n}" // obsolet 0090 << "cases,+,a,,\\\\,$,&,," 0091 // verbatim environments 0092 << "verbatim,+,v,*,,,,," 0093 << "boxedverbatim,+,v,,,,,," 0094 << "Bverbatim,+,v,,,,,[ ]," 0095 << "Lverbatim,+,v,,,,,[ ]," 0096 << "lstlisting,+,v,,,,,[ ]," 0097 ; 0098 0099 // description of the fields for commands 0100 // 0: standard entry (+,-) 0101 // 1: command type (L,R,C,I) 0102 // 2: including starred version (*) 0103 // 3: optional parameter 0104 // 4: parameter 0105 0106 QStringList cmdlist; 0107 cmdlist 0108 // Labels 0109 << "\\label,+,L,,,{ }" 0110 // References 0111 << "\\ref,+,R,,,{ }" 0112 << "\\pageref,+,R,,,{ }" 0113 << "\\vref,+,R,,,{ }" 0114 << "\\vpageref,+,R,,[ ],{ }" 0115 << "\\fref,+,R,,,{ }" 0116 << "\\Fref,+,R,,,{ }" 0117 << "\\eqref,+,R,,,{ }" 0118 << "\\autoref,+,R,,,{ }" 0119 // Bibliographies 0120 << "\\bibliography,+,B,,,{ }" 0121 << "\\addbibresource,+,B,*,[ ],{ }" 0122 << "\\addglobalbib,+,B,*,[ ],{ }" 0123 << "\\addsectionbib,+,B,*,[ ],{ }" 0124 // Citations 0125 << "\\cite,+,C,,,{ }" 0126 // Includes 0127 << "\\include,+,I,,,{ }" 0128 << "\\input,+,I,,,{ }" 0129 << "\\Input,+,I,,,{ }" 0130 ; 0131 0132 // first clear the dictionary 0133 m_latexCommands.clear(); 0134 0135 // insert environments 0136 addUserCommands(m_envGroupName,envlist); 0137 insert(envlist); 0138 0139 // insert commands 0140 addUserCommands(m_cmdGroupName,cmdlist); 0141 insert(cmdlist); 0142 } 0143 0144 0145 // add user-defined environments/commands 0146 0147 //FIXME: the code for reading and writing these configuration entries should be regrouped 0148 // within a single class (currently, the code for writing the values can be found 0149 // in 'latexcommanddialog.cpp'). 0150 void LatexCommands::addUserCommands(const QString &name, QStringList &list) 0151 { 0152 KILE_DEBUG_MAIN << name; 0153 if(!m_config->hasGroup(name)) { 0154 KILE_DEBUG_MAIN << "\tGroup does not exist."; 0155 return; 0156 } 0157 0158 KConfigGroup group = m_config->group(name); 0159 int nrOfDefinedCommands = group.readEntry("Number of Commands", 0); 0160 0161 for(int i = 0; i < nrOfDefinedCommands; ++i) { 0162 const QString commandKey = "Command" + QString::number(i); 0163 const QString parametersKey = "Parameters" + QString::number(i); 0164 0165 if(!group.hasKey(commandKey) || !group.hasKey(parametersKey)) { 0166 KILE_DEBUG_MAIN << "\tEntry" << i << "is invalid!"; 0167 } 0168 const QString command = group.readEntry(commandKey); 0169 const QString parameters = group.readEntry(parametersKey); 0170 list << command + ",-," + parameters; 0171 KILE_DEBUG_MAIN << "\tAdding: " << command + " --> " + parameters; 0172 } 0173 } 0174 0175 // insert all entries into the dictionary 0176 0177 void LatexCommands::insert(const QStringList &list) 0178 { 0179 // now insert new entries, if they have the right number of attributes 0180 QStringList::ConstIterator it; 0181 for(it = list.begin(); it!=list.end(); ++it) { 0182 int pos = (*it).indexOf(','); 0183 if(pos >= 0) { 0184 QString key = (*it).left(pos); 0185 QString value = (*it).right( (*it).length()-pos-1 ); 0186 QStringList valuelist = value.split(',', Qt::KeepEmptyParts); 0187 int attributes = ( key.at(0)=='\\' ) ? MaxCmdAttr : MaxEnvAttr; 0188 if(valuelist.count() == attributes) { 0189 m_latexCommands[key] = value; 0190 } 0191 else { 0192 KILE_DEBUG_MAIN << "\tLatexCommands error: wrong number of attributes (" << key << " ---> " << value << ")"; 0193 } 0194 } 0195 else { 0196 KILE_DEBUG_MAIN << "\tLatexCommands error: no separator found (" << (*it) << ")" ; 0197 } 0198 } 0199 } 0200 0201 //////////////////// get value from dictionary //////////////////// 0202 0203 // Get value of a key. A star at the end is stripped. 0204 0205 QString LatexCommands::getValue(const QString &name) 0206 { 0207 QString key = (name.indexOf('*',-1) >= 0) ? name.left(name.length()-1) : name; 0208 return (m_latexCommands.contains(key)) ? m_latexCommands[key] : QString(); 0209 } 0210 0211 //////////////////// internal functions //////////////////// 0212 0213 // get parameter at index 0214 0215 QString LatexCommands::getAttrAt(const QString &name, int index) 0216 { 0217 if(index < 0) { 0218 return QString(); 0219 } 0220 int attributes = (name.at(0) == '\\') ? MaxCmdAttr : MaxEnvAttr; 0221 QStringList list = getValue(name).split(',', Qt::KeepEmptyParts); 0222 return (index < attributes && list.count() == attributes) ? list[index] : QString(); 0223 } 0224 0225 // check for a standard environment 0226 0227 bool LatexCommands::isUserDefined(const QString &name) 0228 { 0229 return ( getValue(name).at(0) == '-' ); 0230 } 0231 0232 // check for a special environment type 0233 0234 bool LatexCommands::isType(const QString &name, QChar ch) 0235 { 0236 if(name.indexOf('*', -1) >= 0) { 0237 QString envname = name.left(name.length() - 1); 0238 QString value = getValue(envname); 0239 return (value.length() >= 3 && value.at(2) == ch && isStarredEnv(envname)); 0240 } 0241 else { 0242 QString value = getValue(name); 0243 return (value.length() >= 3 && value.at(2) == ch); 0244 } 0245 } 0246 0247 //////////////////// attributes and characters //////////////////// 0248 0249 // convert attribute to character 0250 0251 QChar LatexCommands::getAttrChar(CmdAttribute attr) 0252 { 0253 QChar ch; 0254 switch(attr) { 0255 case CmdAttrAmsmath: 0256 ch = 'a'; 0257 break; 0258 case CmdAttrMath: 0259 ch = 'm'; 0260 break; 0261 case CmdAttrList: 0262 ch = 'l'; 0263 break; 0264 case CmdAttrVerbatim: 0265 ch = 'v'; 0266 break; 0267 case CmdAttrTabular: 0268 ch = 't'; 0269 break; 0270 case CmdAttrLabel: 0271 ch = 'L'; 0272 break; 0273 case CmdAttrReference: 0274 ch = 'R'; 0275 break; 0276 case CmdAttrCitations: 0277 ch = 'C'; 0278 break; 0279 case CmdAttrIncludes: 0280 ch = 'I'; 0281 break; 0282 case CmdAttrBibliographies: 0283 ch = 'B'; 0284 break; 0285 default: 0286 KILE_DEBUG_MAIN << "\tLatexCommands error: unknown type of env/cmd: code " << attr; 0287 return '?'; 0288 } 0289 0290 return ch; 0291 } 0292 0293 // convert character to attribute 0294 CmdAttribute LatexCommands::getCharAttr(QChar ch) 0295 { 0296 CmdAttribute attr; 0297 switch(ch.unicode()) { 0298 case 'a': 0299 attr = CmdAttrAmsmath; 0300 break; 0301 case 'm': 0302 attr = CmdAttrMath; 0303 break; 0304 case 'l': 0305 attr = CmdAttrList; 0306 break; 0307 case 'v': 0308 attr = CmdAttrVerbatim; 0309 break; 0310 case 't': 0311 attr = CmdAttrTabular; 0312 break; 0313 case 'L': 0314 attr = CmdAttrLabel; 0315 break; 0316 case 'R': 0317 attr = CmdAttrReference; 0318 break; 0319 case 'C': 0320 attr = CmdAttrCitations; 0321 break; 0322 case 'I': 0323 attr = CmdAttrIncludes; 0324 break; 0325 case 'B': 0326 attr = CmdAttrBibliographies; 0327 break; 0328 default: 0329 KILE_DEBUG_MAIN << "\tLatexCommands error: unknown type of env/cmd: " << static_cast<char>(ch.unicode()); 0330 return CmdAttrNone; 0331 } 0332 0333 return attr; 0334 } 0335 0336 //////////////////// public attributes //////////////////// 0337 0338 // check for environment types 0339 0340 bool LatexCommands::isMathEnv(const QString &name) 0341 { 0342 QString value = getValue(name); 0343 if(value.length() < 3) { 0344 return false; 0345 } 0346 0347 QChar ch = value.at(2); 0348 return (ch == 'm' || ch == 'a'); 0349 } 0350 0351 // check for some special attributes 0352 0353 bool LatexCommands::isStarredEnv(const QString &name) 0354 { 0355 return (getAttrAt(name, 2) == "*"); 0356 } 0357 0358 bool LatexCommands::isCrEnv(const QString &name) 0359 { 0360 return (getAttrAt(name, 3) == "\\\\"); 0361 } 0362 0363 bool LatexCommands::isMathModeEnv(const QString &name) 0364 { 0365 return (getAttrAt(name, 4) == "$"); 0366 } 0367 0368 bool LatexCommands::isDisplaymathModeEnv(const QString &name) 0369 { 0370 return (getAttrAt(name, 4) == "$$"); 0371 } 0372 0373 bool LatexCommands::needsMathMode(const QString &name) 0374 { 0375 return (isMathModeEnv(name) || isDisplaymathModeEnv(name)); 0376 } 0377 0378 QString LatexCommands::getTabulator(const QString &name) 0379 { 0380 QString tab = getAttrAt(name, 5); 0381 return (tab.indexOf('&') >= 0) ? tab : QString(); 0382 } 0383 0384 //////////////////// environments and commands //////////////////// 0385 0386 // get a list of environments and commands. The search can be restricted 0387 // to given attributes and userdefined environments and commands 0388 0389 void LatexCommands::commandList(QStringList &list, uint attr, bool userdefined) 0390 { 0391 list.clear(); 0392 0393 QMapIterator<QString,QString> it(m_latexCommands); 0394 while(it.hasNext()) { 0395 it.next(); 0396 // first check, if we need really need all environments and commands 0397 // or if a restriction to some attributes is given 0398 if(attr != (uint)CmdAttrNone) { 0399 if(!(attr & (uint)getCharAttr( it.value().at(2)))) { 0400 continue; 0401 } 0402 } 0403 0404 // second check, if we need only user-defined environments or commands 0405 if(!userdefined) { 0406 list.append(it.key()); 0407 } 0408 else if(it.value().at(0) == '-') { 0409 list.append(it.key()); 0410 } 0411 } 0412 } 0413 0414 // get all attributes for a given environment and command 0415 0416 bool LatexCommands::commandAttributes(const QString &name, LatexCmdAttributes &attr) 0417 { 0418 int attributes = (name.at(0) == '\\') ? MaxCmdAttr : MaxEnvAttr; 0419 0420 // split attribute list 0421 QStringList list = getValue(name).split(',', Qt::KeepEmptyParts); 0422 0423 // check number of attributes 0424 if(list.count() != attributes) { 0425 return false; 0426 } 0427 0428 // check for a standard environment/command 0429 attr.standard = (list[0] == "+"); 0430 0431 // most important: type of environment or command 0432 attr.type = getCharAttr(list[1].at(0)); 0433 if(attr.type == CmdAttrNone) { 0434 return false; 0435 } 0436 0437 // all environments/commands have starred attribute 0438 attr.starred = (list[2] == "*"); 0439 0440 // next attributes differ for environments and commands 0441 if(attributes == MaxEnvAttr) { 0442 attr.cr = (list[3] == "\\\\"); 0443 attr.mathmode = (list[4] == "$"); 0444 attr.displaymathmode = (list[4] == "$$"); 0445 attr.tabulator = list[5]; 0446 attr.option = list[6]; 0447 attr.parameter = list[7]; 0448 } 0449 else { 0450 attr.cr = false; 0451 attr.mathmode = false; 0452 attr.displaymathmode = false; 0453 attr.tabulator.clear(); 0454 attr.option = list[3]; 0455 attr.parameter = list[4]; 0456 } 0457 0458 return true; 0459 } 0460 0461 //////////////////// determine config string //////////////////// 0462 0463 QString LatexCommands::configString(const LatexCmdAttributes &attr,bool env) 0464 { 0465 // most important: type of environment or command 0466 QChar ch = getAttrChar(attr.type); 0467 if(ch == '?') { 0468 return QString(); 0469 } 0470 QString s = ch + QString(','); 0471 0472 // all environments/commands have starred attribute 0473 if(attr.starred) { 0474 s += "*,"; 0475 } 0476 else { 0477 s += ','; 0478 } 0479 0480 // next attributes are only valid for environments 0481 if(env) { 0482 if(attr.cr) { 0483 s += "\\\\,"; 0484 } 0485 else { 0486 s += ','; 0487 } 0488 if(attr.mathmode) { 0489 s += "$,"; 0490 } 0491 else if(attr.displaymathmode) { 0492 s += "$$"; 0493 } 0494 else { 0495 s += ','; 0496 } 0497 s += attr.tabulator + ','; 0498 } 0499 0500 // option and parameter are for both types again 0501 s += attr.option + ','; 0502 s += attr.parameter; 0503 0504 return s; // s.left(s.length()-1); 0505 } 0506 0507 // END LatexCommands 0508 0509 }