]> git.lyx.org Git - lyx.git/blobdiff - src/tex2lyx/text.cpp
tex2lyx: support for plural and capitalized refstyle
[lyx.git] / src / tex2lyx / text.cpp
index 1bee520b0ed8c730d8dc717ef43374f749dc15e5..38b03d91793f29dbab834e819492a968837f3e64 100644 (file)
@@ -528,6 +528,35 @@ string guessQuoteStyle(string in, bool const opening)
 }
 
 
+string const fromPolyglossiaEnvironment(string const s)
+{
+       // Since \arabic is taken by the LaTeX kernel,
+       // the Arabic polyglossia environment is upcased
+       if (s == "Arabic")
+               return "arabic";
+       else
+               return s;
+}
+
+
+string uncapitalize(string const s)
+{
+       docstring in = from_ascii(s);
+       char_type t = lowercase(s[0]);
+       in[0] = t;
+       return to_ascii(in);
+}
+
+
+bool isCapitalized(string const s)
+{
+       docstring in = from_ascii(s);
+       char_type t = uppercase(s[0]);
+       in[0] = t;
+       return to_ascii(in) == s;
+}
+
+
 } // namespace
 
 
@@ -1483,7 +1512,7 @@ void parse_listings(Parser & p, ostream & os, Context & parent_context,
                os << "inline true\n";
        else
                os << "inline false\n";
-       os << "status collapsed\n";
+       os << "status open\n";
        Context context(true, parent_context.textclass);
        context.layout = &parent_context.textclass.plainLayout();
        if (use_minted && prefixIs(minted_nonfloat_caption, "[t]")) {
@@ -1565,6 +1594,14 @@ void parse_unknown_environment(Parser & p, string const & name, ostream & os,
        if (specialfont)
                parent_context.new_layout_allowed = false;
        output_ert_inset(os, "\\begin{" + name + "}", parent_context);
+       // Try to handle options: Look if we have an optional arguments,
+       // and if so, put the brackets in ERT.
+       while (p.hasOpt()) {
+               p.get_token(); // eat '['
+               output_ert_inset(os, "[", parent_context);
+               os << parse_text_snippet(p, FLAG_BRACK_LAST, outer, parent_context);
+               output_ert_inset(os, "]", parent_context);
+       }
        parse_text_snippet(p, os, flags, outer, parent_context);
        output_ert_inset(os, "\\end{" + name + "}", parent_context);
        if (specialfont)
@@ -1597,7 +1634,8 @@ void parse_environment(Parser & p, ostream & os, bool outer,
                }
        }
 
-       else if (is_known(name, preamble.polyglossia_languages)) {
+       // We need to use fromPolyglossiaEnvironment die to Arabic > arabic
+       else if (is_known(fromPolyglossiaEnvironment(name), preamble.polyglossia_languages)) {
                // We must begin a new paragraph if not already done
                if (! parent_context.atParagraphStart()) {
                        parent_context.check_end_layout(os);
@@ -1605,7 +1643,8 @@ void parse_environment(Parser & p, ostream & os, bool outer,
                }
                // save the language in the context so that it is
                // handled by parse_text
-               parent_context.font.language = preamble.polyglossia2lyx(name);
+               parent_context.font.language =
+                       preamble.polyglossia2lyx(fromPolyglossiaEnvironment(name));
                parse_text(p, os, FLAG_END, outer, parent_context);
                // Just in case the environment is empty
                parent_context.extra_stuff.erase();
@@ -1617,13 +1656,23 @@ void parse_environment(Parser & p, ostream & os, bool outer,
        else if (unstarred_name == "tabular" || name == "longtable") {
                eat_whitespace(p, os, parent_context, false);
                string width = "0pt";
+               string halign;
+               if (name == "longtable" && p.hasOpt()) {
+                       string const opt = p.getArg('[', ']');
+                       if (opt == "c")
+                               halign = "center";
+                       else if (opt == "l")
+                               halign = "left";
+                       else if (opt == "r")
+                               halign = "right";
+               }
                if (name == "tabular*") {
                        width = lyx::translate_len(p.getArg('{', '}'));
                        eat_whitespace(p, os, parent_context, false);
                }
                parent_context.check_layout(os);
                begin_inset(os, "Tabular ");
-               handle_tabular(p, os, name, width, parent_context);
+               handle_tabular(p, os, name, width, halign, parent_context);
                end_inset(os);
                p.skip_spaces();
        }
@@ -1792,6 +1841,16 @@ void parse_environment(Parser & p, ostream & os, bool outer,
                preamble.registerAutomaticallyLoadedPackage("tipa");
                preamble.registerAutomaticallyLoadedPackage("tipx");
        }
+       
+       else if (name == parent_context.textclass.titlename()
+                && parent_context.textclass.titletype() == TITLE_ENVIRONMENT) {
+                       parse_text(p, os, FLAG_END, outer, parent_context);
+                       // Just in case the environment is empty
+                       parent_context.extra_stuff.erase();
+                       // We must begin a new paragraph
+                       parent_context.new_paragraph(os);
+                       p.skip_spaces();
+       }
 
        else if (name == "CJK") {
                // the scheme is \begin{CJK}{encoding}{mapping}text\end{CJK}
@@ -1901,6 +1960,20 @@ void parse_environment(Parser & p, ostream & os, bool outer,
                p.skip_spaces();
        }
 
+       else if (name == "btUnit") {
+               string const nt = p.next_next_token().cs();
+               // Do not attempt to overwrite a former diverging multibib.
+               // Those are output as ERT instead.
+               if ((nt == "part" || nt == "chapter"
+                    || nt == "section" || nt == "subsection")
+                  && (preamble.multibib().empty() || preamble.multibib() == nt)) {
+                       parse_text(p, os, FLAG_END, outer, parent_context);
+                       preamble.multibib(nt);
+               } else
+                       parse_unknown_environment(p, name, os, FLAG_END, outer,
+                                                 parent_context);
+       }
+
        else if (name == "framed" || name == "shaded") {
                eat_whitespace(p, os, parent_context, false);
                parse_outer_box(p, os, FLAG_END, outer, parent_context, name, "");
@@ -2001,6 +2074,7 @@ void parse_environment(Parser & p, ostream & os, bool outer,
                                                parse_text_snippet(p, FLAG_ITEM,
                                                        false, parent_context);
                                        minted_nonfloat_caption = "[b]" + caption;
+                                       eat_whitespace(p, os, parent_context, true);
                                }
                        }
                        p.popPosition();
@@ -2637,7 +2711,9 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
        // nocite{*} option (needed for bibtex inset)
        string btprint;
        string contentslineContent;
-       string bibliographystyle = "default";
+       // Some classes provide a \bibliographystyle, so do not output
+       // any if none is explicitly set.
+       string bibliographystyle;
        bool const use_natbib = isProvided("natbib");
        bool const use_jurabib = isProvided("jurabib");
        bool const use_biblatex = isProvided("biblatex")
@@ -3311,7 +3387,6 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        continue;
                }
 
-
                // Starred section headings
                // Must attempt to parse "Section*" before "Section".
                if ((p.next_token().asInput() == "*") &&
@@ -3406,6 +3481,19 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        continue;
                }
 
+               if (t.cs() == "xymatrix") {
+                       // we must open a new math because LyX's xy support is in math
+                       context.check_layout(os);
+                       begin_inset(os, "Formula ");
+                       os << '$';
+                       os << "\\" << t.cs() << '{';
+                       parse_math(p, os, FLAG_ITEM, MATH_MODE);
+                       os << '}' << '$';
+                       end_inset(os);
+                       preamble.registerAutomaticallyLoadedPackage("xy");
+                       continue;
+               }
+
                if (t.cs() == "includegraphics") {
                        bool const clip = p.next_token().asInput() == "*";
                        if (clip)
@@ -3610,7 +3698,9 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        continue;
                }
 
-               else if (t.cs() == "makeindex" || t.cs() == "maketitle" || t.cs() == "makebeamertitle") {
+               else if (t.cs() == "makeindex"
+                        || (t.cs() == context.textclass.titlename()
+                            && context.textclass.titletype() == TITLE_COMMAND_AFTER)) {
                        if (preamble.titleLayoutFound()) {
                                // swallow this
                                skip_spaces_braces(p);
@@ -3969,21 +4059,37 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        continue;
                }
 
-               // handle refstyle first to catch \eqref which can also occur
-               // without refstyle. Only recognize these commands if
+               // Handle refstyle first in order to to catch \eqref, because this
+               // can also occur without refstyle. Only recognize these commands if
                // refstyle.sty was found in the preamble (otherwise \eqref
                // and user defined ref commands could be misdetected).
-               if ((where = is_known(t.cs(), known_refstyle_commands))
+               // We uncapitalize the input in order to catch capitalized commands
+               // such as \Eqref.
+               if ((where = is_known(uncapitalize(t.cs()), known_refstyle_commands))
                     && preamble.refstyle()) {
+                       string const cap = isCapitalized(t.cs()) ? "true" : "false";
+                       string plural = "false";
+                       // Catch the plural option [s]
+                       if (p.hasOpt()) {
+                               string const opt = p.getOpt();
+                               if (opt == "[s]")
+                                       plural = "true";
+                               else {
+                                       // LyX does not yet support other optional arguments of ref commands
+                                       output_ert_inset(os, t.asInput() + opt + "{" +
+                                              p.verbatim_item() + '}', context);
+                                       continue;
+                               }
+                       }
                        context.check_layout(os);
                        begin_command_inset(os, "ref", "formatted");
                        os << "reference \"";
                        os << known_refstyle_prefixes[where - known_refstyle_commands]
                           << ":";
-                       os << convert_literate_command_inset_arg(p.verbatim_item())
+                       os << convert_literate_command_inset_arg(p.getArg('{', '}'))
                           << "\"\n";
-                       os << "plural \"false\"\n";
-                       os << "caps \"false\"\n";
+                       os << "plural \"" << plural << "\"\n";
+                       os << "caps \"" << cap << "\"\n";
                        os << "noprefix \"false\"\n";
                        end_inset(os);
                        preamble.registerAutomaticallyLoadedPackage("refstyle");
@@ -4012,8 +4118,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                        preamble.registerAutomaticallyLoadedPackage("prettyref");
                        } else {
                                // LyX does not yet support optional arguments of ref commands
-                               output_ert_inset(os, t.asInput() + '[' + opt + "]{" +
-                                      p.verbatim_item() + '}', context);
+                               output_ert_inset(os, t.asInput() + opt + "{" +
+                                                p.verbatim_item() + '}', context);
                        }
                        continue;
                }
@@ -4431,6 +4537,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                // so simply skip it.
                                parse_text_snippet(p, FLAG_ITEM, false, context);
                        }
+                       eat_whitespace(p, os, context, true);
                        continue;
                }
 
@@ -4765,22 +4872,48 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
 
                if (t.cs() == "input" || t.cs() == "include"
                    || t.cs() == "verbatiminput"
-                   || t.cs() == "lstinputlisting") {
+                   || t.cs() == "lstinputlisting"
+                   || t.cs() == "inputminted") {
                        string name = t.cs();
                        if (name == "verbatiminput"
                            && p.next_token().asInput() == "*")
                                name += p.get_token().asInput();
                        context.check_layout(os);
                        string lstparams;
-                       bool literal = false;
                        if (name == "lstinputlisting" && p.hasOpt()) {
                                lstparams = p.getArg('[', ']');
-                               pair<bool, string> oa = convert_latexed_command_inset_arg(lstparams);
-                               literal = !oa.first;
-                               if (literal)
+                               lstparams = subst(lstparams, "\n", " ");
+                       } else if (name == "inputminted") {
+                               name = "lstinputlisting";
+                               string const lang = p.getArg('{', '}');
+                               if (lang != "tex") {
+                                       string cmd = "\\inputminted{" + lang + "}{";
+                                       cmd += p.getArg('{', '}') + "}";
+                                       output_ert_inset(os, cmd, context);
+                                       continue;
+                               }
+                               if (prefixIs(minted_nonfloat_caption, "[t]")) {
+                                       minted_nonfloat_caption.erase(0,3);
+                                       // extract label and caption from the already produced LyX code
+                                       vector<string> nfc = getVectorFromString(minted_nonfloat_caption, "\n");
+                                       string const caption = nfc.front();
+                                       string label;
+                                       vector<string>::iterator it =
+                                               find(nfc.begin(), nfc.end(), "LatexCommand label");
+                                       if (it != nfc.end()) {
+                                               ++it;
+                                               if (it != nfc.end())
+                                                       label = *it;
+                                               label = support::split(label, '"');
+                                               label.pop_back();
+                                       }
+                                       minted_nonfloat_caption.clear();
+                                       lstparams = "caption=" + caption;
+                                       if (!label.empty())
+                                               lstparams += ",label=" + label;
                                        lstparams = subst(lstparams, "\n", " ");
+                               }
                        }
-                       string lit = literal ? "\"true\"" : "\"false\"";
                        string filename(normalize_filename(p.getArg('{', '}')));
                        string const path = getMasterFilePath(true);
                        // We want to preserve relative / absolute filenames,
@@ -4890,7 +5023,6 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                      "filename \"" << outname << "\"\n";
                                if (!lstparams.empty())
                                        os << "lstparams \"" << lstparams << "\"\n";
-                               os << "literal " << lit << "\n";
                                if (t.cs() == "verbatiminput")
                                        preamble.registerAutomaticallyLoadedPackage("verbatim");
                        }
@@ -5783,8 +5915,18 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                p.get_token();  // Eat '*'
                                name += '*';
                        }
-                       if (!parse_command(name, p, os, outer, context))
+                       if (!parse_command(name, p, os, outer, context)) {
                                output_ert_inset(os, name, context);
+                               // Try to handle options of unknown commands:
+                               // Look if we have an optional arguments,
+                               // and if so, put the brackets in ERT.
+                               while (p.hasOpt()) {
+                                       p.get_token(); // eat '['
+                                       output_ert_inset(os, "[", context);
+                                       os << parse_text_snippet(p, FLAG_BRACK_LAST, outer, context);
+                                       output_ert_inset(os, "]", context);
+                               }
+                       }
                }
        }
 }