mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-29 13:04:58 +00:00
TexRow for InPreamble
This enables error reporting for the preamble, provided the preamble is written using the new InPreamble layouts. In the future, I find it preferable to deprecate the usual preamble in favour of InPreamble layouts rather than implementing error reporting for the usual preamble. This requires some improvements to code editing in the buffer view first (line breaking behaviour, syntax highlighting).
This commit is contained in:
parent
1b4f5970a4
commit
1f6c451ee3
@ -1902,8 +1902,6 @@ void Buffer::writeLaTeXSource(otexstream & os,
|
||||
|
||||
} // output_preamble
|
||||
|
||||
os.texrow().start(paragraphs().begin()->id(), 0);
|
||||
|
||||
LYXERR(Debug::INFO, "preamble finished, now the body.");
|
||||
|
||||
// the real stuff
|
||||
@ -2088,7 +2086,7 @@ void Buffer::writeLyXHTMLSource(odocstream & os,
|
||||
if (!styles.empty())
|
||||
os << "\n<!-- Text Class Preamble -->\n" << styles << '\n';
|
||||
|
||||
styles = features.getPreambleSnippets();
|
||||
styles = features.getPreambleSnippets().str;
|
||||
if (!styles.empty())
|
||||
os << "\n<!-- Preamble Snippets -->\n" << styles << '\n';
|
||||
|
||||
|
@ -1994,33 +1994,36 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
|
||||
os << "\\usepackage[dot]{bibtopic}\n";
|
||||
|
||||
// Will be surrounded by \makeatletter and \makeatother when not empty
|
||||
docstring atlyxpreamble;
|
||||
otexstringstream atlyxpreamble;
|
||||
|
||||
// Some macros LyX will need
|
||||
docstring tmppreamble(features.getMacros());
|
||||
|
||||
if (!tmppreamble.empty())
|
||||
atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
|
||||
{
|
||||
TexString tmppreamble = features.getMacros();
|
||||
if (!tmppreamble.str.empty())
|
||||
atlyxpreamble << "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
|
||||
"LyX specific LaTeX commands.\n"
|
||||
+ tmppreamble + '\n';
|
||||
|
||||
<< move(tmppreamble)
|
||||
<< '\n';
|
||||
}
|
||||
// the text class specific preamble
|
||||
tmppreamble = features.getTClassPreamble();
|
||||
{
|
||||
docstring tmppreamble = features.getTClassPreamble();
|
||||
if (!tmppreamble.empty())
|
||||
atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
|
||||
atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
|
||||
"Textclass specific LaTeX commands.\n"
|
||||
+ tmppreamble + '\n';
|
||||
|
||||
<< tmppreamble
|
||||
<< '\n';
|
||||
}
|
||||
// suppress date if selected
|
||||
// use \@ifundefined because we cannot be sure that every document class
|
||||
// has a \date command
|
||||
if (suppress_date)
|
||||
atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
|
||||
atlyxpreamble << "\\@ifundefined{date}{}{\\date{}}\n";
|
||||
|
||||
/* the user-defined preamble */
|
||||
if (!containsOnly(preamble, " \n\t")) {
|
||||
// FIXME UNICODE
|
||||
atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
|
||||
atlyxpreamble << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
|
||||
"User specified LaTeX commands.\n";
|
||||
|
||||
// Check if the user preamble contains uncodable glyphs
|
||||
@ -2064,7 +2067,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
|
||||
"preamble code accordingly."),
|
||||
uncodable_glyphs));
|
||||
}
|
||||
atlyxpreamble += user_preamble.str() + '\n';
|
||||
atlyxpreamble << user_preamble.str() << '\n';
|
||||
}
|
||||
|
||||
// footmisc must be loaded after setspace
|
||||
@ -2072,7 +2075,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
|
||||
// preamble. For that reason we also pass the options via
|
||||
// \PassOptionsToPackage in getPreamble() and not here.
|
||||
if (features.mustProvide("footmisc"))
|
||||
atlyxpreamble += "\\usepackage{footmisc}\n";
|
||||
atlyxpreamble << "\\usepackage{footmisc}\n";
|
||||
|
||||
// subfig loads internally the LaTeX package "caption". As
|
||||
// caption is a very popular package, users will load it in
|
||||
@ -2084,11 +2087,10 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
|
||||
// koma's own caption commands are used instead of caption. We
|
||||
// use \PassOptionsToPackage here because the user could have
|
||||
// already loaded subfig in the preamble.
|
||||
if (features.mustProvide("subfig")) {
|
||||
atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
|
||||
if (features.mustProvide("subfig"))
|
||||
atlyxpreamble << "\\@ifundefined{showcaptionsetup}{}{%\n"
|
||||
" \\PassOptionsToPackage{caption=false}{subfig}}\n"
|
||||
"\\usepackage{subfig}\n";
|
||||
}
|
||||
|
||||
// Itemize bullet settings need to be last in case the user
|
||||
// defines their own bullets that use a package included
|
||||
@ -2123,13 +2125,12 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
|
||||
}
|
||||
|
||||
if (!bullets_def.empty())
|
||||
atlyxpreamble += bullets_def + "}\n\n";
|
||||
atlyxpreamble << bullets_def << "}\n\n";
|
||||
|
||||
if (!atlyxpreamble.empty()) {
|
||||
if (!atlyxpreamble.empty())
|
||||
os << "\n\\makeatletter\n"
|
||||
<< atlyxpreamble
|
||||
<< atlyxpreamble.release()
|
||||
<< "\\makeatother\n\n";
|
||||
}
|
||||
|
||||
// We try to load babel late, in case it interferes with other packages.
|
||||
// Jurabib, hyperref, varioref, bicaption and listings (bug 8995) have to be
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "Lexer.h"
|
||||
#include "LyXRC.h"
|
||||
#include "TextClass.h"
|
||||
#include "TexRow.h"
|
||||
#include "texstream.h"
|
||||
|
||||
#include "insets/InsetLayout.h"
|
||||
|
||||
@ -586,26 +588,62 @@ bool LaTeXFeatures::isAvailable(string const & name)
|
||||
}
|
||||
|
||||
|
||||
void LaTeXFeatures::addPreambleSnippet(docstring const & preamble,
|
||||
bool allowdupes)
|
||||
namespace {
|
||||
|
||||
void addSnippet(std::list<TexString> & list, TexString ts, bool allow_dupes)
|
||||
{
|
||||
SnippetList::const_iterator begin = preamble_snippets_.begin();
|
||||
SnippetList::const_iterator end = preamble_snippets_.end();
|
||||
if (allowdupes || find(begin, end, preamble) == end)
|
||||
preamble_snippets_.push_back(preamble);
|
||||
if (allow_dupes ||
|
||||
// test the absense of duplicates, i.e. elements with same str
|
||||
none_of(list.begin(), list.end(), [&](TexString const & ts2){
|
||||
return ts.str == ts2.str;
|
||||
})
|
||||
)
|
||||
list.push_back(move(ts));
|
||||
}
|
||||
|
||||
|
||||
TexString getSnippets(std::list<TexString> const & list)
|
||||
{
|
||||
otexstringstream snip;
|
||||
for (TexString const & ts : list)
|
||||
snip << TexString(ts) << '\n';
|
||||
return snip.release();
|
||||
}
|
||||
|
||||
} //anon namespace
|
||||
|
||||
|
||||
void LaTeXFeatures::addPreambleSnippet(TexString ts, bool allow_dupes)
|
||||
{
|
||||
addSnippet(preamble_snippets_, move(ts), allow_dupes);
|
||||
}
|
||||
|
||||
|
||||
void LaTeXFeatures::addPreambleSnippet(docstring const & str, bool allow_dupes)
|
||||
{
|
||||
addSnippet(preamble_snippets_, TexString(str), allow_dupes);
|
||||
}
|
||||
|
||||
|
||||
void LaTeXFeatures::addCSSSnippet(std::string const & snippet)
|
||||
{
|
||||
docstring const u_snippet = from_ascii(snippet);
|
||||
SnippetList::const_iterator begin = css_snippets_.begin();
|
||||
SnippetList::const_iterator end = css_snippets_.end();
|
||||
if (find(begin, end, u_snippet) == end)
|
||||
css_snippets_.push_back(u_snippet);
|
||||
addSnippet(css_snippets_, TexString(from_ascii(snippet)), false);
|
||||
}
|
||||
|
||||
|
||||
TexString LaTeXFeatures::getPreambleSnippets() const
|
||||
{
|
||||
return getSnippets(preamble_snippets_);
|
||||
}
|
||||
|
||||
|
||||
docstring LaTeXFeatures::getCSSSnippets() const
|
||||
{
|
||||
return getSnippets(css_snippets_).str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LaTeXFeatures::useFloat(string const & name, bool subfloat)
|
||||
{
|
||||
if (!usedFloats_[name])
|
||||
@ -1151,31 +1189,9 @@ string const LaTeXFeatures::getPackages() const
|
||||
}
|
||||
|
||||
|
||||
docstring LaTeXFeatures::getPreambleSnippets() const
|
||||
TexString LaTeXFeatures::getMacros() const
|
||||
{
|
||||
odocstringstream snip;
|
||||
SnippetList::const_iterator pit = preamble_snippets_.begin();
|
||||
SnippetList::const_iterator pend = preamble_snippets_.end();
|
||||
for (; pit != pend; ++pit)
|
||||
snip << *pit << '\n';
|
||||
return snip.str();
|
||||
}
|
||||
|
||||
|
||||
docstring LaTeXFeatures::getCSSSnippets() const
|
||||
{
|
||||
odocstringstream snip;
|
||||
SnippetList::const_iterator pit = css_snippets_.begin();
|
||||
SnippetList::const_iterator pend = css_snippets_.end();
|
||||
for (; pit != pend; ++pit)
|
||||
snip << *pit << '\n';
|
||||
return snip.str();
|
||||
}
|
||||
|
||||
|
||||
docstring const LaTeXFeatures::getMacros() const
|
||||
{
|
||||
odocstringstream macros;
|
||||
otexstringstream macros;
|
||||
|
||||
if (!preamble_snippets_.empty()) {
|
||||
macros << '\n';
|
||||
@ -1319,7 +1335,7 @@ docstring const LaTeXFeatures::getMacros() const
|
||||
macros << changetracking_dvipost_def;
|
||||
|
||||
if (mustProvide("ct-xcolor-ulem")) {
|
||||
streamsize const prec = macros.precision(2);
|
||||
streamsize const prec = macros.os().precision(2);
|
||||
|
||||
RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
|
||||
macros << "\\providecolor{lyxadded}{rgb}{"
|
||||
@ -1329,7 +1345,7 @@ docstring const LaTeXFeatures::getMacros() const
|
||||
macros << "\\providecolor{lyxdeleted}{rgb}{"
|
||||
<< cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
|
||||
|
||||
macros.precision(prec);
|
||||
macros.os().precision(prec);
|
||||
|
||||
if (isRequired("hyperref"))
|
||||
macros << changetracking_xcolor_ulem_hyperref_def;
|
||||
@ -1343,7 +1359,7 @@ docstring const LaTeXFeatures::getMacros() const
|
||||
if (mustProvide("rtloutputdblcol"))
|
||||
macros << rtloutputdblcol_def;
|
||||
|
||||
return macros.str();
|
||||
return macros.release();
|
||||
}
|
||||
|
||||
|
||||
@ -1755,7 +1771,7 @@ void LaTeXFeatures::showStruct() const
|
||||
{
|
||||
lyxerr << "LyX needs the following commands when LaTeXing:"
|
||||
<< "\n***** Packages:" << getPackages()
|
||||
<< "\n***** Macros:" << to_utf8(getMacros())
|
||||
<< "\n***** Macros:" << to_utf8(getMacros().str)
|
||||
<< "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
|
||||
<< "\n***** done." << endl;
|
||||
}
|
||||
@ -1779,7 +1795,7 @@ BufferParams const & LaTeXFeatures::bufferParams() const
|
||||
}
|
||||
|
||||
|
||||
void LaTeXFeatures::getFloatDefinitions(odocstream & os) const
|
||||
void LaTeXFeatures::getFloatDefinitions(otexstream & os) const
|
||||
{
|
||||
FloatList const & floats = params_.documentClass().floats();
|
||||
|
||||
|
@ -27,6 +27,7 @@ class Buffer;
|
||||
class BufferParams;
|
||||
class InsetLayout;
|
||||
class Language;
|
||||
class TexString;
|
||||
|
||||
/** The packages and commands that a buffer needs. This class
|
||||
* contains a list<string>. Each of the LaTeX packages that a buffer needs
|
||||
@ -60,7 +61,7 @@ public:
|
||||
/// The packages needed by the document
|
||||
std::string const getPackages() const;
|
||||
/// The macros definitions needed by the document
|
||||
docstring const getMacros() const;
|
||||
TexString getMacros() const;
|
||||
/// Extra preamble code before babel is called
|
||||
docstring const getBabelPresettings() const;
|
||||
/// Extra preamble code after babel is called
|
||||
@ -84,13 +85,15 @@ public:
|
||||
/// Include a file for use with the SGML entities
|
||||
void includeFile(docstring const & key, std::string const & name);
|
||||
/// The float definitions.
|
||||
void getFloatDefinitions(odocstream & os) const;
|
||||
void getFloatDefinitions(otexstream & os) const;
|
||||
/// Print requirements to lyxerr
|
||||
void showStruct() const;
|
||||
///
|
||||
/// Add preamble snippet with TexRow information
|
||||
void addPreambleSnippet(TexString snippet, bool allowdupes = false);
|
||||
/// Add preamble snippet without TexRow information
|
||||
void addPreambleSnippet(docstring const & snippet, bool allowdupes = false);
|
||||
///
|
||||
docstring getPreambleSnippets() const;
|
||||
TexString getPreambleSnippets() const;
|
||||
///
|
||||
void addCSSSnippet(std::string const &);
|
||||
///
|
||||
@ -174,7 +177,7 @@ private:
|
||||
///
|
||||
Features features_;
|
||||
/// Static preamble bits, from external templates, or anywhere else
|
||||
typedef std::list<docstring> SnippetList;
|
||||
typedef std::list<TexString> SnippetList;
|
||||
///
|
||||
SnippetList preamble_snippets_;
|
||||
///
|
||||
|
@ -1386,8 +1386,7 @@ void Paragraph::Private::validate(LaTeXFeatures & features) const
|
||||
// switching machinery of odocstream. Therefore the
|
||||
// output is wrong if this paragraph contains content
|
||||
// that needs to switch encoding.
|
||||
odocstringstream ods;
|
||||
otexstream os(ods);
|
||||
otexstringstream os;
|
||||
if (is_command) {
|
||||
os << '\\' << from_ascii(layout_->latexname());
|
||||
// we have to provide all the optional arguments here, even though
|
||||
@ -1400,19 +1399,21 @@ void Paragraph::Private::validate(LaTeXFeatures & features) const
|
||||
}
|
||||
os << from_ascii(layout_->latexparam());
|
||||
}
|
||||
docstring::size_type const length = ods.str().length();
|
||||
size_t const length = os.length();
|
||||
// this will output "{" at the beginning, but not at the end
|
||||
owner_->latex(bp, f, os, features.runparams(), 0, -1, true);
|
||||
if (ods.str().length() > length) {
|
||||
if (os.length() > length) {
|
||||
if (is_command) {
|
||||
ods << '}';
|
||||
// FIXME: why does it has to be os.os() (equivalent to ods
|
||||
// before)?
|
||||
os.os() << '}';
|
||||
if (!layout_->postcommandargs().empty()) {
|
||||
OutputParams rp = features.runparams();
|
||||
rp.local_font = &owner_->getFirstFontSettings(bp);
|
||||
latexArgInsets(*owner_, os, rp, layout_->postcommandargs(), "post:");
|
||||
}
|
||||
}
|
||||
features.addPreambleSnippet(ods.str(), true);
|
||||
features.addPreambleSnippet(os.release(), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,20 @@ using namespace std;
|
||||
namespace lyx {
|
||||
|
||||
|
||||
TexString::TexString(docstring s)
|
||||
: str(move(s)), texrow(TexRow())
|
||||
{
|
||||
texrow.setRows(1 + count(str.begin(), str.end(), '\n'));
|
||||
}
|
||||
|
||||
|
||||
TexString::TexString(docstring s, TexRow t)
|
||||
: str(move(s)), texrow(move(t))
|
||||
{
|
||||
validate();
|
||||
}
|
||||
|
||||
|
||||
void TexString::validate()
|
||||
{
|
||||
size_t lines = 1 + count(str.begin(), str.end(), '\n');
|
||||
|
10
src/TexRow.h
10
src/TexRow.h
@ -199,7 +199,7 @@ private:
|
||||
|
||||
|
||||
/// TexString : dumb struct to pass around docstrings with TexRow information.
|
||||
/// They are best created using oTexStringstream.
|
||||
/// They are best created using otexstringstream.
|
||||
/// They can be output to otexrowstreams and otexstreams.
|
||||
/// A valid TexString has as many newlines in str as in texrow. Be careful not
|
||||
/// to introduce a mismatch between the line and the row counts, as this will
|
||||
@ -221,9 +221,13 @@ struct TexString {
|
||||
//for gcc 4.6, nothing to do: it's enough to disable implicit copy during
|
||||
// dev with more recent versions of gcc.
|
||||
#endif
|
||||
///
|
||||
/// Empty TexString
|
||||
TexString() = default;
|
||||
/// ensure that the string and the TexRow have as many newlines.
|
||||
/// Texstring containing str and TexRow with enough lines which are empty
|
||||
explicit TexString(docstring str);
|
||||
/// Texstring containing str and texrow. Must be valid.
|
||||
TexString(docstring str, TexRow texrow);
|
||||
/// Ensure that the string and the TexRow have as many newlines.
|
||||
void validate();
|
||||
};
|
||||
|
||||
|
@ -78,8 +78,9 @@ size_t otexstringstream::length()
|
||||
|
||||
TexString otexstringstream::release()
|
||||
{
|
||||
TexString ts{ods_.str(), TexRow()};
|
||||
swap(ts.texrow, texrow());
|
||||
TexString ts(ods_.str(), move(texrow()));
|
||||
// reset this
|
||||
texrow() = TexRow();
|
||||
ods_.clear();
|
||||
ods_.str(docstring());
|
||||
return ts;
|
||||
|
Loading…
Reference in New Issue
Block a user