On Tue, Oct 27, 2009 at 03:20:57PM +0100, Jean-Marc Lasgouttes wrote:
> Enrico Forestieri <for...@lyx.org> writes:
> > This is difficult to achieve, though, as the user defined macros are
> > bound to buffers and the createInsetMath() function has no way to
> > know for what buffer it is creating a math inset. Solving this problem
> > entails a whole overhaul of mathed, most probably.
> 
> I would be curious to see how big the overhaul would be. Having the
> current user-defined macros not be part of the parser state is a very
> big mistake IMO. We could add a macrotable object (does this exist?) to
> the parser state and define a Parser::createInsetMath.

I have no idea how much work it requires. In the meantime, I put together
the attached quick&dirty patch for trunk to demonstrate the concept.
This fix is not acceptable, as it takes into account the user macros
defined in all buffers and not only the right one. However, if you load
only a single document it will work. For example, you can see that the
file attached to bug 6291 is correctly loaded (despite the mhchem \ce
macro).

> I am surprised that this bug has not been identified earlier.

I think it is because no real clash with macro names has occurred
until now. The mhchem package with its 2-letter-easy-to-clash-with
macro names simply evidenced this bug.

-- 
Enrico
Index: src/mathed/MathCompletionList.h
===================================================================
--- src/mathed/MathCompletionList.h     (revision 31763)
+++ src/mathed/MathCompletionList.h     (working copy)
@@ -13,6 +13,7 @@
 #define MATH_COMPLETIONLIST_H
 
 #include "CompletionList.h"
+#include "MacroTable.h"
 
 #include "support/docstring.h"
 
@@ -40,6 +41,9 @@ public:
        ///
        static void addToFavorites(docstring const & completion);
 
+       ///
+       static MacroNameSet all_user_locals;
+
 private:
        ///
        static std::vector<docstring> globals;
Index: src/mathed/MathFactory.cpp
===================================================================
--- src/mathed/MathFactory.cpp  (revision 31763)
+++ src/mathed/MathFactory.cpp  (working copy)
@@ -45,6 +45,7 @@
 #include "InsetMathXArrow.h"
 #include "InsetMathXYMatrix.h"
 #include "MacroTable.h"
+#include "MathCompletionList.h"
 #include "MathMacro.h"
 #include "MathMacroArgument.h"
 #include "MathParser.h"
@@ -308,6 +309,9 @@ MathAtom createInsetMath(char const * co
 
 MathAtom createInsetMath(docstring const & s)
 {
+       if (MathCompletionList::all_user_locals.count(s))
+               return MathAtom(new MathMacro(s));
+
        //lyxerr << "creating inset with name: '" << to_utf8(s) << '\'' << endl;
        latexkeys const * l = in_word_set(s);
        if (l) {
Index: src/mathed/MathParser.cpp
===================================================================
--- src/mathed/MathParser.cpp   (revision 31763)
+++ src/mathed/MathParser.cpp   (working copy)
@@ -59,6 +59,7 @@ following hack as starting point to writ
 #include "InsetMathSplit.h"
 #include "InsetMathSqrt.h"
 #include "InsetMathTabular.h"
+#include "MathCompletionList.h"
 #include "MathMacroTemplate.h"
 #include "MathFactory.h"
 #include "MathMacroArgument.h"
@@ -1053,6 +1054,8 @@ bool Parser::parse1(InsetMathGrid & grid
                        
                        cell->push_back(MathAtom(new MathMacroTemplate(name, 
nargs,
                                optionals, MacroTypeNewcommand, optionalValues, 
def, display)));
+                       MathCompletionList::all_user_locals.insert(name);
+                       lyxerr << "name: " << name << endl;
                        
                }
                
@@ -1750,7 +1753,7 @@ bool Parser::parse1(InsetMathGrid & grid
 
                else if (t.cs().size()) {
                        latexkeys const * l = in_word_set(t.cs());
-                       if (l) {
+                       if (l && 
!MathCompletionList::all_user_locals.count(t.cs())) {
                                if (l->inset == "big") {
                                        skipSpaces();
                                        docstring const delim = 
getToken().asInput();
@@ -1800,7 +1803,8 @@ bool Parser::parse1(InsetMathGrid & grid
 
                        else {
                                bool is_unicode_symbol = false;
-                               if (mode == InsetMath::TEXT_MODE) {
+                               if (mode == InsetMath::TEXT_MODE
+                                   && 
!MathCompletionList::all_user_locals.count(t.cs())) {
                                        int num_tokens = 0;
                                        docstring cmd = prevToken().asInput();
                                        CatCode cat = nextToken().cat();
Index: src/mathed/InsetMathNest.cpp
===================================================================
--- src/mathed/InsetMathNest.cpp        (revision 31763)
+++ src/mathed/InsetMathNest.cpp        (working copy)
@@ -2039,4 +2039,6 @@ std::string MathCompletionList::icon(siz
 
 std::vector<docstring> MathCompletionList::globals;
 
+MacroNameSet MathCompletionList::all_user_locals;
+
 } // namespace lyx
Index: src/Buffer.cpp
===================================================================
--- src/Buffer.cpp      (revision 31763)
+++ src/Buffer.cpp      (working copy)
@@ -74,6 +74,7 @@
 #include "insets/InsetText.h"
 
 #include "mathed/MacroTable.h"
+#include "mathed/MathCompletionList.h"
 #include "mathed/MathMacroTemplate.h"
 #include "mathed/MathSupport.h"
 
@@ -2671,8 +2672,10 @@ void Buffer::listMacroNames(MacroNameSet
        // loop over macro names
        Impl::NamePositionScopeMacroMap::iterator nameIt = d->macros.begin();
        Impl::NamePositionScopeMacroMap::iterator nameEnd = d->macros.end();
-       for (; nameIt != nameEnd; ++nameIt)
+       for (; nameIt != nameEnd; ++nameIt) {
                macros.insert(nameIt->first);
+               MathCompletionList::all_user_locals.insert(nameIt->first);
+       }
 
        // loop over children
        Impl::BufferPositionMap::iterator it = d->children_positions.begin();

Reply via email to