]> git.lyx.org Git - features.git/commitdiff
Replacement for commits bc47054b and ad0d0f6d
authorEnrico Forestieri <forenr@lyx.org>
Sun, 14 Jun 2015 16:10:29 +0000 (18:10 +0200)
committerEnrico Forestieri <forenr@lyx.org>
Sun, 14 Jun 2015 16:10:29 +0000 (18:10 +0200)
The strategy adopted in bc47054b had some drawbacks related to the way
instant preview snippets are generated. See the subthread starting at
http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg187916.html
for details.

The strategy adopted in this commit is that of adding macro definitions
only for the macros actually used in a preview snippet, independently
of whether some macro was already used in a previous snippet. In this way
the snippets don't need to be changed according to whether they are
compiled as a whole or separately from each other. This fact was causing
the regeneration of a preview snippet whenever the cursor entered the
corresponding inset, even if the generated image would have not changed.
The problem of defining or redefining a macro is taken care by the
python scripts.

lib/scripts/lyxpreview2bitmap.py
src/insets/InsetPreview.cpp
src/mathed/InsetMath.h
src/mathed/InsetMathFrac.h
src/mathed/InsetMathHull.cpp
src/mathed/InsetMathHull.h

index 3e055429eb60f3edfac025ba688e46d386269eb8..a7d76236fba969b982b648e2a3859bf81db0ead3 100755 (executable)
@@ -160,27 +160,23 @@ def extract_metrics_info(dvipng_stdout):
 
 def fix_latex_file(latex_file, pdf_output):
     documentclass_re = re.compile("(\\\\documentclass\[)(1[012]pt,?)(.+)")
+    def_re = re.compile(r"(\\newcommandx|\\global\\long\\def)(\\[a-zA-Z])(.+)")
     usepackage_re = re.compile("\\\\usepackage")
     userpreamble_re = re.compile("User specified LaTeX commands")
     enduserpreamble_re = re.compile("\\\\makeatother")
-    begindoc_re = re.compile("\\\\begin\{document\}")
 
     tmp = mkstemp()
 
-    in_doc_body = 0
     in_user_preamble = 0
     usepkg = 0
     changed = 0
+    macros = []
     for line in open(latex_file, 'r').readlines():
-        if in_doc_body:
-            if changed:
-                tmp.write(line)
-                continue
-            else:
-                break
-
-        if begindoc_re.match(line) != None:
-            in_doc_body = 1
+        match = documentclass_re.match(line)
+        if match != None:
+            changed = 1
+            tmp.write("%s%s\n" % (match.group(1), match.group(3)))
+            continue
 
         if not pdf_output and not usepkg:
             if userpreamble_re.search(line) != None:
@@ -200,13 +196,23 @@ def fix_latex_file(latex_file, pdf_output):
                 tmp.write(line)
                 continue
 
-        match = documentclass_re.match(line)
+        match = def_re.match(line)
         if match == None:
             tmp.write(line)
             continue
 
-        changed = 1
-        tmp.write("%s%s\n" % (match.group(1), match.group(3)))
+        macroname = match.group(2)
+        if not macroname in macros:
+            macros.append(macroname)
+            tmp.write(line)
+            continue
+
+        definecmd = match.group(1)
+        if definecmd == "\\global\\long\\def":
+            tmp.write(line)
+        else:
+            changed = 1
+            tmp.write("\\renewcommandx%s%s\n" % (match.group(2), match.group(3)))
 
     if changed:
         copyfileobj(tmp, open(latex_file,"wb"), 1)
@@ -426,8 +432,8 @@ def main(argv):
     progress("Preprocess through lilypond-book: %s" % lilypond)
     progress("Altering the latex file for font size and colors")
 
-    # Omit font size specification in latex file and make sure that
-    # the microtype package doesn't cause issues in dvi mode.
+    # Omit font size specification in latex file and make sure that multiple
+    # defined macros and the microtype package don't cause issues.
     fix_latex_file(latex_file, pdf_output)
 
     if lilypond:
index 1b3456eac947f3e3d415e52a4afdb28fdefd023b..b8fd0aea8c3dda430b57567aae95bc8bd45fb51b 100644 (file)
@@ -24,6 +24,9 @@
 
 #include "graphics/PreviewImage.h"
 
