[LyX/master] DocBook: add layout parameters to control the special case and argument positioning.
Thibaut Cuvelier
tcuvelier at lyx.org
Sun Nov 29 21:24:16 UTC 2020
commit 59acb375d1f44f59726b50343c6bdf96f54206b3
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date: Sat Nov 28 22:43:00 2020 +0100
DocBook: add layout parameters to control the special case and argument positioning.
Only for flex insets.
Also add similar checks in InsetText to avoid bibliographies in paragraphs.
---
lib/scripts/layout2layout.py | 13 ++++++++++-
src/Layout.h | 1 +
src/OutputParams.h | 4 +++
src/Paragraph.cpp | 1 +
src/TextClass.cpp | 2 +-
src/insets/InsetArgument.cpp | 5 ++++
src/insets/InsetArgument.h | 4 +++
src/insets/InsetLayout.cpp | 13 ++++++++++++
src/insets/InsetLayout.h | 8 +++++++
src/insets/InsetText.cpp | 45 ++++++++++++++++++++++++++++++++++++++++-
src/output_docbook.cpp | 36 ++++++++++++++++++++++++++++++++-
11 files changed, 126 insertions(+), 6 deletions(-)
diff --git a/lib/scripts/layout2layout.py b/lib/scripts/layout2layout.py
index 29159b0..b2393ea 100644
--- a/lib/scripts/layout2layout.py
+++ b/lib/scripts/layout2layout.py
@@ -11,7 +11,7 @@
# This script will update a .layout file to current format
# The latest layout format is also defined in src/TextClass.cpp
-currentFormat = 87
+currentFormat = 88
# Incremented to format 4, 6 April 2007, lasgouttes
@@ -296,7 +296,10 @@ currentFormat = 87
# Incremented to format 86, 20 October 2020 by tcuvelier
# New tag DocBookSection.
-# Incremeted to format 87, 2 November 2020 by rkh
+# Incremented to format 87, 2 November 2020 by rkh
+
+# Incremented to format 88, 28 November 2020 by tcuvelier
+# New tag DocBookNotInPara.
# Do not forget to document format change in Customization
# Manual (section "Declaring a new text class").
@@ -358,6 +361,7 @@ def concatenate_label(old, new):
else:
return b'"' + old + new + b'"'
+
# appends a string to a list unless it's already there
def addstring(s, l):
if l.count(s) > 0:
@@ -547,6 +551,11 @@ def convert(lines, end_format):
i += 1
continue
+ if 87 <= format <= 88:
+ # nothing to do.
+ i += 1
+ continue
+
if format == 86:
if lines[i].lstrip().lower().startswith(b"stepmastercounter"):
pattern = re.compile(b"stepmastercounter", re.IGNORECASE)
diff --git a/src/Layout.h b/src/Layout.h
index cb8f537..dfb5afe 100644
--- a/src/Layout.h
+++ b/src/Layout.h
@@ -115,6 +115,7 @@ public:
docstring docbooktag;
docstring docbooktagtype;
docstring docbookattr;
+ bool docbookargumentbeforemaintag = false;
};
///
typedef std::map<std::string, latexarg> LaTeXArgMap;
diff --git a/src/OutputParams.h b/src/OutputParams.h
index 7e0a4b2..1cd16d2 100644
--- a/src/OutputParams.h
+++ b/src/OutputParams.h
@@ -26,6 +26,7 @@ class Encoding;
class ExportData;
class Font;
class Language;
+class InsetArgument;
class OutputParams {
public:
@@ -382,6 +383,9 @@ public:
/// Should wrappers be ignored? Mostly useful to avoid generation of <abstract>.
bool docbook_ignore_wrapper = false;
+ /// Some parameters are output before the rest of the paragraph, they should not be generated a second time.
+ std::set<InsetArgument const *> docbook_prepended_arguments = {};
+
/// Are we generating this material for inclusion in a TOC-like entity?
bool for_toc = false;
diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index aa6bd30..1e92259 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -865,6 +865,7 @@ int Paragraph::eraseChars(pos_type start, pos_type end, bool trackChanges)
return end - i;
}
+
// Handle combining characters
int Paragraph::Private::latexSurrogatePair(BufferParams const & bparams,
otexstream & os, char_type c, char_type next,
diff --git a/src/TextClass.cpp b/src/TextClass.cpp
index cd87cca..a58ae6d 100644
--- a/src/TextClass.cpp
+++ b/src/TextClass.cpp
@@ -59,7 +59,7 @@ namespace lyx {
// You should also run the development/tools/updatelayouts.py script,
// to update the format of all of our layout files.
//
-int const LAYOUT_FORMAT = 87; // rkh: master --> parent for counters
+int const LAYOUT_FORMAT = 88; // tcuvelier: add DocBookNotInPara
// Layout format for the current lyx file format. Controls which format is
diff --git a/src/insets/InsetArgument.cpp b/src/insets/InsetArgument.cpp
index 8f1d762..2ae80ca 100644
--- a/src/insets/InsetArgument.cpp
+++ b/src/insets/InsetArgument.cpp
@@ -126,6 +126,7 @@ void InsetArgument::updateBuffer(ParIterator const & it, UpdateType utype, bool
docbooktag_ = (*lait).second.docbooktag;
docbooktagtype_ = (*lait).second.docbooktagtype;
docbookattr_ = (*lait).second.docbookattr;
+ docbookargumentbeforemaintag_ = (*lait).second.docbookargumentbeforemaintag;
pass_thru_local_ = false;
if (lait->second.is_toc_caption) {
is_toc_caption_ = true;
@@ -312,6 +313,10 @@ InsetLayout::InsetDecoration InsetArgument::decoration() const
void InsetArgument::docbook(XMLStream & xs, OutputParams const & rp) const {
+ // Ignore arguments that have already been output.
+ if (rp.docbook_prepended_arguments.find(this) != rp.docbook_prepended_arguments.end())
+ return;
+
if (docbooktag_ != from_ascii("NONE") && docbooktag_ != from_ascii("IGNORE")) {
// TODO: implement docbooktagtype_.
xs << xml::StartTag(docbooktag_, docbookattr_);
diff --git a/src/insets/InsetArgument.h b/src/insets/InsetArgument.h
index d5d54a6..1c63e5c 100644
--- a/src/insets/InsetArgument.h
+++ b/src/insets/InsetArgument.h
@@ -39,6 +39,8 @@ public:
std::string name() const { return name_; }
+ bool docbookargumentbeforemaintag() const { return docbookargumentbeforemaintag_; }
+
/// \name Public functions inherited from Inset class
//@{
///
@@ -131,6 +133,8 @@ private:
docstring docbooktagtype_;
/// DocBook attributes.
docstring docbookattr_;
+ ///
+ bool docbookargumentbeforemaintag_ = false;
protected:
/// \name Protected functions inherited from Inset class
diff --git a/src/insets/InsetLayout.cpp b/src/insets/InsetLayout.cpp
index 62030d0..5b5308d 100644
--- a/src/insets/InsetLayout.cpp
+++ b/src/insets/InsetLayout.cpp
@@ -95,6 +95,8 @@ bool InsetLayout::read(Lexer & lex, TextClass const & tclass,
IL_DOCBOOKTAGTYPE,
IL_DOCBOOKSECTION,
IL_DOCBOOKININFO,
+ IL_DOCBOOKARGUMENTBEFOREMAINTAG,
+ IL_DOCBOOKNOTINPARA,
IL_DOCBOOKWRAPPERTAG,
IL_DOCBOOKWRAPPERTAGTYPE,
IL_DOCBOOKWRAPPERATTR,
@@ -148,6 +150,7 @@ bool InsetLayout::read(Lexer & lex, TextClass const & tclass,
{ "custompars", IL_CUSTOMPARS },
{ "decoration", IL_DECORATION },
{ "display", IL_DISPLAY },
+ { "docbookargumentbeforemaintag", IL_DOCBOOKARGUMENTBEFOREMAINTAG },
{ "docbookattr", IL_DOCBOOKATTR },
{ "docbookininfo", IL_DOCBOOKININFO },
{ "docbookitemattr", IL_DOCBOOKITEMATTR },
@@ -156,6 +159,7 @@ bool InsetLayout::read(Lexer & lex, TextClass const & tclass,
{ "docbookitemwrapperattr", IL_DOCBOOKITEMWRAPPERATTR },
{ "docbookitemwrappertag", IL_DOCBOOKITEMWRAPPERTAG },
{ "docbookitemwrappertagtype", IL_DOCBOOKITEMWRAPPERTAGTYPE },
+ { "docbooknotinpara", IL_DOCBOOKNOTINPARA },
{ "docbooksection", IL_DOCBOOKSECTION },
{ "docbooktag", IL_DOCBOOKTAG },
{ "docbooktagtype", IL_DOCBOOKTAGTYPE },
@@ -514,6 +518,12 @@ bool InsetLayout::read(Lexer & lex, TextClass const & tclass,
case IL_DOCBOOKININFO:
lex >> docbookininfo_;
break;
+ case IL_DOCBOOKARGUMENTBEFOREMAINTAG:
+ lex >> docbookargumentbeforemaintag_;
+ break;
+ case IL_DOCBOOKNOTINPARA:
+ lex >> docbooknotinpara_;
+ break;
case IL_DOCBOOKSECTION:
lex >> docbooksection_;
break;
@@ -819,6 +829,9 @@ void InsetLayout::readArgument(Lexer & lex)
} else if (tok == "docbooktagtype") {
lex.next();
arg.docbooktagtype = lex.getDocString();
+ } else if (tok == "docbookargumentbeforemaintag") {
+ lex.next();
+ arg.docbookargumentbeforemaintag = lex.getBool();
} else {
lex.printError("Unknown tag");
error = true;
diff --git a/src/insets/InsetLayout.h b/src/insets/InsetLayout.h
index 09abe71..88143d5 100644
--- a/src/insets/InsetLayout.h
+++ b/src/insets/InsetLayout.h
@@ -158,6 +158,10 @@ public:
///
bool docbooksection() const { return docbooksection_; }
///
+ bool docbooknotinpara() const { return docbooknotinpara_; }
+ ///
+ bool docbookargumentbeforemaintag() const { return docbookargumentbeforemaintag_; }
+ ///
std::string docbookwrappertag() const { return docbookwrappertag_; }
///
std::string docbookwrappertagtype() const;
@@ -311,6 +315,10 @@ private:
///
mutable std::string docbookininfo_;
///
+ bool docbooknotinpara_ = false;
+ ///
+ bool docbookargumentbeforemaintag_ = false;
+ ///
bool docbooksection_ = false;
///
std::string docbookwrappertag_;
diff --git a/src/insets/InsetText.cpp b/src/insets/InsetText.cpp
index 2c757a9..bf1fe62 100644
--- a/src/insets/InsetText.cpp
+++ b/src/insets/InsetText.cpp
@@ -621,8 +621,35 @@ void InsetText::docbook(XMLStream & xs, OutputParams const & rp, XHTMLOptions op
if (!rp.docbook_generate_info && il.docbookininfo() != "never")
return;
+ // In some cases, the input parameters must be overridden for outer tags.
+ bool writeOuterTag = opts & WriteOuterTag;
+ if (writeOuterTag) {
+ // For each paragraph, if there are only Bibitems and the corresponding text, don't write the outer tags.
+ bool allBibitems = std::all_of(text().paragraphs().begin(), text().paragraphs().end(), [](Paragraph const & par) {
+ auto nInsets = std::distance(par.insetList().begin(), par.insetList().end());
+ auto parSize = (size_t) par.size();
+ return nInsets == 1 && parSize > 1 && par.insetList().begin()->inset->lyxCode() == BIBITEM_CODE;
+ });
+ writeOuterTag = !allBibitems;
+ }
+
+ // Detect arguments that should be output before the paragraph.
+ // Don't reuse runparams.docbook_prepended_arguments, as the same object is used in InsetArgument to determine
+ // whether the inset should be output or not, whatever the context (i.e. position with respect to the wrapper).
+ std::set<InsetArgument const *> prependedArguments;
+ for (auto const & par : paragraphs()) {
+ for (pos_type i = 0; i < par.size(); ++i) {
+ if (par.getInset(i) && par.getInset(i)->lyxCode() == ARG_CODE) {
+ InsetArgument const *arg = par.getInset(i)->asInsetArgument();
+ if (arg->docbookargumentbeforemaintag())
+ prependedArguments.insert(par.getInset(i)->asInsetArgument());
+ }
+ }
+ }
+
// Start outputting this inset.
- if (opts & WriteOuterTag) {
+ // - First, wrapper around the inset and its main tag.
+ if (writeOuterTag) {
if (!il.docbookwrappertag().empty() && il.docbookwrappertag() != "NONE" && il.docbookwrappertag() != "IGNORE")
xml::openTag(xs, il.docbookwrappertag(), il.docbookwrapperattr(), il.docbookwrappertagtype());
@@ -634,7 +661,19 @@ void InsetText::docbook(XMLStream & xs, OutputParams const & rp, XHTMLOptions op
attrs += from_ascii(" xlink:href=\"") + text_.asString() + from_ascii("\"");
xml::openTag(xs, il.docbooktag(), attrs, il.docbooktagtype());
}
+ }
+
+ // - Think about the arguments.
+ OutputParams np = runparams;
+ np.docbook_in_par = true;
+ for (auto const & arg : prependedArguments)
+ arg->docbook(xs, np);
+
+ // - Mark the newly generated arguments are not-to-be-generated-again.
+ runparams.docbook_prepended_arguments = std::move(prependedArguments);
+ // - Deal with the first item.
+ if (writeOuterTag) {
if (!il.docbookitemwrappertag().empty() && il.docbookitemwrappertag() != "NONE" && il.docbookitemwrappertag() != "IGNORE")
xml::openTag(xs, il.docbookitemwrappertag(), il.docbookitemwrapperattr(), il.docbookitemwrappertagtype());
@@ -650,11 +689,13 @@ void InsetText::docbook(XMLStream & xs, OutputParams const & rp, XHTMLOptions op
if (il.isPassThru())
runparams.pass_thru = true;
+ // - Write the main content of the inset.
xs.startDivision(false);
docbookParagraphs(text_, buffer(), xs, runparams);
xs.endDivision();
- if (opts & WriteOuterTag) {
+ // - Close the required tags.
+ if (writeOuterTag) {
if (!il.docbookitemtag().empty() && il.docbookitemtag() != "NONE" && il.docbookitemtag() != "IGNORE")
xml::closeTag(xs, il.docbookitemtag(), il.docbookitemtagtype());
diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp
index d815abc..aaa3860 100644
--- a/src/output_docbook.cpp
+++ b/src/output_docbook.cpp
@@ -347,7 +347,7 @@ void makeParagraph(
special_case = true;
}
- size_t nInsets = std::distance(par->insetList().begin(), par->insetList().end());
+ auto nInsets = std::distance(par->insetList().begin(), par->insetList().end());
auto parSize = (size_t) par->size();
// Plain layouts must be ignored.
@@ -377,6 +377,40 @@ void makeParagraph(
};
special_case |= nInsets == parSize && std::all_of(par->insetList().begin(), par->insetList().end(), isLyxCodeSpecialCase);
+ // Flex elements (InsetLayout) have their own parameter to control the special case.
+ auto isFlexSpecialCase = [](InsetList::Element inset) {
+ if (inset.inset->lyxCode() != FLEX_CODE)
+ return false;
+ // Standard condition: check the parameter.
+ if (inset.inset->getLayout().docbooknotinpara())
+ return true;
+
+ // If the parameter is not set, maybe the flex inset only contains things that should match the standard
+ // condition. In this case, isLyxCodeSpecialCase must also check for bibitems...
+ auto isLyxCodeSpecialCase = [](InsetList::Element inset) {
+ return lyxCodeSpecialCases.find(inset.inset->lyxCode()) != lyxCodeSpecialCases.end() ||
+ inset.inset->lyxCode() == BIBITEM_CODE;
+ };
+ if (InsetText * text = inset.inset->asInsetText()) {
+ for (auto const & par : text->paragraphs()) {
+ auto nInsets = std::distance(par.insetList().begin(), par.insetList().end());
+ auto parSize = (size_t) par.size();
+
+ if (nInsets == 1 && par.insetList().begin()->inset->lyxCode() == BIBITEM_CODE)
+ return true;
+ if (nInsets != parSize)
+ return false;
+ if (!std::all_of(par.insetList().begin(), par.insetList().end(), isLyxCodeSpecialCase))
+ return false;
+ }
+ return true;
+ }
+
+ // No case matched: give up.
+ return false;
+ };
+ special_case |= nInsets == parSize && std::all_of(par->insetList().begin(), par->insetList().end(), isFlexSpecialCase);
+
// Open a paragraph if it is allowed, we are not already within a paragraph, and the insets in the paragraph do
// not forbid paragraphs (aka special cases).
bool const open_par = runparams.docbook_make_pars
More information about the lyx-cvs
mailing list