]> git.lyx.org Git - lyx.git/commitdiff
tex2lyx: support qualified citation lists (biblatex)
authorJuergen Spitzmueller <spitz@lyx.org>
Sun, 4 Mar 2018 19:12:27 +0000 (20:12 +0100)
committerJuergen Spitzmueller <spitz@lyx.org>
Tue, 6 Mar 2018 07:20:18 +0000 (08:20 +0100)
(cherry picked from commit 0915e814814ab26732b6dd13fc1740cfbf64b5b4)

src/tex2lyx/Parser.cpp
src/tex2lyx/Parser.h
src/tex2lyx/TODO.txt
src/tex2lyx/text.cpp

index ec63b77da83e7c063724746427fa64be8c0c127e..35748b97694d4dbeaef1ef7e9e1cdea2299ef4cb 100644 (file)
@@ -533,11 +533,11 @@ string Parser::getArg(char left, char right, bool allow_escaping)
 }
 
 
-string Parser::getFullOpt(bool keepws)
+string Parser::getFullOpt(bool keepws, char left, char right)
 {
-       Arg arg = getFullArg('[', ']');
+       Arg arg = getFullArg(left, right);
        if (arg.first)
-               return '[' + arg.second + ']';
+               return left + arg.second + right;
        if (keepws)
                unskip_spaces(true);
        return string();
index cbdfcf723470a88a2cc2825db046172487b405c5..ca1edebfa2d658295f96debb73632db83eead415 100644 (file)
@@ -240,7 +240,8 @@ public:
         * Like getOpt(), but distinguishes between a missing argument ""
         * and an empty argument "[]".
         */
-       std::string getFullOpt(bool keepws = false);
+       std::string getFullOpt(bool keepws = false,
+                              char left = '[', char right = ']');
        /*!
         * \returns getArg('[', ']') including the brackets or the
         * empty string if there is no such argument.
index e5488b5936dc7b59254bd55fd6d40272edb560cb..2ea4d8bd32d908cd9828b64a8ee6d1542eee3baf 100644 (file)
@@ -102,17 +102,6 @@ Format LaTeX feature                        LyX feature
        - cjkangle (angle brackets)           \begin_inset Quotes k..
 526
        Plural and capitalized refstyles      InsetRef
-531    Biblatex "qualified citation lists"
-       \cites(pre)(post)[pre1][post1]{key1}[pre2][post2]{key2}...
-                                           \begin_inset CommandInset citation
-                                           LatexCmd cite
-                                           after "post"
-                                           before "pre"
-                                           key "key1,key2..."
-                                           pretextlist "key1 pre1\tab key2 pre2..."
-                                           posttextlist "key1 post1\tab key2 post2..."
-      Same for:
-      \Cites, \textcites, \Textcites, \parencites, \Parencites, \smartcites, \Smartcites, \autocites, Autocites
 533   Multibib support
       \begin{btUnit}...\end{btUnit}        \multibib {none|part|chapter|section|subsection}
         (if a part, chapter, section etc.
index 0e1290062be5d28eb9f42e3a4aeeb6a353340361..b2dd0eb65c85fbdbbc02fdb27ba14dcafb419813 100644 (file)
@@ -191,7 +191,8 @@ char const * const known_jurabib_commands[] = { "cite", "citet", "citep",
 char const * const known_biblatex_commands[] = { "cite", "Cite", "textcite", "Textcite",
 "parencite", "Parencite", "citeauthor", "Citeauthor", "citeyear", "smartcite", "Smartcite",
  "footcite", "Footcite", "autocite", "Autocite", "citetitle", "fullcite", "footfullcite",
-"supercite", 0 };
+"supercite", "cites", "Cites", "textcites", "Textcites", "parencites", "Parencites",
+"smartcites", "Smartcites", "autocites", "Autocites", 0 };
 
 // Whether we need to insert a bibtex inset in a comment
 bool need_commentbib = false;
@@ -2144,17 +2145,17 @@ void parse_text_attributes(Parser & p, ostream & os, unsigned flags, bool outer,
 
 /// get the arguments of a natbib or jurabib citation command
 void get_cite_arguments(Parser & p, bool natbibOrder,
-       string & before, string & after)
+       string & before, string & after, bool const qualified = false)
 {
        // We need to distinguish "" and "[]", so we can't use p.getOpt().
 
        // text before the citation
        before.clear();
        // text after the citation
-       after = p.getFullOpt();
+       after = qualified ? p.getFullOpt(false, '(', ')') : p.getFullOpt();
 
        if (!after.empty()) {
-               before = p.getFullOpt();
+               before = qualified ? p.getFullOpt(false, '(', ')') : p.getFullOpt();
                if (natbibOrder && !before.empty())
                        swap(before, after);
        }
@@ -3830,14 +3831,23 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                preamble.citeEngine("natbib");
                }
 
-               else if (use_biblatex
+               else if ((use_biblatex
                         && is_known(t.cs(), known_biblatex_commands)
                         && ((t.cs() == "cite"
                             || t.cs() == "citeauthor"
                             || t.cs() == "Citeauthor"
                             || t.cs() == "parencite"
                             || t.cs() == "citetitle")
-                        || p.next_token().asInput() != "*")) {
+                        || p.next_token().asInput() != "*"))
+                       || (use_biblatex_natbib
+                           && (is_known(t.cs(), known_biblatex_commands)
+                             || is_known(t.cs(), known_natbib_commands))
+                           && ((t.cs() == "cite" || t.cs() == "citet" || t.cs() == "Citet"
+                              || t.cs() == "citep" || t.cs() == "Citep" || t.cs() == "citealt"
+                              || t.cs() == "Citealt" || t.cs() == "citealp" || t.cs() == "Citealp"
+                              || t.cs() == "citeauthor" || t.cs() == "Citeauthor"
+                              || t.cs() == "parencite" || t.cs() == "citetitle")
+                              || p.next_token().asInput() != "*"))){
                        context.check_layout(os);
                        string command = t.cs();
                        if (p.next_token().asInput() == "*") {
@@ -3845,87 +3855,15 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                p.get_token();
                        }
 
-                       // text before the citation
-                       string before;
-                       // text after the citation
-                       string after;
-                       get_cite_arguments(p, true, before, after);
-
-                       // These use natbib cmd names in LyX
-                       // for inter-citeengine compativility
-                       if (command == "citeyear")
-                               command = "citebyear";
-                       else if (command == "cite*")
-                               command = "citeyear";
-                       else if (command == "textcite")
-                               command = "citet";
-                       else if (command == "Textcite")
-                               command = "Citet";
-                       else if (command == "parencite")
-                               command = "citep";
-                       else if (command == "Parencite")
-                               command = "Citep";
-                       else if (command == "parencite*")
-                               command = "citeyearpar";
-                       else if (command == "smartcite")
-                               command = "footcite";
-                       else if (command == "Smartcite")
-                               command = "Footcite";
-
-                       if (before.empty() && after == "[]")
-                               // avoid \cite[]{a}
-                               after.erase();
-                       else if (before == "[]" && after == "[]") {
-                               // avoid \cite[][]{a}
-                               before.erase();
-                               after.erase();
-                       }
-                       // remove the brackets around after and before
-                       if (!after.empty()) {
-                               after.erase(0, 1);
-                               after.erase(after.length() - 1, 1);
-                               after = convert_command_inset_arg(after);
-                       }
-                       if (!before.empty()) {
-                               before.erase(0, 1);
-                               before.erase(before.length() - 1, 1);
-                               before = convert_command_inset_arg(before);
-                       }
-                       begin_command_inset(os, "citation", command);
-                       os << "after " << '"' << after << '"' << "\n";
-                       os << "before " << '"' << before << '"' << "\n";
-                       os << "key \""
-                          << convert_command_inset_arg(p.verbatim_item())
-                          << "\"\n"
-                          << "literal \"true\"\n";
-                       end_inset(os);
-                       // Need to set the cite engine if biblatex is loaded by
-                       // the document class directly
-                       if (preamble.citeEngine() == "basic")
-                               preamble.citeEngine("biblatex");
-               }
-
-               else if (use_biblatex_natbib
-                        && (is_known(t.cs(), known_biblatex_commands)
-                            || is_known(t.cs(), known_natbib_commands))
-                        && ((t.cs() == "cite" || t.cs() == "citet" || t.cs() == "Citet"
-                             || t.cs() == "citep" || t.cs() == "Citep" || t.cs() == "citealt"
-                             || t.cs() == "Citealt" || t.cs() == "citealp" || t.cs() == "Citealp"
-                             || t.cs() == "citeauthor" || t.cs() == "Citeauthor"
-                             || t.cs() == "parencite" || t.cs() == "citetitle")
-                           || p.next_token().asInput() != "*")) {
-                       context.check_layout(os);
-                       string command = t.cs();
-                       if (p.next_token().asInput() == "*") {
-                               command += '*';
-                               p.get_token();
-                       }
+                       bool const qualified = suffixIs(command, "s");
+                       if (qualified)
+                               command = rtrim(command, "s");
 
                        // text before the citation
                        string before;
                        // text after the citation
                        string after;
-                       get_cite_arguments(p, true, before, after);
+                       get_cite_arguments(p, true, before, after, qualified);
 
                        // These use natbib cmd names in LyX
                        // for inter-citeengine compativility
@@ -3948,10 +3886,11 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        else if (command == "Smartcite")
                                command = "Footcite";
 
-                       if (before.empty() && after == "[]")
+                       string const emptyarg = qualified ? "()" : "[]";
+                       if (before.empty() && after == emptyarg)
                                // avoid \cite[]{a}
                                after.erase();
-                       else if (before == "[]" && after == "[]") {
+                       else if (before == emptyarg && after == emptyarg) {
                                // avoid \cite[][]{a}
                                before.erase();
                                after.erase();
@@ -3967,18 +3906,77 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                before.erase(before.length() - 1, 1);
                                before = convert_command_inset_arg(before);
                        }
+                       string keys, pretextlist, posttextlist;
+                       if (qualified) {
+                               map<string, string> pres;
+                               map<string, string> posts;
+                               vector<string> lkeys;
+                               // text before the citation
+                               string lbefore;
+                               // text after the citation
+                               string lafter;
+                               string lkey;
+                               while (true) {
+                                       get_cite_arguments(p, true, lbefore, lafter);
+                                       // remove the brackets around after and before
+                                       if (!lafter.empty()) {
+                                               lafter.erase(0, 1);
+                                               lafter.erase(lafter.length() - 1, 1);
+                                               lafter = convert_command_inset_arg(lafter);
+                                       }
+                                       if (!lbefore.empty()) {
+                                               lbefore.erase(0, 1);
+                                               lbefore.erase(lbefore.length() - 1, 1);
+                                               lbefore = convert_command_inset_arg(lbefore);
+                                       }
+                                       if (lbefore.empty() && lafter == "[]")
+                                               // avoid \cite[]{a}
+                                               lafter.erase();
+                                       else if (lbefore == "[]" && lafter == "[]") {
+                                               // avoid \cite[][]{a}
+                                               lbefore.erase();
+                                               lafter.erase();
+                                       }
+                                       lkey = p.getArg('{', '}');
+                                       if (lkey.empty())
+                                               break;
+                                       if (!lbefore.empty())
+                                               pres.insert(make_pair(lkey, lbefore));
+                                       if (!lafter.empty())
+                                               posts.insert(make_pair(lkey, lafter));
+                                       lkeys.push_back(lkey);
+                               }
+                               keys = convert_command_inset_arg(getStringFromVector(lkeys));
+                               for (auto const & ptl : pres) {
+                                       if (!pretextlist.empty())
+                                               pretextlist += '\t';
+                                       pretextlist += ptl.first + " " + ptl.second;
+                               }
+                               for (auto const & potl : posts) {
+                                       if (!posttextlist.empty())
+                                               posttextlist += '\t';
+                                       posttextlist += potl.first + " " + potl.second;
+                               }
+                       } else
+                               keys = convert_command_inset_arg(p.verbatim_item());
                        begin_command_inset(os, "citation", command);
                        os << "after " << '"' << after << '"' << "\n";
                        os << "before " << '"' << before << '"' << "\n";
                        os << "key \""
-                          << convert_command_inset_arg(p.verbatim_item())
-                          << "\"\n"
-                          << "literal \"true\"\n";
+                          << keys
+                          << "\"\n";
+                       if (!pretextlist.empty())
+                               os << "pretextlist " << '"'  << pretextlist << '"' << "\n";
+                       if (!posttextlist.empty())
+                               os << "posttextlist " << '"'  << posttextlist << '"' << "\n";
+                       os << "literal \"true\"\n";
                        end_inset(os);
                        // Need to set the cite engine if biblatex is loaded by
                        // the document class directly
                        if (preamble.citeEngine() == "basic")
-                               preamble.citeEngine("biblatex-natbib");
+                               use_biblatex_natbib ?
+                                         preamble.citeEngine("biblatex-natbib")
+                                       : preamble.citeEngine("biblatex");
                }
 
                else if (use_jurabib &&