commit aad2bc0bab33639ed2790b7bd4ac98cef50ea696
Author: Enrico Forestieri <[email protected]>
Date:   Fri Jul 4 12:21:05 2025 -0400

    Fix bug #8934
    
    Patch by Georg adapted to current master, and amended, by Enrico.
---
 src/Buffer.cpp              |  1 -
 src/Buffer.h                |  3 +-
 src/insets/InsetInclude.cpp |  8 +---
 src/mathed/MathParser.cpp   | 91 ++++++++++++++++++++++++++++++++++++---------
 status.24x                  |  2 +
 5 files changed, 80 insertions(+), 25 deletions(-)

diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index 43dd4a69da..46db015569 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -1131,7 +1131,6 @@ bool Buffer::readDocument(Lexer & lex)
                for (auto const & m : usermacros)
                        pbuf->usermacros.insert(m);
        }
-       usermacros.clear();
        updateMacros();
        updateMacroInstances(InternalUpdate);
        return res;
diff --git a/src/Buffer.h b/src/Buffer.h
index dc2583629d..7b78281e3b 100644
--- a/src/Buffer.h
+++ b/src/Buffer.h
@@ -629,7 +629,8 @@ public:
        MacroData const * getMacro(docstring const & name, Buffer const & 
child, bool global = true) const;
 
        /// Collect user macro names at loading time
-       typedef std::set<docstring> UserMacroSet;
+       /// Map maps from macro name to number of optional arguments
+       typedef std::map<docstring, size_t> UserMacroSet;
        mutable UserMacroSet usermacros;
 
        /// Replace the inset contents for insets which InsetCode is equal
diff --git a/src/insets/InsetInclude.cpp b/src/insets/InsetInclude.cpp
index f4ecaae8a0..5e23280096 100644
--- a/src/insets/InsetInclude.cpp
+++ b/src/insets/InsetInclude.cpp
@@ -512,12 +512,8 @@ Buffer * InsetInclude::loadIfNeeded() const
                // inform parent buffer about local macros.
                Buffer const * parent = &buffer();
                child->setParent(parent);
-               MacroNameSet macros;
-               child->listMacroNames(macros);
-               MacroNameSet::const_iterator cit = macros.begin();
-               MacroNameSet::const_iterator end = macros.end();
-               for (; cit != end; ++cit)
-                       parent->usermacros.insert(*cit);
+               for (auto const & m : child->usermacros)
+                       parent->usermacros.insert(m);
        }
 
        // Cache the child buffer.
diff --git a/src/mathed/MathParser.cpp b/src/mathed/MathParser.cpp
index 8a324818ed..382b14b71e 100644
--- a/src/mathed/MathParser.cpp
+++ b/src/mathed/MathParser.cpp
@@ -1079,12 +1079,13 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned 
flags,
                        if (nextToken().cat() == catBegin)
                                parse(display, FLAG_ITEM, InsetMath::MATH_MODE);
 
+                       size_t const optionals = 0;
                        cell->push_back(MathAtom(new InsetMathMacroTemplate(buf,
-                               name, nargs, 0, MacroTypeDef,
+                               name, nargs, optionals, MacroTypeDef,
                                vector<MathData>(), def, display)));
 
                        if (buf && (mode_ & Parse::TRACKMACRO))
-                               buf->usermacros.insert(name);
+                               buf->usermacros[name] = optionals;
                }
 
                else if (t.cs() == "newcommand" ||
@@ -1132,7 +1133,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
                                optionalValues, def, display)));
 
                        if (buf && (mode_ & Parse::TRACKMACRO))
-                               buf->usermacros.insert(name);
+                               buf->usermacros[name] = optionals;
                }
 
                else if (t.cs() == "newcommandx" ||
@@ -1253,7 +1254,7 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
                                optionalValues, def, display)));
 
                        if (buf && (mode_ & Parse::TRACKMACRO))
