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 }