[LyX/master] DocBook: implement prepended/appended arguments for all kinds of elements.
Thibaut Cuvelier
tcuvelier at lyx.org
Fri Feb 19 16:34:46 UTC 2021
commit 358e4ace560f4a6a3a8435ac9959e38a23cb6d56
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date: Fri Feb 19 17:38:22 2021 +0100
DocBook: implement prepended/appended arguments for all kinds of elements.
Previously, it was just in InsetText.
---
src/Paragraph.cpp | 90 ++++++++++++++++++++++++++++++++++------------
src/Paragraph.h | 3 +-
src/insets/InsetERT.cpp | 10 +++++-
src/output_docbook.cpp | 54 ++++++++++++++++++++++++----
4 files changed, 124 insertions(+), 33 deletions(-)
diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index b7616ad..559a61a 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -47,6 +47,7 @@
#include "frontends/alert.h"
+#include "insets/InsetArgument.h"
#include "insets/InsetBibitem.h"
#include "insets/InsetLabel.h"
#include "insets/InsetSpecialChar.h"
@@ -3419,35 +3420,55 @@ std::tuple<vector<xml::FontTag>, vector<xml::EndFontTag>> computeDocBookFontSwit
} // anonymous namespace
-std::vector<docstring> Paragraph::simpleDocBookOnePar(Buffer const & buf,
+std::tuple<std::vector<docstring>, std::vector<docstring>, std::vector<docstring>>
+ Paragraph::simpleDocBookOnePar(Buffer const & buf,
OutputParams const & runparams,
Font const & outerfont,
pos_type initial,
bool is_last_par,
bool ignore_fonts) const
{
- // Track whether we have opened these tags
- DocBookFontState fs;
+ std::vector<docstring> prependedParagraphs;
+ std::vector<docstring> generatedParagraphs;
+ std::vector<docstring> appendedParagraphs;
+ odocstringstream os;
- Layout const & style = *d->layout_;
- FontInfo font_old =
- style.labeltype == LABEL_MANUAL ? style.labelfont : style.font;
+ // If there is an argument that must be output before the main tag, do it before handling the rest of the paragraph.
+ // Also tag all arguments that shouldn't go in the main content right now, so that they are never generated at the
+ // wrong place.
+ OutputParams rp = runparams;
+ for (pos_type i = initial; i < size(); ++i) {
+ if (getInset(i) && getInset(i)->lyxCode() == ARG_CODE) {
+ const InsetArgument * arg = getInset(i)->asInsetArgument();
+ if (arg->docbookargumentbeforemaintag()) {
+ auto xs_local = XMLStream(os);
+ arg->docbook(xs_local, rp);
+
+ prependedParagraphs.push_back(os.str());
+ os.str(from_ascii(""));
+
+ rp.docbook_prepended_arguments.insert(arg);
+ } else if (arg->docbookargumentaftermaintag()) {
+ rp.docbook_appended_arguments.insert(arg);
+ }
+ }
+ }
- string const default_family =
- buf.masterBuffer()->params().fonts_default_family;
+ // State variables for the main loop.
+ auto xs = new XMLStream(os); // XMLStream has no copy constructor: to create a new object, the only solution
+ // is to hold a pointer to the XMLStream (xs = XMLStream(os) is not allowed once the first object is built).
+ std::vector<char_type> delayedChars; // When a font tag ends with a space, output it after the closing font tag.
+ // This requires to store delayed characters at some point.
- vector<xml::FontTag> tagsToOpen;
- vector<xml::EndFontTag> tagsToClose;
+ DocBookFontState fs; // Track whether we have opened font tags
+ DocBookFontState old_fs = fs;
- std::vector<docstring> generatedParagraphs;
- DocBookFontState old_fs = fs;
- odocstringstream os;
- auto * xs = new XMLStream(os); // XMLStream has no copy constructor: to create a new object, the only solution
- // is to hold a pointer to the XMLStream (xs = XMLStream(os) is not allowed once the first object is built).
+ Layout const & style = *d->layout_;
+ FontInfo font_old = style.labeltype == LABEL_MANUAL ? style.labelfont : style.font;
+ string const default_family = buf.masterBuffer()->params().fonts_default_family;
- // When a font tag ends with a space, output it after the closing font tag. This requires to store delayed
- // characters at some point.
- std::vector<char_type> delayedChars;
+ vector<xml::FontTag> tagsToOpen;
+ vector<xml::EndFontTag> tagsToClose;
// Parsing main loop.
for (pos_type i = initial; i < size(); ++i) {
@@ -3511,8 +3532,13 @@ std::vector<docstring> Paragraph::simpleDocBookOnePar(Buffer const & buf,
// Finally, write the next character or inset.
if (Inset const * inset = getInset(i)) {
- if (!runparams.for_toc || inset->isInToc()) {
- OutputParams np = runparams;
+ bool inset_is_argument_elsewhere = getInset(i)->asInsetArgument() &&
+ rp.docbook_appended_arguments.find(inset->asInsetArgument()) != rp.docbook_appended_arguments.end() &&
+ rp.docbook_prepended_arguments.find(inset->asInsetArgument()) != rp.docbook_prepended_arguments.end();
+
+ if ((!rp.for_toc || inset->isInToc()) && !inset_is_argument_elsewhere) {
+ // Arguments may need to be output
+ OutputParams np = rp;
np.local_font = &font;
// TODO: special case will bite here.
@@ -3520,7 +3546,7 @@ std::vector<docstring> Paragraph::simpleDocBookOnePar(Buffer const & buf,
inset->docbook(*xs, np);
}
} else {
- char_type c = getUChar(buf.masterBuffer()->params(), runparams, i);
+ char_type c = getUChar(buf.masterBuffer()->params(), rp, i);
if (lyx::isSpace(c) && !ignore_fonts)
delayedChars.push_back(c);
else
@@ -3542,14 +3568,30 @@ std::vector<docstring> Paragraph::simpleDocBookOnePar(Buffer const & buf,
// In listings, new lines (i.e. \n characters in the output) are very important. Avoid generating one for the
// last line to get a clean output.
- if (runparams.docbook_in_listing && !is_last_par)
+ if (rp.docbook_in_listing && !is_last_par)
*xs << xml::CR();
// Finalise the last (and most likely only) paragraph.
generatedParagraphs.push_back(os.str());
- delete xs;
+ os.str(from_ascii(""));
+ delete xs;
+
+ // If there is an argument that must be output after the main tag, do it after handling the rest of the paragraph.
+ for (pos_type i = initial; i < size(); ++i) {
+ if (getInset(i) && getInset(i)->lyxCode() == ARG_CODE) {
+ const InsetArgument * arg = getInset(i)->asInsetArgument();
+ if (arg->docbookargumentaftermaintag()) {
+ // Don't use rp, as this argument would not generate anything.
+ auto xs_local = XMLStream(os);
+ arg->docbook(xs_local, runparams);
+
+ appendedParagraphs.push_back(os.str());
+ os.str(from_ascii(""));
+ }
+ }
+ }
- return generatedParagraphs;
+ return std::tuple(prependedParagraphs, generatedParagraphs, appendedParagraphs);
}
diff --git a/src/Paragraph.h b/src/Paragraph.h
index c67a507..67f41dd 100644
--- a/src/Paragraph.h
+++ b/src/Paragraph.h
@@ -204,7 +204,8 @@ public:
pos_type firstWordLyXHTML(XMLStream & xs, OutputParams const & runparams) const;
/// Outputs to stream the DocBook representation, one element per paragraph.
- std::vector<docstring> simpleDocBookOnePar(Buffer const & buf,
+ std::tuple<std::vector<docstring>, std::vector<docstring>, std::vector<docstring>>
+ simpleDocBookOnePar(Buffer const & buf,
OutputParams const & runparams,
Font const & outerfont,
pos_type initial = 0,
diff --git a/src/insets/InsetERT.cpp b/src/insets/InsetERT.cpp
index 559fef2..61adfbd 100644
--- a/src/insets/InsetERT.cpp
+++ b/src/insets/InsetERT.cpp
@@ -98,7 +98,13 @@ void InsetERT::docbook(XMLStream & xs, OutputParams const & runparams) const
// in an ERT, use simple line breaks.
// New line after each paragraph of the ERT, save the last one.
while (true) { // For each paragraph in the ERT...
- auto pars = par->simpleDocBookOnePar(buffer(), runparams, text().outerFont(distance(begin, par)), 0, false, true);
+ std::vector<docstring> pars_prepend;
+ std::vector<docstring> pars;
+ std::vector<docstring> pars_append;
+ tie(pars_prepend, pars, pars_append) = par->simpleDocBookOnePar(buffer(), runparams, text().outerFont(distance(begin, par)), 0, false, true);
+
+ for (docstring const & parXML : pars_prepend)
+ xs << XMLStream::ESCAPE_NONE << parXML;
auto p = pars.begin();
while (true) { // For each line of this ERT paragraph...
os << *p;
@@ -108,6 +114,8 @@ void InsetERT::docbook(XMLStream & xs, OutputParams const & runparams) const
else
break;
}
+ for (docstring const & parXML : pars_append)
+ xs << XMLStream::ESCAPE_NONE << parXML;
++par;
if (par != end)
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index e039d70..582fab0 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -286,9 +286,17 @@ void makeBibliography(
// Generate the entry. Concatenate the different parts of the paragraph if any.
auto const begin = text.paragraphs().begin();
- auto pars = par->simpleDocBookOnePar(buf, runparams, text.outerFont(std::distance(begin, par)), 0);
+ std::vector<docstring> pars_prepend;
+ std::vector<docstring> pars;
+ std::vector<docstring> pars_append;
+ tie(pars_prepend, pars, pars_append) = par->simpleDocBookOnePar(buf, runparams, text.outerFont(std::distance(begin, par)), 0);
+
+ for (auto & parXML : pars_prepend)
+ xs << XMLStream::ESCAPE_NONE << parXML;
for (auto & parXML : pars)
xs << XMLStream::ESCAPE_NONE << parXML;
+ for (auto & parXML : pars_append)
+ xs << XMLStream::ESCAPE_NONE << parXML;
// End the precooked bibliography entry.
xs << xml::EndTag("bibliomixed");
@@ -432,7 +440,14 @@ void makeParagraph(
// Open and close tags around each contained paragraph.
auto nextpar = par;
++nextpar;
- auto pars = par->simpleDocBookOnePar(buf, runparams, text.outerFont(distance(begin, par)), 0, nextpar == end, special_case);
+
+ std::vector<docstring> pars_prepend;
+ std::vector<docstring> pars;
+ std::vector<docstring> pars_append;
+ tie(pars_prepend, pars, pars_append) = par->simpleDocBookOnePar(buf, runparams, text.outerFont(distance(begin, par)), 0, nextpar == end, special_case);
+
+ for (docstring const & parXML : pars_prepend)
+ xs << XMLStream::ESCAPE_NONE << parXML;
for (docstring const & parXML : pars) {
if (!xml::isNotOnlySpace(parXML))
continue;
@@ -445,6 +460,8 @@ void makeParagraph(
if (close_par)
closeParTag(xs, &*par, (nextpar != end) ? &*nextpar : nullptr, runparams);
}
+ for (docstring const & parXML : pars_append)
+ xs << XMLStream::ESCAPE_NONE << parXML;
}
@@ -480,8 +497,13 @@ void makeEnvironment(Text const &text,
// Nothing to do (otherwise, infinite loops).
} else if (style.latextype == LATEX_ENVIRONMENT) {
// Generate the paragraph, if need be.
- auto pars = par->simpleDocBookOnePar(buf, runparams, text.outerFont(std::distance(text.paragraphs().begin(), par)), 0, false, ignoreFonts);
+ std::vector<docstring> pars_prepend;
+ std::vector<docstring> pars;
+ std::vector<docstring> pars_append;
+ tie(pars_prepend, pars, pars_append) = par->simpleDocBookOnePar(buf, runparams, text.outerFont(std::distance(text.paragraphs().begin(), par)), 0, false, ignoreFonts);
+ for (docstring const & parXML : pars_prepend)
+ xs << XMLStream::ESCAPE_NONE << parXML;
if (mimicListing) {
auto p = pars.begin();
while (p != pars.end()) {
@@ -504,6 +526,8 @@ void makeEnvironment(Text const &text,
xml::closeTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnertagtype());
}
}
+ for (docstring const & parXML : pars_append)
+ xs << XMLStream::ESCAPE_NONE << parXML;
} else {
makeAny(text, buf, xs, runparams, par);
}
@@ -604,14 +628,21 @@ ParagraphList::const_iterator makeListEnvironment(Text const &text,
// Generate the content of the item.
if (sep < par->size()) {
- auto pars = par->simpleDocBookOnePar(buf, runparams,
+ std::vector<docstring> pars_prepend;
+ std::vector<docstring> pars;
+ std::vector<docstring> pars_append;
+ tie(pars_prepend, pars, pars_append) = par->simpleDocBookOnePar(buf, runparams,
text.outerFont(std::distance(text.paragraphs().begin(), par)), sep);
+ for (docstring const & parXML : pars_prepend)
+ xs << XMLStream::ESCAPE_NONE << parXML;
for (auto &p : pars) {
xml::openTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnerattr(),
par->layout().docbookiteminnertagtype());
xs << XMLStream::ESCAPE_NONE << p;
xml::closeTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnertagtype());
}
+ for (docstring const & parXML : pars_append)
+ xs << XMLStream::ESCAPE_NONE << parXML;
} else {
// DocBook doesn't like emptiness.
xml::compTag(xs, par->layout().docbookiteminnertag(), par->layout().docbookiteminnerattr(),
@@ -656,14 +687,23 @@ void makeCommand(
// Generate this command.
auto prevpar = text.paragraphs().getParagraphBefore(par);
- openParTag(xs, &*par, prevpar, runparams);
- auto pars = par->simpleDocBookOnePar(buf, runparams,text.outerFont(distance(begin, par)));
+ std::vector<docstring> pars_prepend;
+ std::vector<docstring> pars;
+ std::vector<docstring> pars_append;
+ tie(pars_prepend, pars, pars_append) = par->simpleDocBookOnePar(buf, runparams,text.outerFont(distance(begin, par)));
+
+ for (docstring const & parXML : pars_prepend)
+ xs << XMLStream::ESCAPE_NONE << parXML;
+
+ openParTag(xs, &*par, prevpar, runparams);
for (auto & parXML : pars)
// TODO: decide what to do with openParTag/closeParTag in new lines.
xs << XMLStream::ESCAPE_NONE << parXML;
+ closeParTag(xs, &*par, (nextpar != end) ? &*nextpar : nullptr, runparams);
- closeParTag(xs, &*par, (nextpar != end) ? &*nextpar : nullptr, runparams);
+ for (docstring const & parXML : pars_append)
+ xs << XMLStream::ESCAPE_NONE << parXML;
}
More information about the lyx-cvs
mailing list