-                               buf->usermacros.insert(name);
+                               buf->usermacros[name] = optionals;
                }
 
                else if (t.cs() == "(") {
@@ -1989,10 +1990,28 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned 
flags,
                        if (l && !is_user_macro) {
                                if (l->inset == "big") {
                                        skipSpaces();
+                                       // If we are parsing for an optional 
argument,
+                                       // we must not handle ']' as a 
delimiter (bug 8934).
+                                       // In standard LaTeX \foo[\Big] will 
give an error
+                                       // "Missing delimiter (. inserted)", 
however in
+                                       // combination with 
\DeclarePairedDelimiterX from
+                                       // the mathtools package \Big on its 
own inside an
+                                       // optional argument is valid:
+                                       // \documentclass{article}
+                                       // \usepackage{mathtools}
+                                       // 
\DeclarePairedDelimiterX{\COM}[2]{[}{]}{#1,#2}
+                                       // 
\newcommand{\Com}[3][]{\COM[#1]{#2}{#3}}
+                                       // \begin{document}
+                                       // $\Com[\Big]AB$
+                                       // \end{document}
+                                       // Therefore, if we are looking for 
FLAG_BRACK_LAST,
+                                       // and if the delimiter is ']', let 
FLAG_BRACK_LAST
+                                       // take precedence.
                                        docstring const delim = 
getToken().asInput();
-                                       if 
(InsetMathBig::isBigInsetDelim(delim))
+                                       if 
(InsetMathBig::isBigInsetDelim(delim) &&
+                                           (delim != "]" || !(flags & 
FLAG_BRACK_LAST)))
                                                cell->push_back(MathAtom(
-                                                                               
        new InsetMathBig(buf, t.cs(), delim)));
+                                                       new InsetMathBig(buf, 
t.cs(), delim)));
                                        else {
                                                
cell->push_back(createInsetMath(t.cs(), buf));
                                                // For some reason delim.empty()
@@ -2109,19 +2128,57 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned 
flags,
                                                m = at->currentMode();
                                        //lyxerr << "default creation: m2: " << 
m << endl;
                                        idx_type start = 0;
-                                       // this fails on \bigg[...\bigg]
-                                       //MathData opt;
-                                       //parse(opt, FLAG_OPTION, 
InsetMath::VERBATIM_MODE);
-                                       //if (!opt.empty()) {
-                                       //      start = 1;
-                                       //      at.nucleus()->cell(0) = opt;
-                                       //}
-                                       for (idx_type i = start; i < 
at->nargs(); ++i) {
-                                               parse(at.nucleus()->cell(i), 
FLAG_ITEM, m);
-                                               if (mode == 
InsetMath::MATH_MODE)
+                                       // The code for handling arguments of 
at does not work
+                                       // together with the optional argument 
handling, therefore
+                                       // we must not use the latter if 
at->nargs() > 0.
+                                       size_t optionals = 0;
+                                       if (is_user_macro && at->nargs() == 0 
&& buf) {
+                                               if (mode_ & Parse::TRACKMACRO) {
+                                                       
Buffer::UserMacroSet::const_iterator it =
+                                                               
buf->usermacros.find(t.cs());
+                                                       if (it != 
buf->usermacros.end())
+                                                               optionals = 
it->second;
+                                               } else {
+                                                       MacroData const * const 
user_macro =
+                                                               
buf->getMacro(t.cs(), false);
+                                                       if (user_macro)
+                                                               optionals = 
user_macro->optionals();
+
+                                               }
+                                       }
+                                       if (optionals > 0)
+                                       {
+                                               cell->push_back(at);
+                                               // Try to parse the optional 
arguments with FLAG_OPTION.
+                                               // Without this the end of the 
optional arg will not
+                                               // be handled correctly (bug 
8934).
+                                               // We must know the number of 
allowed optional arguments
+                                               // of the macro template. 
Otherwise user defined macros
+                                               // similar to big operators 
like \mybigg[...\mybigg]
+                                               // would not be parsed 
correctly.
+                                               for (size_t i = 0; i < 
optionals; ++i) {
+                                                       // We need to 
distinguish empty arguments []
+                                                       // and missing 
arguments, since this makes a
+                                                       // difference for some 
macros.
+                                                       MathData opt(buf);
                                                        skipSpaces();
+                                                       if (good() && 
nextToken().asInput() == "[") {
+                                                               parse(opt, 
FLAG_OPTION, m);
+                                                               // the optional 
arg will later be attached to the
+                                                               // macro by 
MathData::collectOptionalParameters()
+                                                               opt.insert(0, 
MathAtom(new InsetMathChar(buf, '[')));
+                                                               
opt.push_back(MathAtom(new InsetMathChar(buf, ']')));
+                                                               
cell->append(opt);
+                                                       }
+                                               }
+                                       } else {
+                                               for (idx_type i = start; i < 
at->nargs(); ++i) {
+                                                       
parse(at.nucleus()->cell(i), FLAG_ITEM, m);
+                                                       if (mode == 
InsetMath::MATH_MODE)
+                                                               skipSpaces();
+                                               }
+                                               cell->push_back(at);
                                        }
-                                       cell->push_back(at);
                                }
                        }
                }
diff --git a/status.24x b/status.24x
index 86896eaa8b..95fb1874af 100644
--- a/status.24x
+++ b/status.24x
@@ -50,6 +50,8 @@ What's new
 - Fix LaTeX output of formulas with a prime, a superscript and a subscripi 
   (bug 13004).
 
+- Fix problem when using DeclarePairedDelimiterX (bug 8934).
+
 
 * USER INTERFACE
 
-- 
lyx-cvs mailing list
[email protected]
https://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to