commit ce5b420a44ec1bfa5898c05236cc16ccec210343
Author: Juergen Spitzmueller <[email protected]>
Date: Fri Mar 16 12:56:17 2018 +0100
tex2lyx: add support for LaTeXParam
Part of #11068
(cherry picked from commit 506ae2d2ea1e646461841c57edd3f79c97d671c2)
---
src/tex2lyx/Context.h | 2 +
src/tex2lyx/Parser.cpp | 21 ++++++++++
src/tex2lyx/Parser.h | 5 ++
src/tex2lyx/TODO.txt | 15 -------
src/tex2lyx/tex2lyx.cpp | 36 +++++++++--------
src/tex2lyx/tex2lyx.h | 10 +++--
src/tex2lyx/text.cpp | 99 ++++++++++++++++++++++++++++++++++++++++++++---
7 files changed, 146 insertions(+), 42 deletions(-)
diff --git a/src/tex2lyx/Context.h b/src/tex2lyx/Context.h
index 47b39fc..e48bdf3 100644
--- a/src/tex2lyx/Context.h
+++ b/src/tex2lyx/Context.h
@@ -130,6 +130,8 @@ public:
std::string par_extra_stuff;
/// We may need to add something at the beginning of a list.
std::string list_extra_stuff;
+ /// A LaTeXParam to be ignored in parsing.
+ std::string latexparam;
/// If there has been an \\begin_deeper, we'll need a matching
/// \\end_deeper
bool need_end_deeper;
diff --git a/src/tex2lyx/Parser.cpp b/src/tex2lyx/Parser.cpp
index 1d506a7..94da955 100644
--- a/src/tex2lyx/Parser.cpp
+++ b/src/tex2lyx/Parser.cpp
@@ -650,6 +650,27 @@ string const Parser::plainCommand(char left, char right,
string const & name)
}
+string const Parser::getCommandLatexParam()
+{
+ if (!good())
+ return string();
+ string res;
+ size_t offset = 0;
+ while (true) {
+ if (pos_ + offset >= tokens_.size())
+ tokenize_one();
+ if (pos_ + offset >= tokens_.size())
+ break;
+ Token t = tokens_[pos_ + offset];
+ if (t.cat() == catBegin)
+ break;
+ res += t.asInput();
+ ++offset;
+ }
+ return res;
+}
+
+
Parser::Arg Parser::verbatimStuff(string const & end_string, bool const
allow_linebreak)
{
if (!good())
diff --git a/src/tex2lyx/Parser.h b/src/tex2lyx/Parser.h
index 83fa1c7..b15f95a 100644
--- a/src/tex2lyx/Parser.h
+++ b/src/tex2lyx/Parser.h
@@ -279,6 +279,11 @@ public:
*/
std::string const plainCommand(char left, char right, std::string const
& name);
/*
+ * Returns everything before the main command argument.
+ * This is where the LaTeXParam value of a layout is output.
+ */
+ std::string const getCommandLatexParam();
+ /*
* Basically the same as plainEnvironment() but the parsing is
* stopped at string \p end_string. Contrary to the other
* methods, this uses proper catcode setting. This function is
diff --git a/src/tex2lyx/TODO.txt b/src/tex2lyx/TODO.txt
index b42ea3f..be5d770 100644
--- a/src/tex2lyx/TODO.txt
+++ b/src/tex2lyx/TODO.txt
@@ -45,7 +45,6 @@ Format LaTeX feature LyX feature
386 LyX version InsetInfo
390 forward/reverse search \forward_search, \forward_macro
391 decimal alignment in tables InsetTabular
-392 new beamer format InsetLayout
399 automatic mathdots loading \use_mathdots
407 vertical offset for multirows InsetTabular
411 support for polyglossia \language_package (the cases of
no package, of babel and of custom package is supported)
@@ -53,21 +52,7 @@ Format LaTeX feature LyX feature
443 unicode-math.sty InsetMath*
448
453 automatic stmaryrd loading \use_package stmaryrd
-454 beamer overprint environment InsetArgument, layout Overprint
- \begin{overprint}[maxlength]
- \onslide<slide> text ...
- \end{overprint}
-455 beamer frametitle command \begin_layout FrameTitle
- \frametitle<overlay>[short]{long}
457 automatic stackrel loading \use_package stackrel
-466 Powerdot updates:
- \pause[] layout Pause
- \onslide{}{} InsetFlex, InsetArgument
- \onslide*{}{} InsetFlex, InsetArgument
- \onslide+{}{} InsetFlex, InsetArgument
- \twocolumn[]{}{} Layout Twocolumn, InsetArgument
- \item[]<> InsetArgument
- \begin{enumerate|itemize|...}[] InsetArgument
526 Plural and capitalized refstyles InsetRef
533 Multibib support
\begin{btUnit}...\end{btUnit} \multibib
{none|part|chapter|section|subsection}
diff --git a/src/tex2lyx/tex2lyx.cpp b/src/tex2lyx/tex2lyx.cpp
index cbdd750..416f126 100644
--- a/src/tex2lyx/tex2lyx.cpp
+++ b/src/tex2lyx/tex2lyx.cpp
@@ -172,30 +172,32 @@ void add_known_theorem(string const & theorem, string
const & o1,
}
-Layout const * findLayoutWithoutModule(TextClass const & textclass,
- string const & name, bool command)
+Layout const * findLayoutWithoutModule(TextClass const & tc,
+ string const & name, bool command,
+ string const & latexparam)
{
- DocumentClass::const_iterator it = textclass.begin();
- DocumentClass::const_iterator en = textclass.end();
- for (; it != en; ++it) {
- if (it->latexname() == name &&
- ((command && it->isCommand()) || (!command &&
it->isEnvironment())))
- return &*it;
+ for (auto const & lay : tc) {
+ if (lay.latexname() == name &&
+ (latexparam.empty() ||
+ (!lay.latexparam().empty() && suffixIs(latexparam,
lay.latexparam()))) &&
+ ((command && lay.isCommand()) || (!command &&
lay.isEnvironment())))
+ return &lay;
}
return 0;
}
-InsetLayout const * findInsetLayoutWithoutModule(TextClass const & textclass,
- string const & name, bool
command)
+InsetLayout const * findInsetLayoutWithoutModule(TextClass const & tc,
+ string const & name, bool
command,
+ string const & latexparam)
{
- DocumentClass::InsetLayouts::const_iterator it =
textclass.insetLayouts().begin();
- DocumentClass::InsetLayouts::const_iterator en =
textclass.insetLayouts().end();
- for (; it != en; ++it) {
- if (it->second.latexname() == name &&
- ((command && it->second.latextype() ==
InsetLayout::COMMAND) ||
- (!command && it->second.latextype() ==
InsetLayout::ENVIRONMENT)))
- return &(it->second);
+ for (auto const & ilay : tc.insetLayouts()) {
+ if (ilay.second.latexname() == name &&
+ (latexparam.empty() ||
+ (!ilay.second.latexparam().empty() && suffixIs(latexparam,
ilay.second.latexparam()))) &&
+ ((command && ilay.second.latextype() ==
InsetLayout::COMMAND) ||
+ (!command && ilay.second.latextype() ==
InsetLayout::ENVIRONMENT)))
+ return &(ilay.second);
}
return 0;
}
diff --git a/src/tex2lyx/tex2lyx.h b/src/tex2lyx/tex2lyx.h
index 34da590..1791c2f 100644
--- a/src/tex2lyx/tex2lyx.h
+++ b/src/tex2lyx/tex2lyx.h
@@ -112,10 +112,12 @@ extern void add_known_environment(std::string const &
environment,
docstring const & end);
extern void add_known_theorem(std::string const & theorem,
std::string const & o1, bool o2, docstring const & definition);
-extern Layout const * findLayoutWithoutModule(TextClass const & textclass,
- std::string const & name, bool command);
-extern InsetLayout const * findInsetLayoutWithoutModule(
- TextClass const & textclass, std::string const & name, bool command);
+extern Layout const * findLayoutWithoutModule(TextClass const & tc,
+ std::string const & name, bool command,
+ std::string const & latexparam = std::string());
+extern InsetLayout const * findInsetLayoutWithoutModule(TextClass const & tc,
+ std::string const & name, bool command,
+ std::string const & latexparam = std::string());
/*!
* Check whether a module provides command (if \p command is true) or
* environment (if \p command is false) \p name, and add the module to the
diff --git a/src/tex2lyx/text.cpp b/src/tex2lyx/text.cpp
index f3617a8..2036ea6 100644
--- a/src/tex2lyx/text.cpp
+++ b/src/tex2lyx/text.cpp
@@ -67,6 +67,13 @@ void parse_text_in_inset(Parser & p, ostream & os, unsigned
flags, bool outer,
if (layout)
output_arguments(os, p, outer, false, string(), newcontext,
layout->latexargs());
+ // If we have a latex param, we eat it here.
+ if (!context.latexparam.empty()) {
+ ostringstream oss;
+ Context dummy(true, context.textclass);
+ parse_text(p, oss, FLAG_RDELIM, outer, dummy,
+ string(1, context.latexparam.back()));
+ }
parse_text(p, os, flags, outer, newcontext, rdelim);
if (layout)
output_arguments(os, p, outer, false, "post", newcontext,
@@ -697,24 +704,27 @@ void output_comment(Parser & p, ostream & os, string
const & s,
}
-Layout const * findLayout(TextClass const & textclass, string const & name,
bool command)
+Layout const * findLayout(TextClass const & textclass, string const & name,
bool command,
+ string const & latexparam = string())
{
- Layout const * layout = findLayoutWithoutModule(textclass, name,
command);
+ Layout const * layout = findLayoutWithoutModule(textclass, name,
command, latexparam);
if (layout)
return layout;
if (checkModule(name, command))
- return findLayoutWithoutModule(textclass, name, command);
+ return findLayoutWithoutModule(textclass, name, command,
latexparam);
return layout;
}
-InsetLayout const * findInsetLayout(TextClass const & textclass, string const
& name, bool command)
+InsetLayout const * findInsetLayout(TextClass const & textclass, string const
& name, bool command,
+ string const & latexparam = string())
{
- InsetLayout const * insetlayout =
findInsetLayoutWithoutModule(textclass, name, command);
+ InsetLayout const * insetlayout =
+ findInsetLayoutWithoutModule(textclass, name, command,
latexparam);
if (insetlayout)
return insetlayout;
if (checkModule(name, command))
- return findInsetLayoutWithoutModule(textclass, name, command);
+ return findInsetLayoutWithoutModule(textclass, name, command,
latexparam);
return insetlayout;
}
@@ -844,6 +854,13 @@ void output_command_layout(ostream & os, Parser & p, bool
outer,
context.check_deeper(os);
output_arguments(os, p, outer, true, string(), context,
context.layout->latexargs());
+ // If we have a latex param, we eat it here.
+ if (!parent_context.latexparam.empty()) {
+ ostringstream oss;
+ Context dummy(true, parent_context.textclass);
+ parse_text(p, oss, FLAG_RDELIM, outer, dummy,
+ string(1, parent_context.latexparam.back()));
+ }
parse_text(p, os, FLAG_ITEM, outer, context);
output_arguments(os, p, outer, false, "post", context,
context.layout->postcommandargs());
@@ -3269,6 +3286,25 @@ void parse_text(Parser & p, ostream & os, unsigned
flags, bool outer,
continue;
}
+ // Before we look for the layout name with star and alone
below, we check the layouts including
+ // the LateXParam, which might be one or several options or a
star.
+ // The single '=' is meant here.
+ if (context.new_layout_allowed &&
+ (newlayout = findLayout(context.textclass, t.cs(), true,
p.getCommandLatexParam()))) {
+ // store the latexparam here. This is eaten in
output_command_layout
+ context.latexparam = newlayout->latexparam();
+ // write the layout
+ output_command_layout(os, p, outer, context, newlayout);
+ p.skip_spaces();
+ if (!preamble.titleLayoutFound())
+ preamble.titleLayoutFound(newlayout->intitle);
+ set<string> const & req = newlayout->requires();
+ for (set<string>::const_iterator it = req.begin(); it
!= req.end(); ++it)
+
preamble.registerAutomaticallyLoadedPackage(*it);
+ continue;
+ }
+
+
// Starred section headings
// Must attempt to parse "Section*" before "Section".
if ((p.next_token().asInput() == "*") &&
@@ -5389,6 +5425,57 @@ void parse_text(Parser & p, ostream & os, unsigned
flags, bool outer,
continue;
}
+ // Before we look for the layout name alone below, we check the
layouts including the LateXParam, which
+ // might be one or several options or a star.
+ // The single '=' is meant here.
+ if ((newinsetlayout = findInsetLayout(context.textclass,
starredname, true, p.getCommandLatexParam()))) {
+ if (starred)
+ p.get_token();
+ p.skip_spaces();
+ context.check_layout(os);
+ // store the latexparam here. This is eaten in
parse_text_in_inset
+ context.latexparam = newinsetlayout->latexparam();
+ docstring name = newinsetlayout->name();
+ bool const caption = name.find(from_ascii("Caption:"))
== 0;
+ if (caption) {
+ // Already done for floating minted listings.
+ if (minted_float.empty()) {
+ begin_inset(os, "Caption ");
+ os << to_utf8(name.substr(8)) << '\n';
+ }
+ } else {
+ // FIXME: what do we do if the prefix is not
Flex: ?
+ if (prefixIs(name, from_ascii("Flex:")))
+ name.erase(0, 5);
+ begin_inset(os, "Flex ");
+ os << to_utf8(name) << '\n'
+ << "status collapsed\n";
+ }
+ if (!minted_float.empty()) {
+ parse_text_snippet(p, os, FLAG_ITEM, false,
context);
+ } else if (newinsetlayout->isPassThru()) {
+ // set catcodes to verbatim early, just in case.
+ p.setCatcodes(VERBATIM_CATCODES);
+ string delim = p.get_token().asInput();
+ if (delim != "{")
+ cerr << "Warning: bad delimiter for
command " << t.asInput() << endl;
+ //FIXME: handle error condition
+ string const arg = p.verbatimStuff("}").second;
+ Context newcontext(true, context.textclass);
+ if (newinsetlayout->forcePlainLayout())
+ newcontext.layout =
&context.textclass.plainLayout();
+ output_ert(os, arg, newcontext);
+ } else
+ parse_text_in_inset(p, os, FLAG_ITEM, false,
context, newinsetlayout);
+ if (caption)
+ p.skip_spaces();
+ // Minted caption insets are not closed here because
+ // we collect everything into the caption.
+ if (minted_float.empty())
+ end_inset(os);
+ continue;
+ }
+
// The single '=' is meant here.
if ((newinsetlayout = findInsetLayout(context.textclass,
starredname, true))) {
if (starred)