tex2lyx: add support for LaTeXParam

Part of #11068

(cherry picked from commit 506ae2d2ea)
This commit is contained in:
Juergen Spitzmueller 2018-03-16 12:56:17 +01:00
parent 42863eac92
commit ce5b420a44
7 changed files with 146 additions and 42 deletions

View File

@ -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;

View File

@ -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())

View File

@ -278,6 +278,11 @@ public:
* This function is designed to parse verbatim commands.
*/
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

View File

@ -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}

View File

@ -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;
}

View File

@ -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

View File

@ -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)