]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/MathParser.cpp
* \newcommandx support for the math parser
[lyx.git] / src / mathed / MathParser.cpp
index d2c4d762edfd0bed9e35f47e86a55b22abe2b3d3..4856924590d3c49f2278c888646eb1a850b80641 100644 (file)
@@ -63,8 +63,8 @@ following hack as starting point to write some macros:
 #include "MathSupport.h"
 
 #include "Lexer.h"
-#include "support/debug.h"
 
+#include "support/debug.h"
 #include "support/convert.h"
 #include "support/docstream.h"
 
@@ -892,16 +892,28 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                                cell->back().nucleus()->lock(true);
                }
 
-               else if (t.cs() == "def" ||
+               else if ((t.cs() == "global" && nextToken().cs() == "def") ||
+                       t.cs() == "def" ||
                        t.cs() == "newcommand" ||
-                       t.cs() == "renewcommand")
+                       t.cs() == "renewcommand" ||
+                       t.cs() == "newlyxcommand" ||
+                       t.cs() == "newcommandx" ||
+                       t.cs() == "renewcommandx")
                {
-                       docstring const type = t.cs();
+                       MacroType type = MacroTypeNewcommand;
+                       if (t.cs() == "global") {
+                               getToken();
+                               type = MacroTypeDef;
+                       }
+                       if (t.cs() == "def")
+                               type = MacroTypeDef;
+                       if (t.cs() == "newcommandx" || t.cs() == "renewcommandx")
+                               type = MacroTypeNewcommandx;
                        docstring name;
                        int nargs = 0;
                        int optionals = 0;
                        vector<MathData> optionalValues;
-                       if (t.cs() == "def") {
+                       if (type == MacroTypeDef) {
                                // get name
                                name = getToken().cs();
 
@@ -914,7 +926,100 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                                nargs /= 2;
                                //lyxerr << "read \\def parameter list '" << pars << "'" << endl;
 
-                       } else { // t.cs() == "newcommand" || t.cs() == "renewcommand"
+                       } else if (type == MacroTypeNewcommandx) {
+                               // \newcommandx{\foo}[2][usedefault, addprefix=\global,1=default]{#1,#2}
+                               // name
+                               if (nextToken().cat() == catBegin) {
+                                       getToken();
+                                       name = getToken().cs();
+                                       if (getToken().cat() != catEnd) {
+                                               error("'}' in \\newcommandx expected");
+                                               return;
+                                       }
+                               } else
+                                       name = getToken().cs();
+                               
+                               // arity
+                               docstring const arg = getArg('[', ']');
+                               if (arg.empty()) {
+                                       error("[num] in \\newcommandx expected");
+                                       return;
+                               }
+                               nargs = convert<int>(arg);
+                               
+                               // options
+                               if (nextToken().character() == '[') {
+                                       // skip '['
+                                       getToken();
+                                       
+                                       // handle 'opt=value' options, separated by ','.
+                                       skipSpaces();
+                                       while (nextToken().character() != ']' && good()) {
+                                               if (nextToken().character() >= '1'
+                                                   && nextToken().character() <= '9') {
+                                                       // optional value -> get parameter number
+                                                       int n = getChar() - '0';
+                                                       if (n > nargs) {
+                                                               error("Arity of \\newcommandx too low for given optional parameter.");
+                                                               return;
+                                                       }
+                                                       
+                                                       // skip '='
+                                                       if (getToken().character() != '=') {
+                                                               error("'=' and optional parameter value expected for \\newcommandx");
+                                                               return;
+                                                       }
+                                                       
+                                                       // get value
+                                                       optionalValues.resize(max(size_t(n), optionalValues.size()));
+                                                       optionalValues[n - 1].clear();
+                                                       while (nextToken().character() != ']'
+                                                              && nextToken().character() != ',') {
+                                                               MathData data;
+                                                               parse(data, FLAG_ITEM, InsetMath::UNDECIDED_MODE);
+                                                               optionalValues[n - 1].append(data);
+                                                       }
+                                                       optionals = max(n, optionals);
+                                               } else if (nextToken().cat() == catLetter) {
+                                                       // we in fact ignore every non-optional
+                                                       // parameters
+                                                       
+                                                       // get option name
+                                                       docstring opt;
+                                                       while (nextToken().cat() == catLetter)
+                                                               opt += getChar();
+                                                       
+                                                       // value?
+                                                       skipSpaces();
+                                                       MathData value;
+                                                       if (nextToken().character() == '=') {
+                                                               getToken();
+                                                               while (nextToken().character() != ']'
+                                                                       && nextToken().character() != ',')
+                                                                       parse(value, FLAG_ITEM, InsetMath::UNDECIDED_MODE);
+                                                       }
+                                               } else {
+                                                       error("option for \\newcommandx expected");
+                                                       return;
+                                               }
+
+                                               // skip komma
+                                               skipSpaces();
+                                               if (nextToken().character() == ',') {
+                                                       getChar();
+                                                       skipSpaces();
+                                               } else if (nextToken().character() != ']') {
+                                                       error("Expecting ',' or ']' in options of \\newcommandx");
+                                                       return;
+                                               }
+                                       }
+                                       
+                                       // skip ']'
+                                       if (!good())
+                                               return;
+                                       getToken();
+                               }
+                       } else {
                                if (getToken().cat() != catBegin) {
                                        error("'{' in \\newcommand expected (1) ");
                                        return;
@@ -950,8 +1055,8 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                        if (nextToken().cat() == catBegin)
                                parse(display, FLAG_ITEM, InsetMath::MATH_MODE);
 
-                       cell->push_back(MathAtom(new MathMacroTemplate(name, nargs, optionals, type, 
-                                                                                                                                                                                                                optionalValues, def, display)));
+                       cell->push_back(MathAtom(new MathMacroTemplate(name, nargs,
+                               optionals, type, optionalValues, def, display)));
                }
 
                else if (t.cs() == "(") {
@@ -1263,7 +1368,7 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                                               << to_utf8(l->inset) << "'." << endl;
                                        // create generic environment inset
                                        cell->push_back(MathAtom(new InsetMathEnv(name)));
-                                       parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+                                       parse(cell->back().nucleus()->cell(0), FLAG_END, mode);
                                }
                        }
 
@@ -1273,7 +1378,7 @@ void Parser::parse1(InsetMathGrid & grid, unsigned flags,
                                        << "'" << endl;
                                // create generic environment inset
                                cell->push_back(MathAtom(new InsetMathEnv(name)));
-                               parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
+                               parse(cell->back().nucleus()->cell(0), FLAG_END, mode);
                        }
                }