From acba847649f89b63a7762a227a3aac2a12fd6b75 Mon Sep 17 00:00:00 2001 From: Enrico Forestieri Date: Tue, 23 Apr 2019 21:06:12 +0200 Subject: [PATCH] Amend [54147a71/lyxgit] If none of the optional arguments of a macro is used, there is no following '[' after the macro name. Unfortunately, at loading time the macro machinery is still not initialized, so the optionals() member of InsetMathMacro is unusable. Hence, we have to track the creation of macros with optionals as already we do for all macros. The collected information is only used at loading time, because the macros are dynamic and they may loose or acquire optional args. Fixes the particular case reported at #11552. --- src/Buffer.h | 3 +++ src/mathed/MathParser.cpp | 29 +++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/Buffer.h b/src/Buffer.h index f1bd1f5e79..7fc9e4808c 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -621,6 +621,9 @@ public: typedef std::set UserMacroSet; mutable UserMacroSet usermacros; + /// Collect user macro names with optional parameters at loading time + mutable UserMacroSet usermacros_with_opts; + /// Replace the inset contents for insets which InsetCode is equal /// to the passed \p inset_code. void changeRefsIfUnique(docstring const & from, docstring const & to); diff --git a/src/mathed/MathParser.cpp b/src/mathed/MathParser.cpp index c41a6cfbd7..470731fc8e 100644 --- a/src/mathed/MathParser.cpp +++ b/src/mathed/MathParser.cpp @@ -946,13 +946,28 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, parse(ar, FLAG_BRACE_LAST, mode); // do not create a BraceInset if they were written by LyX // this helps to keep the annoyance of "a choose b" to a minimum + InsetMathMacro const * ma; InsetMathBrace const * mb; InsetMathChar const * mc; for (size_type i = 0; i < ar.size(); ++i) { mb = ar[i]->asBraceInset(); - mc = mb && mb->cell(0).size() > 1 && mb->cell(0)[0]->asMacro() + ma = mb && mb->cell(0).size() + ? mb->cell(0)[0]->asMacro() : 0; + mc = ma && mb && mb->cell(0).size() > 1 ? mb->cell(0)[1]->asCharInset(): 0; - if (mc && mc->getChar() == '[') { + bool has_opts = mc && mc->getChar() == '['; + // If this is a macro, it may have optional + // arguments, even if only defaults are used. + // In this case, there is no following '['. + if (!has_opts && ma && buf) { + if (mode_ & Parse::TRACKMACRO) + has_opts = buf->usermacros_with_opts.count(ma->name()); + else { + MacroData const * md = buf->getMacro(ma->name(), false); + has_opts = md && md->optionals(); + } + } + if (has_opts) { // Remove the BraceInset around a macro // with optional arguments. It will be // automatically reinserted on write. @@ -1149,8 +1164,11 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, name, nargs, optionals, MacroTypeNewcommand, optionalValues, def, display))); - if (buf && (mode_ & Parse::TRACKMACRO)) + if (buf && (mode_ & Parse::TRACKMACRO)) { buf->usermacros.insert(name); + if (optionals) + buf->usermacros_with_opts.insert(name); + } } else if (t.cs() == "newcommandx" || @@ -1270,8 +1288,11 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, name, nargs, optionals, MacroTypeNewcommandx, optionalValues, def, display))); - if (buf && (mode_ & Parse::TRACKMACRO)) + if (buf && (mode_ & Parse::TRACKMACRO)) { buf->usermacros.insert(name); + if (optionals) + buf->usermacros_with_opts.insert(name); + } } else if (t.cs() == "(") { -- 2.39.2