commit b1a6edcd77bdbf0efc7585828efc5f3c9618084a Author: Juergen Spitzmueller <sp...@lyx.org> Date: Thu May 15 12:20:53 2025 +0200
Implement MultiPar to layouts (#10590) --- lib/doc/Customization.lyx | 59 +++++++++++++++++++++++++++++++++++++++++++- lib/doc/de/Customization.lyx | 59 +++++++++++++++++++++++++++++++++++++++++++- lib/scripts/layout2layout.py | 5 +++- src/Layout.cpp | 8 +++++- src/Layout.h | 4 +++ src/Paragraph.cpp | 4 +-- src/output_latex.cpp | 52 ++++++++++++++++++++++++++++++-------- 7 files changed, 175 insertions(+), 16 deletions(-) diff --git a/lib/doc/Customization.lyx b/lib/doc/Customization.lyx index 5e45337483..1edd3fba10 100644 --- a/lib/doc/Customization.lyx +++ b/lib/doc/Customization.lyx @@ -1,5 +1,5 @@ #LyX 2.5 created this file. For more info see https://www.lyx.org/ -\lyxformat 638 +\lyxformat 640 \begin_document \begin_header \save_transient_properties true @@ -15347,6 +15347,57 @@ Right_Address_Box \end_layout \end_deeper +\begin_layout Description + +\change_inserted -712698321 1747303660 +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout + +\change_inserted -712698321 1747303589 +MultiPar +\end_layout + +\end_inset + + [ +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout + +\change_inserted -712698321 1747303589 + +\emph on +0 +\end_layout + +\end_inset + +, +\begin_inset space \thinspace{} +\end_inset + + +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout + +\change_inserted -712698321 1747303589 +1 +\end_layout + +\end_inset + +] Whether multiple paragraphs are permitted in this layout. + This only applies to command layouts. + If true, + multiple paragraphs are put within the same command (rather than starting new commands for each paragraph). + Default is false. +\end_layout + \begin_layout Description \begin_inset Flex Code status collapsed @@ -16941,6 +16992,8 @@ status collapsed \change_inserted -712698321 1745643926 TheoremCrossRefName +\change_unchanged + \end_layout \end_inset @@ -16973,6 +17026,8 @@ status collapsed \change_inserted -712698321 1745645504 TheoremCrossRefPluralName +\change_unchanged + \end_layout \end_inset @@ -16985,6 +17040,8 @@ status collapsed \change_inserted -712698321 1745644987 TheoremCrossRefName +\change_unchanged + \end_layout \end_inset diff --git a/lib/doc/de/Customization.lyx b/lib/doc/de/Customization.lyx index 1044fb14dc..2d29921d33 100644 --- a/lib/doc/de/Customization.lyx +++ b/lib/doc/de/Customization.lyx @@ -1,5 +1,5 @@ #LyX 2.5 created this file. For more info see https://www.lyx.org/ -\lyxformat 638 +\lyxformat 640 \begin_document \begin_header \save_transient_properties true @@ -13843,6 +13843,63 @@ Right_Address_Box \begin_inset Flex Code status collapsed +\begin_layout Plain Layout +MultiPar +\end_layout + +\end_inset + + [ +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout + +\emph on +0 +\end_layout + +\end_inset + +, +\begin_inset space \thinspace{} +\end_inset + + +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout +1 +\end_layout + +\end_inset + +] Legt fest, + ob innerhalb dieses Layouts mehrere Absätze erlaubt sind. + Dies betrifft nur Layouts des Typs +\begin_inset Quotes gld +\end_inset + + +\lang english +command +\lang ngerman + +\begin_inset Quotes grd +\end_inset + +. + Falls dies aktiviert ist, + werden mehrere Absätze als Argument ein und desselben Befehls ausgegeben (statt dass für jeden Absatz ein neuer Befehl ausgegeben wird). + Voreinstellung: + deaktiviert. +\end_layout + +\begin_layout Description +\begin_inset Flex Code +status collapsed + \begin_layout Plain Layout NeedProtect \end_layout diff --git a/lib/scripts/layout2layout.py b/lib/scripts/layout2layout.py index 176fd2643e..b3485e820e 100644 --- a/lib/scripts/layout2layout.py +++ b/lib/scripts/layout2layout.py @@ -364,6 +364,9 @@ currentFormat = 108 # "TheoremCounter", "TheoremParentCounter", "TheoremStyle", # "TheoremCrossRefName", "TheoremCrossRefPluralName" +# Incremented to format 109, 15 May 2025 by spitz +# New Layout tag "MultiPar" + # Do not forget to document format change in Customization # Manual (section "Declaring a new text class"). @@ -598,7 +601,7 @@ def convert(lines, end_format): i += 1 continue - if 101 <= format <= 107: + if 101 <= format <= 108: # nothing to do. i += 1 continue diff --git a/src/Layout.cpp b/src/Layout.cpp index 09626bbb22..0c14c79d61 100644 --- a/src/Layout.cpp +++ b/src/Layout.cpp @@ -74,6 +74,7 @@ enum LayoutTags { LT_LATEXTYPE, LT_LEFTDELIM, LT_LEFTMARGIN, + LT_MULTIPAR, LT_NEED_CPROTECT, LT_NEED_MBOXPROTECT, LT_NEED_PROTECT, @@ -161,7 +162,7 @@ enum LayoutTags { ///////////////////// Layout::Layout() - : add_to_toc_(false), is_toc_caption_(true) + : add_to_toc_(false), multi_par_(false), is_toc_caption_(true) { unknown_ = false; margintype = MARGIN_STATIC; @@ -324,6 +325,7 @@ bool Layout::readIgnoreForcelocal(Lexer & lex, TextClass const & tclass, { "leftdelim", LT_LEFTDELIM }, { "leftmargin", LT_LEFTMARGIN }, { "margin", LT_MARGIN }, + { "multipar", LT_MULTIPAR }, { "needcprotect", LT_NEED_CPROTECT }, { "needmboxprotect", LT_NEED_MBOXPROTECT }, { "needprotect", LT_NEED_PROTECT }, @@ -679,6 +681,10 @@ bool Layout::readIgnoreForcelocal(Lexer & lex, TextClass const & tclass, lex >> newline_allowed; break; + case LT_MULTIPAR: + lex >> multi_par_; + break; + case LT_ALIGN: readAlign(lex); break; diff --git a/src/Layout.h b/src/Layout.h index 4722866b54..af179f6533 100644 --- a/src/Layout.h +++ b/src/Layout.h @@ -298,6 +298,8 @@ public: /// are handled as one group? bool isParagraphGroup() const { return par_group_; } /// + bool isMultiparCommand() const { return isCommand() && multi_par_; } + /// bool labelIsInline() const { return labeltype == LABEL_STATIC || labeltype == LABEL_SENSITIVE @@ -686,6 +688,8 @@ private: /// bool add_to_toc_; /// + bool multi_par_; + /// std::string toc_type_; /// bool is_toc_caption_; diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index 234ce3fb4b..b897c03951 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -2755,7 +2755,7 @@ void Paragraph::latex(BufferParams const & bparams, if (empty()) { // For InTitle commands, we have already opened a group // in output_latex::TeXOnePar. - if (style.isCommand() && !style.intitle) { + if (style.isCommand() && !style.intitle && !style.isMultiparCommand()) { os << '{'; ++column; } @@ -2795,7 +2795,7 @@ void Paragraph::latex(BufferParams const & bparams, } // For InTitle commands, we have already opened a group // in output_latex::TeXOnePar. - if (style.isCommand() && !style.intitle) { + if (style.isCommand() && !style.intitle && !style.isMultiparCommand()) { os << '{'; ++column; } diff --git a/src/output_latex.cpp b/src/output_latex.cpp index 9fdc901727..b804cf4f2f 100644 --- a/src/output_latex.cpp +++ b/src/output_latex.cpp @@ -305,6 +305,23 @@ static TeXEnvironmentData prepareEnvironment(Buffer const & buf, "listpreamble:"); } } + + if (style.isMultiparCommand() && !style.latexname().empty()) { + if (!runparams.no_cprotect && pit->needsCProtection(runparams.moving_arg)) { + if (contains(runparams.active_chars, '^')) + // cprotect relies on ^ being on catcode 7 + os << "\\begingroup\\catcode`\\^=7"; + os << "\\cprotect"; + } + os << "\\" << from_ascii(style.latexname()); + // Command arguments + if (!style.latexargs().empty()) { + OutputParams rp = runparams; + rp.local_font = &pit->getFirstFontSettings(bparams); + latexArgInsets(paragraphs, pit, os, rp, style.latexargs()); + } + os << from_ascii(style.latexparam()) << "{%"; + } data.style = &style; // in multilingual environments, the CJK tags have to be nested properly @@ -340,8 +357,9 @@ static void finishEnvironment(otexstream & os, OutputParams const & runparams, state->open_encoding_ = none; } - if (data.style->isEnvironment()) { - os << breakln; + if (data.style->isEnvironment() || data.style->isMultiparCommand()) { + if (data.style->isEnvironment()) + os << breakln; bool const using_begin_end = runparams.use_polyglossia || !lyxrc.language_command_end.empty(); @@ -365,8 +383,12 @@ static void finishEnvironment(otexstream & os, OutputParams const & runparams, os << '\n'; state->nest_level_ -= 1; string const & name = data.style->latexname(); - if (!name.empty()) - os << "\\end{" << from_ascii(name) << "}\n"; + if (!name.empty()) { + if (data.style->isEnvironment()) + os << "\\end{" << from_ascii(name) << "}\n"; + else + os << "}\n"; + } state->prev_env_language_ = data.par_language; if (runparams.encoding != data.prev_encoding) { runparams.encoding = data.prev_encoding; @@ -738,6 +760,8 @@ namespace { void parStartCommand(Paragraph const & par, otexstream & os, OutputParams const & runparams, Layout const & style) { + if (style.isMultiparCommand()) + return; switch (style.latextype) { case LATEX_COMMAND: if (!runparams.no_cprotect && par.needsCProtection(runparams.moving_arg)) { @@ -1232,7 +1256,8 @@ void TeXOnePar(Buffer const & buf, par.parEndChange(), runparams); os << bparams.encoding().latexString(docstring(1, 0x00b6)).first << "}"; } - os << '}'; + if (!style.isMultiparCommand()) + os << '}'; if (!style.postcommandargs().empty()) latexArgInsets(par, os, runparams, style.postcommandargs(), "post:"); if (!runparams.post_macro.empty()) { @@ -1403,7 +1428,8 @@ void TeXOnePar(Buffer const & buf, // InTitle commands need to be closed after the language has been closed. if (intitle_command) { - os << '}'; + if (!style.isMultiparCommand()) + os << '}'; if (!style.postcommandargs().empty()) latexArgInsets(par, os, runparams, style.postcommandargs(), "post:"); if (!runparams.post_macro.empty()) { @@ -1429,7 +1455,12 @@ void TeXOnePar(Buffer const & buf, os << bparams.encoding().latexString(docstring(1, 0x00b6)).first << "}"; } - if (pending_newline) { + // with multipar layouts, do not output new line for last par in group + bool last_multipar_command = false; + if (nextpar && par.layout().isMultiparCommand() + && nextpar->layout().latexname() != par.layout().latexname()) + last_multipar_command = true; + if (pending_newline && !last_multipar_command) { if (unskip_newline) // prevent unwanted whitespace os << '%'; @@ -1514,7 +1545,7 @@ void TeXOnePar(Buffer const & buf, // we don't need a newline for the last paragraph!!! // Note from JMarc: we will re-add a \n explicitly in // TeXEnvironment, because it is needed in this case - if (nextpar && !os.afterParbreak() && !last_was_separator) { + if (nextpar && !os.afterParbreak() && !last_was_separator && !last_multipar_command) { if (!text.inset().getLayout().parbreakIgnored() && !merged_par) // Make sure to start a new line os << breakln; @@ -1725,8 +1756,9 @@ void latexParagraphs(Buffer const & buf, } } - if (!layout.isEnvironment() && par->params().leftIndent().zero()) { - // This is a standard top level paragraph, TeX it and continue. + if (!layout.isEnvironment() && !layout.isMultiparCommand() + && par->params().leftIndent().zero()) { + // This is a standard top level single-par paragraph, TeX it and continue. TeXOnePar(buf, text, pit, os, runparams, everypar); continue; } -- lyx-cvs mailing list lyx-cvs@lists.lyx.org https://lists.lyx.org/mailman/listinfo/lyx-cvs