commit 958f6193ed07060f98b752262568a225bda13ae4
Author: Juergen Spitzmueller <sp...@lyx.org>
Date:   Tue Jan 3 13:11:11 2017 +0100

    Differentiate InsetCite
    
    Next to the cmd name, introduce optional latex names (that might differ
    from the cmd name) and aliases (that are "obsoleted by" the cmd).
    
    This enhances portability between the engines.
---
 src/BiblioInfo.cpp                |   23 ++++++++++-------
 src/BiblioInfo.h                  |    6 +++-
 src/BufferParams.cpp              |   11 +++++++-
 src/BufferParams.h                |    2 +
 src/Citation.h                    |    8 ++++--
 src/TextClass.cpp                 |   49 +++++++++++++++++++++++++++++++-----
 src/TextClass.h                   |    5 ++++
 src/frontends/qt4/GuiCitation.cpp |    5 ++-
 src/insets/InsetCitation.cpp      |   42 ++++++++++++++++++++++++++++---
 src/insets/InsetCitation.h        |    2 +
 10 files changed, 124 insertions(+), 29 deletions(-)

diff --git a/src/BiblioInfo.cpp b/src/BiblioInfo.cpp
index 406d0e2..dedcd12 100644
--- a/src/BiblioInfo.cpp
+++ b/src/BiblioInfo.cpp
@@ -1019,7 +1019,7 @@ vector<docstring> const BiblioInfo::getCiteStrings(
        string style;
        vector<docstring> vec(styles.size());
        for (size_t i = 0; i != vec.size(); ++i) {
-               style = styles[i].cmd;
+               style = styles[i].name;
                vec[i] = getLabel(keys, buf, style, false, max_size, before, 
after, dialog);
        }
 
@@ -1181,32 +1181,35 @@ void BiblioInfo::makeCitationLabels(Buffer const & buf)
 //////////////////////////////////////////////////////////////////////
 
 
-CitationStyle citationStyleFromString(string const & command)
+CitationStyle citationStyleFromString(string const & command,
+                                     BufferParams const & params)
 {
        CitationStyle cs;
        if (command.empty())
                return cs;
 
-       string cmd = command;
-       if (isUpperCase(cmd[0])) {
+       string const alias = params.getCiteAlias(command);
+       string cmd = alias.empty() ? command : alias;
+       if (isUpperCase(command[0])) {
                cs.forceUpperCase = true;
                cmd[0] = lowercase(cmd[0]);
        }
 
-       size_t const n = cmd.size() - 1;
-       if (cmd[n] == '*') {
+       size_t const n = command.size() - 1;
+       if (command[n] == '*') {
                cs.fullAuthorList = true;
-               cmd = cmd.substr(0, n);
+               if (suffixIs(cmd, '*'))
+                       cmd = cmd.substr(0, cmd.size() - 1);
        }
 
-       cs.cmd = cmd;
+       cs.name = cmd;
        return cs;
 }
 
 
-string citationStyleToString(const CitationStyle & cs)
+string citationStyleToString(const CitationStyle & cs, bool const latex)
 {
-       string cmd = cs.cmd;
+       string cmd = latex ? cs.cmd : cs.name;
        if (cs.forceUpperCase)
                cmd[0] = uppercase(cmd[0]);
        if (cs.fullAuthorList)
diff --git a/src/BiblioInfo.h b/src/BiblioInfo.h
index 5d485c9..1a1f324 100644
--- a/src/BiblioInfo.h
+++ b/src/BiblioInfo.h
@@ -17,6 +17,7 @@
 
 #include "support/docstring.h"
 
+#include "BufferParams.h"
 #include "Citation.h"
 
 #include <map>
@@ -29,9 +30,10 @@ namespace lyx {
 class Buffer;
 
 /// \param latex_str a LaTeX command, "cite", "Citep*", etc
-CitationStyle citationStyleFromString(std::string const & latex_str);
+CitationStyle citationStyleFromString(std::string const & latex_str,
+                                     BufferParams const &);
 /// the other way round
-std::string citationStyleToString(CitationStyle const &);
+std::string citationStyleToString(CitationStyle const &, bool const latex = 
false);
 
 
 /// Class to represent information about a BibTeX or
diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp
index 7a726eb..5afb79c 100644
--- a/src/BufferParams.cpp
+++ b/src/BufferParams.cpp
@@ -3251,6 +3251,15 @@ bool const & BufferParams::fullAuthorList() const
 }
 
 
+string BufferParams::getCiteAlias(string const & s) const
+{
+       map<string,string> aliases = documentClass().citeCommandAliases();
+       if (aliases.find(s) != aliases.end())
+               return aliases[s];
+       return string();
+}
+
+
 void BufferParams::setCiteEngine(string const & engine)
 {
        clearCiteEngine();
@@ -3271,7 +3280,7 @@ vector<string> BufferParams::citeCommands() const
        vector<string> commands =
                documentClass().citeCommands(citeEngineType());
        if (commands.empty())
-               commands.push_back(default_style.cmd);
+               commands.push_back(default_style.name);
        return commands;
 }
 
diff --git a/src/BufferParams.h b/src/BufferParams.h
index 8748600..30b65e0 100644
--- a/src/BufferParams.h
+++ b/src/BufferParams.h
@@ -471,6 +471,8 @@ public:
        std::string const & defaultBiblioStyle() const;
        /// whether the BibTeX style supports full author lists
        bool const & fullAuthorList() const;
+       /// Check if a citation style is an alias to another style
+       std::string getCiteAlias(std::string const & s) const;
 
        /// options for pdf output
        PDFOptions & pdfoptions();
diff --git a/src/Citation.h b/src/Citation.h
index 7f0503f..42ddfc2 100644
--- a/src/Citation.h
+++ b/src/Citation.h
@@ -30,10 +30,12 @@ class CitationStyle
 {
 public:
        ///
-       CitationStyle() : cmd("cite"), forceUpperCase(false), 
fullAuthorList(false),
-               textAfter(false), textBefore(false) {}
+       CitationStyle() : name("cite"), cmd("cite"), forceUpperCase(false),
+               fullAuthorList(false), textAfter(false), textBefore(false) {}
 
-       /// the LaTeX command
+       /// the LyX name
+       std::string name;
+       /// the LaTeX command (might differ from the LyX name)
        std::string cmd;
        /// upper casing author prefixes (van -> Van)
        bool forceUpperCase;
diff --git a/src/TextClass.cpp b/src/TextClass.cpp
index 2a82cc9..03c6c79 100644
--- a/src/TextClass.cpp
+++ b/src/TextClass.cpp
@@ -1036,7 +1036,6 @@ bool TextClass::readCiteEngine(Lexer & lexrc)
                        getout = true;
                        continue;
                }
-               string cmd;
                CitationStyle cs;
                char ichar = def[0];
                if (ichar == '#')
@@ -1046,20 +1045,56 @@ bool TextClass::readCiteEngine(Lexer & lexrc)
                        def[0] = lowercase(ichar);
                }
 
+               /** For portability reasons (between different
+                *  cite engines such as natbib and biblatex),
+                *  we distinguish between:
+                *  1. The LyX name as output in the LyX file
+                *  2. Possible aliases that might fall back to
+                *     the given LyX name in the current engine
+                *  3. The actual LaTeX command that is output
+                *  (2) and (3) are optional.
+                *  The syntax is:
+                *  LyXName|alias,nextalias*[][]=latexcmd
+                */
+               enum ScanMode {
+                       LyXName,
+                       Alias,
+                       LaTeXCmd
+               };
+
+               ScanMode mode = LyXName;
+               string lyx_cmd;
+               string alias;
+               string latex_cmd;
                size_t const n = def.size();
                for (size_t i = 0; i != n; ++i) {
                        ichar = def[i];
-                       if (ichar == '*')
+                       if (ichar == '|')
+                               mode = Alias;
+                       else if (ichar == '=')
+                               mode = LaTeXCmd;
+                       else if (mode == LaTeXCmd)
+                               latex_cmd += ichar;
+                       else if (ichar == '*')
                                cs.fullAuthorList = true;
                        else if (ichar == '[' && cs.textAfter)
                                cs.textBefore = true;
                        else if (ichar == '[')
                                cs.textAfter = true;
-                       else if (ichar != ']')
-                               cmd += ichar;
+                       else if (ichar != ']') {
+                               if (mode == Alias)
+                                       alias += ichar;
+                               else
+                                       lyx_cmd += ichar;
+                       }
+               }
+               cs.name = lyx_cmd;
+               cs.cmd = latex_cmd.empty() ? lyx_cmd : latex_cmd;
+               if (!alias.empty()) {
+                       vector<string> const aliases = 
getVectorFromString(alias);
+                       for (string const &s: aliases)
+                               cite_command_aliases_[s] = lyx_cmd;
                }
-
-               cs.cmd = cmd;
                if (type & ENGINE_TYPE_AUTHORYEAR)
                        cite_styles_[ENGINE_TYPE_AUTHORYEAR].push_back(cs);
                if (type & ENGINE_TYPE_NUMERICAL)
@@ -1792,7 +1827,7 @@ vector<string> const DocumentClass::citeCommands(
        vector<string> cmds;
        for (; it != end; ++it) {
                CitationStyle const cite = *it;
-               cmds.push_back(cite.cmd);
+               cmds.push_back(cite.name);
        }
        return cmds;
 }
diff --git a/src/TextClass.h b/src/TextClass.h
index 51bb417..319ea96 100644
--- a/src/TextClass.h
+++ b/src/TextClass.h
@@ -333,6 +333,8 @@ protected:
        std::map<CiteEngineType, std::map<std::string, std::string> > 
cite_macros_;
        /// The default BibTeX bibliography style file
        std::map<std::string, std::string> cite_default_biblio_style_;
+       /// Citation command aliases
+       std::map<std::string, std::string> cite_command_aliases_;
        /// Whether full author lists are supported
        bool cite_full_author_list_;
        /// The possible citation styles
@@ -494,6 +496,9 @@ public:
        std::map<std::string, std::string> const & defaultBiblioStyle() const
        { return cite_default_biblio_style_; }
        ///
+       std::map<std::string, std::string> const & citeCommandAliases() const
+       { return cite_command_aliases_; }
+       ///
        bool const & fullAuthorList() const { return cite_full_author_list_; }
 protected:
        /// Constructs a DocumentClass based upon a LayoutFile.
diff --git a/src/frontends/qt4/GuiCitation.cpp 
b/src/frontends/qt4/GuiCitation.cpp
index 10c9167..459a51e 100644
--- a/src/frontends/qt4/GuiCitation.cpp
+++ b/src/frontends/qt4/GuiCitation.cpp
@@ -555,7 +555,8 @@ void GuiCitation::init()
 
        // Initialize the citation formatting
        string const & cmd = params_.getCmdName();
-       CitationStyle const cs = citationStyleFromString(cmd);
+       CitationStyle const cs =
+               citationStyleFromString(cmd, documentBuffer().params());
        forceuppercaseCB->setChecked(cs.forceUpperCase);
        fulllistCB->setChecked(cs.fullAuthorList &&
                documentBuffer().params().fullAuthorList());
@@ -576,7 +577,7 @@ void GuiCitation::init()
                // Find the citation style
                vector<string> const & cmds = citeCmds_;
                vector<string>::const_iterator cit =
-                       std::find(cmds.begin(), cmds.end(), cs.cmd);
+                       std::find(cmds.begin(), cmds.end(), cs.name);
                int i = 0;
                if (cit != cmds.end())
                        i = int(cit - cmds.begin());
diff --git a/src/insets/InsetCitation.cpp b/src/insets/InsetCitation.cpp
index 7063cae..9327129 100644
--- a/src/insets/InsetCitation.cpp
+++ b/src/insets/InsetCitation.cpp
@@ -21,6 +21,7 @@
 #include "DispatchResult.h"
 #include "FuncCode.h"
 #include "FuncRequest.h"
+#include "FuncStatus.h"
 #include "LaTeXFeatures.h"
 #include "output_xhtml.h"
 #include "ParIterator.h"
@@ -124,6 +125,29 @@ void InsetCitation::doDispatch(Cursor & cur, FuncRequest & 
cmd)
 }
 
 
+bool InsetCitation::getStatus(Cursor & cur, FuncRequest const & cmd,
+       FuncStatus & status) const
+{
+       switch (cmd.action()) {
+       // Handle the alias case
+       case LFUN_INSET_MODIFY:
+               if (cmd.getArg(0) == "changetype") {
+                       string cmdname = getCmdName();
+                       string const alias = 
buffer().params().getCiteAlias(cmdname);
+                       if (!alias.empty())
+                               cmdname = alias;
+                       string const newtype = cmd.getArg(1);
+                       status.setEnabled(isCompatibleCommand(newtype));
+                       status.setOnOff(newtype == cmdname);
+               }
+               status.setEnabled(true);
+               return true;
+       default:
+               return InsetCommand::getStatus(cur, cmd, status);
+       }
+}
+
+
 bool InsetCitation::addKey(string const & key)
 {
        docstring const ukey = from_utf8(key);
@@ -185,7 +209,8 @@ docstring InsetCitation::toolTip(BufferView const & bv, 
int, int) const
 namespace {
 
 
-CitationStyle asValidLatexCommand(string const & input, vector<CitationStyle> 
const & valid_styles)
+CitationStyle asValidLatexCommand(BufferParams const & bp, string const & 
input,
+                                 vector<CitationStyle> const & valid_styles)
 {
        CitationStyle cs = valid_styles[0];
        cs.forceUpperCase = false;
@@ -200,11 +225,15 @@ CitationStyle asValidLatexCommand(string const & input, 
vector<CitationStyle> co
        if (input[n] == '*')
                normalized_input = normalized_input.substr(0, n);
 
+       string const alias = bp.getCiteAlias(normalized_input);
+       if (!alias.empty())
+               normalized_input = alias;
+
        vector<CitationStyle>::const_iterator it  = valid_styles.begin();
        vector<CitationStyle>::const_iterator end = valid_styles.end();
        for (; it != end; ++it) {
                CitationStyle this_cs = *it;
-               if (this_cs.cmd == normalized_input) {
+               if (this_cs.name == normalized_input) {
                        cs = *it;
                        break;
                }
@@ -267,6 +296,11 @@ docstring InsetCitation::complexLabel(bool for_xhtml) const
                // and this would mean FULL
                cite_type = cite_type.substr(0, cite_type.size() - 1);
 
+       // handle alias
+       string const alias = buf.params().getCiteAlias(cite_type);
+       if (!alias.empty())
+               cite_type = alias;
+
        docstring const & before = getParam("before");
        docstring const & after = getParam("after");
 
@@ -414,10 +448,10 @@ void InsetCitation::forOutliner(docstring & os, size_t 
const, bool const) const
 void InsetCitation::latex(otexstream & os, OutputParams const & runparams) 
const
 {
        vector<CitationStyle> citation_styles = buffer().params().citeStyles();
-       CitationStyle cs = asValidLatexCommand(getCmdName(), citation_styles);
+       CitationStyle cs = asValidLatexCommand(buffer().params(), getCmdName(), 
citation_styles);
        BiblioInfo const & bi = buffer().masterBibInfo();
        // FIXME UNICODE
-       docstring const cite_str = from_utf8(citationStyleToString(cs));
+       docstring const cite_str = from_utf8(citationStyleToString(cs, true));
 
        if (runparams.inulemcmd > 0)
                os << "\\mbox{";
diff --git a/src/insets/InsetCitation.h b/src/insets/InsetCitation.h
index 417b46f..70022c6 100644
--- a/src/insets/InsetCitation.h
+++ b/src/insets/InsetCitation.h
@@ -46,6 +46,8 @@ public:
        ///
        void doDispatch(Cursor & cur, FuncRequest & cmd);
        ///
+       bool getStatus(Cursor & cur, FuncRequest const & cmd, FuncStatus &) 
const;
+       ///
        InsetCode lyxCode() const { return CITE_CODE; }
        ///
        void latex(otexstream &, OutputParams const &) const;

Reply via email to