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:
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)
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:
#include "graphics/PreviewImage.h"
+#include "mathed/InsetMathHull.h"
+#include "mathed/MacroTable.h"
+
#include <sstream>
using namespace std;
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());
}
class InsetMathBrace;
class InsetMathChar;
class InsetMathDelim;
+class InsetMathFracBase;
class InsetMathFrac;
class InsetMathFont;
class InsetMathGrid;
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; }
bool idxBackward(Cursor &) const { return false; }
///
bool idxForward(Cursor &) const { return false; }
+ ///
+ InsetMathFracBase * asFracBaseInset() { return this; }
+ ///
+ InsetMathFracBase const * asFracBaseInset() const { return this; }
};
#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"
#include "LaTeXFeatures.h"
#include "LyXRC.h"
#include "MacroTable.h"
+#include "MathMacro.h"
#include "output_xhtml.h"
#include "Paragraph.h"
#include "ParIterator.h"
}
+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
{
// 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()) {
'{' + 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);
}
namespace lyx {
class InsetLabel;
+class MacroNameSet;
class ParConstIterator;
class RenderPreview;
/// 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;
///