commit ce5b420a44ec1bfa5898c05236cc16ccec210343
Author: Juergen Spitzmueller <sp...@lyx.org>
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)

Reply via email to