Backport latest changes about instant preview

* Fix typo causing to only account for the first char of a macro name
* Also check for macros as arguments of other macros
* Take into account macro redefinitions in the legacy route
* Take into account macros inside nested macro definitions
* Use the draft option for microtype instead of redefining \usepackage
* Make really sure to wait for previews after zoom changes

This is an amendment to previous commits, so no status line is needed.
This commit is contained in:
Enrico Forestieri 2015-06-21 19:23:18 +02:00
parent 501435345a
commit 93c0512ba2
4 changed files with 52 additions and 49 deletions

View File

@ -160,59 +160,33 @@ 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")
def_re = re.compile(r"(\\newcommandx|\\global\\long\\def)(\\[a-zA-Z]+)")
tmp = mkstemp()
in_user_preamble = 0
usepkg = 0
changed = 0
changed = False
macros = []
for line in open(latex_file, 'r').readlines():
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:
in_user_preamble = 1
elif enduserpreamble_re.search(line) != None:
in_user_preamble = 0
if usepackage_re.match(line) != None and in_user_preamble:
usepkg = 1
changed = 1
tmp.write("\\def\\t@a{microtype}\n")
tmp.write("\\let\\oldusepkg\\usepackage\n")
tmp.write("\\def\\usepackage{\\@ifnextchar[\\@usepkg{\\@usepkg[]}}\n")
tmp.write("\\def\\@usepkg[#1]#2{\\@ifnextchar[")
tmp.write("{\\@@usepkg[#1]{#2}}{\\@@usepkg[#1]{#2}[]}}\n")
tmp.write("\\def\@@usepkg[#1]#2[#3]{\\def\\t@b{#2}")
tmp.write("\\ifx\\t@a\\t@b\\else\\oldusepkg[#1]{#2}[#3]\\fi}\n")
tmp.write(line)
continue
match = def_re.match(line)
if match == None:
tmp.write(line)
continue
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)
if line.startswith("\\documentclass"):
match = documentclass_re.match(line)
if match != None:
changed = True
line = match.group(1) + match.group(3) + "\n"
if not pdf_output:
changed = True
line += "\\PassOptionsToPackage{draft}{microtype}\n"
else:
changed = 1
tmp.write("\\renewcommandx%s%s\n" % (match.group(2), match.group(3)))
match = def_re.match(line)
if match != None:
macroname = match.group(2)
if macroname in macros:
definecmd = match.group(1)
if definecmd == "\\newcommandx":
changed = True
line = line.replace(definecmd, "\\renewcommandx")
else:
macros.append(macroname)
tmp.write(line)
if changed:
copyfileobj(tmp, open(latex_file,"wb"), 1)

View File

@ -272,11 +272,13 @@ def write_metrics_info(metrics_info, metrics_file):
# Reads a .tex files and create an identical file but only with
# pages whose index is in pages_to_keep
def filter_pages(source_path, destination_path, pages_to_keep):
def_re = re.compile(r"(\\newcommandx|\\renewcommandx|\\global\\long\\def)(\\[a-zA-Z]+)")
source_file = open(source_path, "r")
destination_file = open(destination_path, "w")
page_index = 0
skip_page = False
macros = []
for line in source_file:
# We found a new page
if line.startswith("\\begin{preview}"):
@ -285,6 +287,14 @@ def filter_pages(source_path, destination_path, pages_to_keep):
skip_page = page_index not in pages_to_keep
if not skip_page:
match = def_re.match(line)
if match != None:
definecmd = match.group(1)
macroname = match.group(2)
if not macroname in macros:
macros.append(macroname)
if definecmd == "\\renewcommandx":
line = line.replace(definecmd, "\\newcommandx")
destination_file.write(line)
# End of a page, we reset the skip_page bool

View File

@ -253,6 +253,8 @@ private:
mutable int font_scaling_factor_;
///
QTimer * delay_refresh_;
///
bool finished_generating_;
/// We don't own this
static lyx::Converter const * pconverter_;
@ -401,7 +403,7 @@ namespace lyx {
namespace graphics {
PreviewLoader::Impl::Impl(PreviewLoader & p, Buffer const & b)
: parent_(p), buffer_(b)
: parent_(p), buffer_(b), finished_generating_(true)
{
font_scaling_factor_ = buffer_.isExporting()
? int(75.0 * buffer_.params().html_math_img_scale)
@ -441,7 +443,7 @@ PreviewLoader::Impl::preview(string const & latex_snippet) const
delay_refresh_->start(1000);
}
// Don't try to access the cache until we are done.
if (delay_refresh_->isActive())
if (delay_refresh_->isActive() || !finished_generating_)
return 0;
Cache::const_iterator it = cache_.find(latex_snippet);
return (it == cache_.end()) ? 0 : it->second.get();
@ -453,10 +455,16 @@ void PreviewLoader::Impl::refreshPreviews()
font_scaling_factor_ = buffer_.isExporting()
? int(75.0 * buffer_.params().html_math_img_scale)
: int(0.01 * lyxrc.dpi * lyxrc.zoom * lyxrc.preview_scale_factor);
// Reschedule refresh until the previous process completed.
if (!finished_generating_) {
delay_refresh_->start(1000);
return;
}
Cache::const_iterator cit = cache_.begin();
Cache::const_iterator cend = cache_.end();
while (cit != cend)
parent_.remove((cit++)->first);
finished_generating_ = false;
buffer_.updatePreviews();
}
@ -751,6 +759,7 @@ void PreviewLoader::Impl::finishedGenerating(pid_t pid, int retval)
for (; nit != nend; ++nit) {
imageReady(*nit->get());
}
finished_generating_ = true;
}

View File

@ -37,6 +37,7 @@
#include "LyXRC.h"
#include "MacroTable.h"
#include "MathMacro.h"
#include "MathMacroTemplate.h"
#include "output_xhtml.h"
#include "Paragraph.h"
#include "ParIterator.h"
@ -634,11 +635,15 @@ void InsetMathHull::usedMacros(MathData const & md, DocIterator const & pos,
for (size_t i = 0; i < md.size(); ++i) {
MathMacro const * mi = md[i].nucleus()->asMacro();
MathMacroTemplate const * mt = md[i].nucleus()->asMacroTemplate();
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) {
// Look for macros in the arguments of this macro.
for (idx_type idx = 0; idx < mi->nargs(); ++idx)
usedMacros(mi->cell(idx), pos, macros, defs);
// 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.
@ -646,6 +651,7 @@ void InsetMathHull::usedMacros(MathData const & md, DocIterator const & pos,
if (macros.find(name) == end)
continue;
macros.erase(name);
// Look for macros in the definition of this macro.
MathData ar(pos.buffer());
MacroData const * data =
pos.buffer()->getMacro(name, pos, true);
@ -657,6 +663,10 @@ void InsetMathHull::usedMacros(MathData const & md, DocIterator const & pos,
asArray(data->definition(), ar);
}
usedMacros(ar, pos, macros, defs);
} else if (mt) {
MathData ar(pos.buffer());
asArray(mt->definition(), ar);
usedMacros(ar, pos, macros, defs);
} else if (si) {
if (!si->nuc().empty())
usedMacros(si->nuc(), pos, macros, defs);