From 42eca3d8d68a2e18701466b8669e45f722c4ea87 Mon Sep 17 00:00:00 2001 From: Thibaut Cuvelier Date: Mon, 3 Aug 2020 22:56:06 +0200 Subject: [PATCH] Revert "DocBook: simplify code to handle abstracts." This reverts commit 0199e048ffed026b909aa0e2d8161efb4f29a4a6. --- .../docbook/bibliography_precooked_aastex.xml | 4 +- lib/layouts/aastex.layout | 6 - src/output_docbook.cpp | 126 +++++++----------- 3 files changed, 52 insertions(+), 84 deletions(-) diff --git a/autotests/export/docbook/bibliography_precooked_aastex.xml b/autotests/export/docbook/bibliography_precooked_aastex.xml index e15bfddc51..2c9f5bd32a 100644 --- a/autotests/export/docbook/bibliography_precooked_aastex.xml +++ b/autotests/export/docbook/bibliography_precooked_aastex.xml @@ -19,10 +19,8 @@ Patron, Alonso's Bar and Grill This is a preliminary report on surface photometry of the major fraction of known globular clusters, to see which of them show the signs of a collapsed core. We also explore some diversionary mathematics and recreational tables. - - + -clusters: globular, peanut—bosons: bozos diff --git a/lib/layouts/aastex.layout b/lib/layouts/aastex.layout index 97c8b64940..445d25f536 100644 --- a/lib/layouts/aastex.layout +++ b/lib/layouts/aastex.layout @@ -282,9 +282,6 @@ Style Abstract Series Bold Size Normal EndFont - DocBookTag abstract - DocBookItemTag para - DocBookInInfo always End @@ -334,9 +331,6 @@ Style Keywords Shape Italic Size Normal EndFont - DocBookTag keyword - DocBookWrapperTag keywordset - DocBookInInfo always End diff --git a/src/output_docbook.cpp b/src/output_docbook.cpp index fd38940064..d0536eee3a 100644 --- a/src/output_docbook.cpp +++ b/src/output_docbook.cpp @@ -50,7 +50,7 @@ namespace lyx { namespace { -std::string fontToDocBookTag(xml::FontTypes type) +std::string const fontToDocBookTag(xml::FontTypes type) { switch (type) { case xml::FontTypes::FT_EMPH: @@ -90,7 +90,6 @@ std::string fontToDocBookTag(xml::FontTypes type) } } - string fontToRole(xml::FontTypes type) { // Specific fonts are achieved with roles. The only common ones are "" for basic emphasis, @@ -104,13 +103,14 @@ string fontToRole(xml::FontTypes type) return ""; case xml::FontTypes::FT_BOLD: return "bold"; - case xml::FontTypes::FT_NOUN: // Outputs a - case xml::FontTypes::FT_TYPE: // Outputs a - return ""; + case xml::FontTypes::FT_NOUN: + return ""; // Outputs a + case xml::FontTypes::FT_TYPE: + return ""; // Outputs a case xml::FontTypes::FT_UBAR: return "underline"; - // All other roles are non-standard for DocBook. + // All other roles are non-standard for DocBook. case xml::FontTypes::FT_WAVE: return "wave"; @@ -814,21 +814,7 @@ pair makeAny( using DocBookDocumentSectioning = tuple; - - -struct DocBookInfoTag -{ - const set shouldBeInInfo; - const set mustBeInInfo; - const set abstract; - pit_type bpit; - pit_type epit; - - DocBookInfoTag(const set & shouldBeInInfo, const set & mustBeInInfo, - const set & abstract, pit_type bpit, pit_type epit) : - shouldBeInInfo(shouldBeInInfo), mustBeInInfo(mustBeInInfo), abstract(abstract), - bpit(bpit), epit(epit) {} -}; +using DocBookInfoTag = tuple, set, pit_type, pit_type>; DocBookDocumentSectioning hasDocumentSectioning(ParagraphList const ¶graphs, pit_type bpit, pit_type const epit) { @@ -861,7 +847,6 @@ bool hasOnlyNotes(Paragraph const & par) DocBookInfoTag getParagraphsWithInfo(ParagraphList const ¶graphs, pit_type bpit, pit_type const epit) { set shouldBeInInfo; set mustBeInInfo; - set abstract; // Find the first non empty paragraph by mutating bpit. while (bpit < epit) { @@ -874,18 +859,14 @@ DocBookInfoTag getParagraphsWithInfo(ParagraphList const ¶graphs, pit_type b // Find the last info-like paragraph. pit_type cpit = bpit; - bool hasAbstractLayout = false; while (cpit < epit) { // Skip paragraphs only containing one note. - Paragraph const & par = paragraphs[cpit]; + Paragraph const &par = paragraphs[cpit]; if (hasOnlyNotes(par)) { cpit += 1; continue; } - if (par.layout().name() == from_ascii("Abstract")) - hasAbstractLayout = true; - // Based on layout information, store this paragraph in one set: should be in , must be. Layout const &style = par.layout(); @@ -895,55 +876,42 @@ DocBookInfoTag getParagraphsWithInfo(ParagraphList const ¶graphs, pit_type b shouldBeInInfo.emplace(cpit); } else { // Hypothesis: the parts should be grouped together near the beginning bpit. - // There may be notes in between, but nothing else. break; } cpit += 1; } // Now, cpit points to the last paragraph that has things that could go in . - // bpit is the beginning of the part. + // bpit is still the beginning of the part. - // Go once again through the list of paragraphs to find the abstract. If there is an abstract - // layout, only consider it. Otherwise, an abstract is just a sequence of paragraphs with text. - if (hasAbstractLayout) { - pit_type pit = bpit; - while (pit < cpit) { // Don't overshoot the part. - if (paragraphs[pit].layout().name() == from_ascii("Abstract")) - abstract.emplace(pit); - pit++; - } - } else { - pit_type lastAbstract = epit + 1; // A nonsensical value. - docstring lastAbstractLayout; + return make_tuple(shouldBeInInfo, mustBeInInfo, bpit, cpit); +} - pit_type pit = bpit; - while (pit < cpit) { // Don't overshoot the part. - const Paragraph & par = paragraphs.at(pit); - if (!par.insetList().empty()) { - for (const auto &i : par.insetList()) { - if (i.inset->getText(0) != nullptr) { - if (lastAbstract == epit + 1) { - // First paragraph that matches the heuristic definition of abstract. - lastAbstract = pit; - lastAbstractLayout = par.layout().name(); - } else if (pit > lastAbstract + 1 || par.layout().name() != lastAbstractLayout) { - // This is either too far from the last abstract paragraph or doesn't - // have the right layout name, BUT there has already been an abstract - // in this document: done with detecting the abstract. - goto done; // Easier to get out of two nested loops. - } - abstract.emplace(pit); - break; - } +bool hasAbstractBetween(ParagraphList const ¶graphs, pit_type const bpitAbstract, pit_type const epitAbstract) +{ + // Hypothesis: the paragraphs between bpitAbstract and epitAbstract can be considered an abstract because they + // are just after a document or part title. + if (epitAbstract - bpitAbstract <= 0) + return false; + + // If there is something between these paragraphs, check if it's compatible with an abstract (i.e. some text). + pit_type bpit = bpitAbstract; + while (bpit < epitAbstract) { + const Paragraph &p = paragraphs.at(bpit); + + if (p.layout().name() == from_ascii("Abstract")) + return true; + + if (!p.insetList().empty()) { + for (const auto &i : p.insetList()) { + if (i.inset->getText(0) != nullptr) { + return true; } } - pit++; } + bpit++; } - - done: - return DocBookInfoTag(shouldBeInInfo, mustBeInInfo, abstract, bpit, cpit); + return false; } @@ -979,18 +947,26 @@ void outputDocBookInfo( XMLStream & xs, OutputParams const & runparams, ParagraphList const & paragraphs, - DocBookInfoTag const & info) + DocBookInfoTag const & info, + pit_type bpitAbstract, + pit_type const epitAbstract) { + // Consider everything between bpitAbstract and epitAbstract (excluded) as paragraphs for the abstract. + // Use bpitAbstract >= epitAbstract to indicate there is no abstract. + + set shouldBeInInfo; + set mustBeInInfo; + pit_type bpitInfo; + pit_type epitInfo; + tie(shouldBeInInfo, mustBeInInfo, bpitInfo, epitInfo) = info; + // Perform an additional check on the abstract. Sometimes, there are many paragraphs that should go // into the abstract, but none generates actual content. Thus, first generate to a temporary stream, // then only create the tag if these paragraphs generate some content. // This check must be performed *before* a decision on whether or not to output is made. - bool hasAbstract = !info.abstract.empty(); + bool hasAbstract = hasAbstractBetween(paragraphs, bpitAbstract, epitAbstract); docstring abstract; if (hasAbstract) { - pit_type bpitAbstract = *std::min_element(info.abstract.begin(), info.abstract.end()); - pit_type epitAbstract = *std::max_element(info.abstract.begin(), info.abstract.end()); - odocstringstream os2; XMLStream xs2(os2); generateDocBookParagraphWithoutSectioning(text, buf, xs2, runparams, paragraphs, bpitAbstract, epitAbstract); @@ -1007,7 +983,7 @@ void outputDocBookInfo( } // The abstract must go in . - bool needInfo = !info.mustBeInInfo.empty() || hasAbstract; + bool needInfo = !mustBeInInfo.empty() || hasAbstract; // Start the tag if required. if (needInfo) { @@ -1017,10 +993,10 @@ void outputDocBookInfo( } // Output the elements that should go in . - generateDocBookParagraphWithoutSectioning(text, buf, xs, runparams, paragraphs, info.bpit, info.epit); + generateDocBookParagraphWithoutSectioning(text, buf, xs, runparams, paragraphs, bpitInfo, epitInfo); if (hasAbstract && !abstract.empty()) { // The second test is probably superfluous. - string tag = paragraphs[*info.abstract.begin()].layout().docbookforceabstracttag(); + string tag = paragraphs[bpitAbstract].layout().docbookforceabstracttag(); if (tag == "NONE") tag = "abstract"; @@ -1053,7 +1029,7 @@ void docbookFirstParagraphs( ParagraphList const ¶graphs = text.paragraphs(); pit_type bpit = runparams.par_begin; DocBookInfoTag info = getParagraphsWithInfo(paragraphs, bpit, epit); - outputDocBookInfo(text, buf, xs, runparams, paragraphs, info); + outputDocBookInfo(text, buf, xs, runparams, paragraphs, info, get<3>(info), epit); } @@ -1080,8 +1056,8 @@ void docbookSimpleAllParagraphs( pit_type bpit = runparams.par_begin; pit_type const epit = runparams.par_end; DocBookInfoTag info = getParagraphsWithInfo(paragraphs, bpit, epit); - outputDocBookInfo(text, buf, xs, runparams, paragraphs, info); - bpit = info.bpit; + outputDocBookInfo(text, buf, xs, runparams, paragraphs, info, 0, 0); + bpit = get<3>(info); // Generate the content starting from the end of the part. // Then, the content. ParagraphList::const_iterator const pend =