Replacement for commits bc47054b and ad0d0f6d

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.
This commit is contained in:
Enrico Forestieri 2015-06-14 18:10:29 +02:00
parent bdec44d614
commit 11c2b7792c
6 changed files with 128 additions and 29 deletions

View File

@ -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:

View 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());
}

View 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; }

View 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; }
};

View File

@ -14,6 +14,10 @@
#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);
}

View 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;
///