+#include "mathed/InsetMathHull.h"
+#include "mathed/MacroTable.h"
+
 #include <sstream>
 
 using namespace std;
@@ -72,7 +75,32 @@ void InsetPreview::preparePreview(DocIterator const & pos) const
        otexstream os(str, texrow);
        OutputParams runparams(&pos.buffer()->params().encoding());
        latex(os, runparams);
-       docstring const snippet = str.str();
+
+       // collect macros at this position
+       MacroNameSet macros;
+       pos.buffer()->listMacroNames(macros);
+
+       // look for math insets and collect definitions for the used macros
+       MacroNameSet defs;
+       DocIterator dit = doc_iterator_begin(pos.buffer(), this);
+       DocIterator const dend = doc_iterator_end(pos.buffer(), this);
+       if (!dit.nextInset())
+               dit.forwardInset();
+       for (; dit != dend; dit.forwardInset()) {
+               InsetMath * im = dit.nextInset()->asInsetMath();
+               InsetMathHull * hull = im ? im->asHullInset() : 0;
+               if (!hull)
+                       continue;
+               for (idx_type idx = 0; idx < hull->nargs(); ++idx)
+                       hull->usedMacros(hull->cell(idx), pos, macros, defs);
+       }
+       MacroNameSet::iterator it = defs.begin();
+       MacroNameSet::iterator end = defs.end();
+       docstring macro_preamble;
+       for (; it != end; ++it)
+               macro_preamble.append(*it);
+
+       docstring const snippet = macro_preamble + str.str();
        preview_->addPreview(snippet, *pos.buffer());
 }
 
index 325f79ae9e200eab0153706a4320a1accd1385b4..917011fbb3aae411f1f2cad2d6b4908e92138650 100644 (file)
@@ -58,6 +58,7 @@ class InsetMathAMSArray;
 class InsetMathBrace;
 class InsetMathChar;
 class InsetMathDelim;
+class InsetMathFracBase;
 class InsetMathFrac;
 class InsetMathFont;
 class InsetMathGrid;
@@ -129,6 +130,8 @@ public:
        virtual InsetMathChar const     * asCharInset() const     { return 0; }
        virtual InsetMathDelim          * asDelimInset()          { return 0; }
        virtual InsetMathDelim const    * asDelimInset() const    { return 0; }
+       virtual InsetMathFracBase       * asFracBaseInset()       { return 0; }
+       virtual InsetMathFracBase const * asFracBaseInset() const { return 0; }
        virtual InsetMathFrac           * asFracInset()           { return 0; }
        virtual InsetMathFrac const     * asFracInset() const     { return 0; }
        virtual InsetMathFont           * asFontInset()           { return 0; }
index 5030730647db540a4f0047f8d875be434c0934ff..c030c8a51a0203f15b2429b64988f345a744e2e7 100644 (file)
@@ -30,6 +30,10 @@ public:
        bool idxBackward(Cursor &) const { return false; }
        ///
        bool idxForward(Cursor &) const { return false; }
+       ///
+       InsetMathFracBase * asFracBaseInset() { return this; }
+       ///
+       InsetMathFracBase const * asFracBaseInset() const { return this; }
 };
 
 
index f8e68ba132c5cfbcb448619855cdaf92ecaf2f16..4e18b72420e16022ae62a1d61e2ff95fa85df1e2 100644 (file)
 
 #include "InsetMathChar.h"
 #include "InsetMathColor.h"
+#include "InsetMathFrac.h"
+#include "InsetMathGrid.h"
+#include "InsetMathNest.h"
+#include "InsetMathScript.h"
 #include "MathExtern.h"
 #include "MathFactory.h"
 #include "MathStream.h"
@@ -32,6 +36,7 @@
 #include "LaTeXFeatures.h"
 #include "LyXRC.h"
 #include "MacroTable.h"
+#include "MathMacro.h"
 #include "output_xhtml.h"
 #include "Paragraph.h"
 #include "ParIterator.h"
@@ -623,6 +628,55 @@ void InsetMathHull::addPreview(DocIterator const & inset_pos,
 }
 
 
+void InsetMathHull::usedMacros(MathData const & md, DocIterator const & pos,
+                               MacroNameSet & macros, MacroNameSet & defs) const
+{
+       MacroNameSet::iterator const end = macros.end();
+
+       for (size_t i = 0; i < md.size(); ++i) {
+               MathMacro const * mi = md[i].nucleus()->asMacro();
+               InsetMathScript const * si = md[i].nucleus()->asScriptInset();
+               InsetMathFracBase const * fi = md[i].nucleus()->asFracBaseInset();
+               InsetMathGrid const * gi = md[i].nucleus()->asGridInset();
+               InsetMathNest const * ni = md[i].nucleus()->asNestInset();
+               if (mi) {
+                       // Make sure this is a macro defined in the document
+                       // (as we also spot the macros in the symbols file)
+                       // or that we have not already accounted for it.
+                       docstring const name = mi->name();
+                       if (macros.find(name) == end)
+                               continue;
+                       macros.erase(name);
+                       MathData ar(pos.buffer());
+                       MacroData const * data =
+                               pos.buffer()->getMacro(name, pos, true);
+                       if (data) {
+                               odocstringstream macro_def;
+                               data->write(macro_def, true);
+                               macro_def << endl;
+                               defs.insert(macro_def.str());
+                               asArray(data->definition(), ar);
+                       }
+                       usedMacros(ar, pos, macros, defs);
+               } else if (si) {
+                       if (!si->nuc().empty())
+                               usedMacros(si->nuc(), pos, macros, defs);
+                       if (si->hasDown())
+                               usedMacros(si->down(), pos, macros, defs);
+                       if (si->hasUp())
+                               usedMacros(si->up(), pos, macros, defs);
+               } else if (fi || gi) {
+                       idx_type nidx = fi ? fi->nargs() : gi->nargs();
+                       for (idx_type idx = 0; idx < nidx; ++idx)
+                               usedMacros(fi ? fi->cell(idx) : gi->cell(idx),
+                                          pos, macros, defs);
+               } else if (ni) {
+                       usedMacros(ni->cell(0), pos, macros, defs);
+               }
+       }
+}
+
+
 void InsetMathHull::preparePreview(DocIterator const & pos,
                                    bool forexport) const
 {
@@ -636,16 +690,17 @@ void InsetMathHull::preparePreview(DocIterator const & pos,
        // collect macros at this position
        MacroNameSet macros;
        buffer->listMacroNames(macros);
-       MacroNameSet::iterator it = macros.begin();
-       MacroNameSet::iterator end = macros.end();
-       odocstringstream macro_preamble;
-       for (; it != end; ++it) {
-               MacroData const * data = buffer->getMacro(*it, pos, true);
-               if (data) {
-                       data->write(macro_preamble, true);
-                       macro_preamble << endl;
-               }
-       }
+
+       // collect definitions only for the macros used in this inset
+       MacroNameSet defs;
+       for (idx_type idx = 0; idx < nargs(); ++idx)
+               usedMacros(cell(idx), pos, macros, defs);
+
+       MacroNameSet::iterator it = defs.begin();
+       MacroNameSet::iterator end = defs.end();
+       docstring macro_preamble;
+       for (; it != end; ++it)
+               macro_preamble.append(*it);
 
        docstring setcnt;
        if (forexport && haveNumbers()) {
@@ -668,8 +723,7 @@ void InsetMathHull::preparePreview(DocIterator const & pos,
                                          '{' + convert<docstring>(num) + '}';
                }
        }
-       docstring const snippet = macro_preamble.str() +
-           setcnt + latexString(*this);
+       docstring const snippet = macro_preamble + setcnt + latexString(*this);
        LYXERR(Debug::MACROS, "Preview snippet: " << snippet);
        preview_->addPreview(snippet, *buffer, forexport);
 }
index 55275371fd796dc7f4cb33fe007ad4fd03bf48bc..5462acd8ef9ab961ddf053569743e4da0dd00961 100644 (file)
@@ -23,6 +23,7 @@
 namespace lyx {
 
 class InsetLabel;
+class MacroNameSet;
 class ParConstIterator;
 class RenderPreview;
 
@@ -162,6 +163,9 @@ public:
        /// Recreates the preview if preview is enabled.
        void reloadPreview(DocIterator const & pos) const;
        ///
+       void usedMacros(MathData const & md, DocIterator const & pos,
+                       MacroNameSet & macros, MacroNameSet & defs) const;
+       ///
        void initUnicodeMath() const;
 
        ///