The branch, biblatex2, has been updated. - Log -----------------------------------------------------------------
commit 8e4bd6a497561b1dda99f0b75102a9f8a1ca46ff Author: Juergen Spitzmueller <[email protected]> Date: Sat Dec 31 09:28:51 2016 +0100 Properly support the cite engines in the GUI Instead of hardcoding 3 engines, we now support all engines which are defined in the *.citeengines files. diff --git a/lib/citeengines/basic.citeengine b/lib/citeengines/basic.citeengine index dc4941b..7de5e35 100644 --- a/lib/citeengines/basic.citeengine +++ b/lib/citeengines/basic.citeengine @@ -1,6 +1,7 @@ -# \DeclareLyXCiteEngine{BibTeX (basic)} +# \DeclareLyXCiteEngine{Basic (BibTeX)} # DescriptionBegin -# Use the basic citation capabilities provided by plain LaTeX. +# The basic citation capabilities provided by BibTeX. +# Mainly simple numeric styles primarily suitable for science and maths. # DescriptionEnd # Excludes: jurabib | natbib diff --git a/lib/citeengines/jurabib.citeengine b/lib/citeengines/jurabib.citeengine index 13bbc6f..de292bb 100644 --- a/lib/citeengines/jurabib.citeengine +++ b/lib/citeengines/jurabib.citeengine @@ -1,8 +1,8 @@ -# \DeclareLyXCiteEngine[jurabib.sty]{Jurabib} +# \DeclareLyXCiteEngine[jurabib.sty]{Jurabib (BibTeX)} # DescriptionBegin -# Loads the LaTeX package jurabib, a citation engine. Jurabib supports annotations, -# author-year style citations and hyphenation patterns for bibliography entries in -# English, German, French, Dutch, Spanish and Italian. +# Jurabib supports a range of author-year styles primarily suitable for law studies +# and the Humanities. It includes localizations for English, German, French, Dutch, +# Spanish and Italian. # DescriptionEnd # Excludes: basic | natbib diff --git a/lib/citeengines/natbib.citeengine b/lib/citeengines/natbib.citeengine index 63bf1cb..dcd160f 100644 --- a/lib/citeengines/natbib.citeengine +++ b/lib/citeengines/natbib.citeengine @@ -1,9 +1,9 @@ -# \DeclareLyXCiteEngine[natbib.sty]{Natbib} +# \DeclareLyXCiteEngine[natbib.sty]{Natbib (BibTeX)} # DescriptionBegin -# Loads the LaTeX package natbib, a citation engine. Natbib supports -# both author-year and numerical styles for citations, automatic sorting -# and merging of numerical citations, annotations, capitalization of the -# `van' part of author names, shortened and full author lists, and more. +# Natbib supports a range of both author-year and numerical styles mainly +# aimed at the Humanities. It features automatic sorting and merging of +# numerical citations, annotations, capitalization of the `van' part of +# author names, shortened and full author lists, and more. # DescriptionEnd # Excludes: basic | jurabib diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp index 326d487..1e7f772 100644 --- a/src/BufferParams.cpp +++ b/src/BufferParams.cpp @@ -23,6 +23,7 @@ #include "Buffer.h" #include "buffer_funcs.h" #include "Bullet.h" +#include "CiteEnginesList.h" #include "Color.h" #include "ColorSet.h" #include "Converter.h" @@ -272,27 +273,6 @@ PackageTranslator const & packagetranslator() } -// Cite engine -typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator; - - -CiteEngineTypeTranslator const init_citeenginetypetranslator() -{ - CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR); - translator.addPair("numerical", ENGINE_TYPE_NUMERICAL); - translator.addPair("default", ENGINE_TYPE_DEFAULT); - return translator; -} - - -CiteEngineTypeTranslator const & citeenginetypetranslator() -{ - static CiteEngineTypeTranslator const translator = - init_citeenginetypetranslator(); - return translator; -} - - // Spacing typedef Translator<string, Spacing::Space> SpaceTranslator; @@ -863,7 +843,7 @@ string BufferParams::readToken(Lexer & lex, string const & token, } else if (token == "\\cite_engine_type") { string engine_type; lex >> engine_type; - cite_engine_type_ = citeenginetypetranslator().find(engine_type); + cite_engine_type_ = theCiteEnginesList.getType(engine_type); } else if (token == "\\biblio_style") { lex.eatLine(); biblio_style = lex.getString(); @@ -1234,7 +1214,7 @@ void BufferParams::writeFile(ostream & os, Buffer const * buf) const os << "basic"; } - os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_) + os << "\n\\cite_engine_type " << theCiteEnginesList.getTypeAsString(cite_engine_type_) << "\n\\biblio_style " << biblio_style << "\n\\use_bibtopic " << convert<string>(use_bibtopic) << "\n\\use_indices " << convert<string>(use_indices) diff --git a/src/CiteEnginesList.cpp b/src/CiteEnginesList.cpp index 48222cb..209c8bc 100644 --- a/src/CiteEnginesList.cpp +++ b/src/CiteEnginesList.cpp @@ -14,6 +14,7 @@ #include "CiteEnginesList.h" +#include "Citation.h" #include "LaTeXFeatures.h" #include "Lexer.h" @@ -22,6 +23,7 @@ #include "support/gettext.h" #include "support/filetools.h" #include "support/lstrings.h" +#include "support/Translator.h" #include <algorithm> @@ -76,6 +78,13 @@ bool LyXCiteEngine::isAvailable() const } +bool LyXCiteEngine::hasEngineType(CiteEngineType const & et) const +{ + return std::find(engine_types_.begin(), engine_types_.end(), + theCiteEnginesList.getTypeAsString(et)) != engine_types_.end(); +} + + bool LyXCiteEngine::isCompatible(string const & cename) const { // do we exclude it? @@ -119,6 +128,43 @@ public: }; +// Local translators +namespace { + +typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator; + + +CiteEngineTypeTranslator const init_citeenginetypetranslator() +{ + CiteEngineTypeTranslator translator("authoryear", ENGINE_TYPE_AUTHORYEAR); + translator.addPair("numerical", ENGINE_TYPE_NUMERICAL); + translator.addPair("default", ENGINE_TYPE_DEFAULT); + return translator; +} + + +CiteEngineTypeTranslator const & citeenginetypetranslator() +{ + static CiteEngineTypeTranslator const translator = + init_citeenginetypetranslator(); + return translator; +} + +} // namespace anon + + +string CiteEnginesList::getTypeAsString(CiteEngineType const & et) const +{ + return citeenginetypetranslator().find(et); +} + + +CiteEngineType CiteEnginesList::getType(string const & et) const +{ + return citeenginetypetranslator().find(et); +} + + // Much of this is borrowed from LayoutFileList::read() bool CiteEnginesList::read() { diff --git a/src/CiteEnginesList.h b/src/CiteEnginesList.h index 0e6d119..17cfbb8 100644 --- a/src/CiteEnginesList.h +++ b/src/CiteEnginesList.h @@ -13,6 +13,8 @@ #ifndef CITEENGINESLIST_H #define CITEENGINESLIST_H +#include "Citation.h" + #include <string> #include <vector> @@ -29,13 +31,13 @@ namespace lyx { * which must begin roughly so: * # \DeclareLyXCiteEngine[natbib.sty]{Natbib} * # DescriptionBegin - * # Loads the LaTeX package natbib, a citation engine. Natbib supports - * # both author-year and numerical styles for citations, automatic sorting - * # and merging of numerical citations, annotations, capitalization of the - * # `van' part of author names, shortened and full author lists, and more. + * # Natbib supports a range of both author-year and numerical styles mainly + * # aimed at the Humanities. It features automatic sorting and merging of + * # numerical citations, annotations, capitalization of the `van' part of + * # author names, shortened and full author lists, and more. * # DescriptionEnd * # Excludes: basic | jurabib - * The description might be used in the gui to give information to the user. The + * The description will be used in the gui to give information to the user. The * Requires and Excludes lines are read by the configuration script * and written to a file citeengines.lst in the user configuration directory. * That file is then read on startup to populate the CiteEnginesList, below. @@ -66,6 +68,8 @@ public: /// std::vector<std::string> const & getEngineType() const { return engine_types_; } /// + bool hasEngineType(CiteEngineType const &) const; + /// std::string const & getDescription() const { return description_; } /// std::vector<std::string> const & getPackageList() const @@ -121,6 +125,10 @@ class CiteEnginesList { public: /// CiteEnginesList() {} + /// + std::string getTypeAsString(CiteEngineType const &) const; + /// + CiteEngineType getType(std::string const &) const; /// reads the engines from a file generated by configure.py bool read(); /// diff --git a/src/frontends/qt4/GuiDocument.cpp b/src/frontends/qt4/GuiDocument.cpp index 6ef39dc..d971eeb 100644 --- a/src/frontends/qt4/GuiDocument.cpp +++ b/src/frontends/qt4/GuiDocument.cpp @@ -29,6 +29,7 @@ #include "Buffer.h" #include "BufferParams.h" #include "BufferView.h" +#include "CiteEnginesList.h" #include "Color.h" #include "ColorCache.h" #include "Converter.h" @@ -1126,22 +1127,10 @@ GuiDocument::GuiDocument(GuiView & lv) // biblio biblioModule = new UiWidget<Ui::BiblioUi>; - connect(biblioModule->citeDefaultRB, SIGNAL(toggled(bool)), - this, SLOT(setNumerical(bool))); - connect(biblioModule->citeJurabibRB, SIGNAL(toggled(bool)), - this, SLOT(setAuthorYear(bool))); - connect(biblioModule->citeNatbibRB, SIGNAL(toggled(bool)), - biblioModule->citationStyleL, SLOT(setEnabled(bool))); - connect(biblioModule->citeNatbibRB, SIGNAL(toggled(bool)), - biblioModule->citeStyleCO, SLOT(setEnabled(bool))); - connect(biblioModule->citeDefaultRB, SIGNAL(clicked()), - this, SLOT(biblioChanged())); - connect(biblioModule->citeNatbibRB, SIGNAL(clicked()), - this, SLOT(biblioChanged())); + connect(biblioModule->citeEngineCO, SIGNAL(activated(int)), + this, SLOT(citeEngineChanged(int))); connect(biblioModule->citeStyleCO, SIGNAL(activated(int)), this, SLOT(biblioChanged())); - connect(biblioModule->citeJurabibRB, SIGNAL(clicked()), - this, SLOT(biblioChanged())); connect(biblioModule->bibtopicCB, SIGNAL(clicked()), this, SLOT(biblioChanged())); connect(biblioModule->bibtexCO, SIGNAL(activated(int)), @@ -1151,15 +1140,19 @@ GuiDocument::GuiDocument(GuiView & lv) connect(biblioModule->bibtexStyleLE, SIGNAL(textChanged(QString)), this, SLOT(biblioChanged())); + biblioModule->citeEngineCO->clear(); + for (LyXCiteEngine const & cet : theCiteEnginesList) { + biblioModule->citeEngineCO->addItem(qt_(cet.getName()), toqstr(cet.getID())); + int const i = biblioModule->citeEngineCO->findData(toqstr(cet.getID())); + biblioModule->citeEngineCO->setItemData(i, qt_(cet.getDescription()), + Qt::ToolTipRole); + } + biblioModule->bibtexOptionsLE->setValidator(new NoNewLineValidator( biblioModule->bibtexOptionsLE)); biblioModule->bibtexStyleLE->setValidator(new NoNewLineValidator( biblioModule->bibtexStyleLE)); - biblioModule->citeStyleCO->addItem(qt_("Author-year")); - biblioModule->citeStyleCO->addItem(qt_("Numerical")); - biblioModule->citeStyleCO->setCurrentIndex(0); - // NOTE: we do not provide "custom" here for security reasons! biblioModule->bibtexCO->clear(); biblioModule->bibtexCO->addItem(qt_("Default"), QString("default")); @@ -2278,6 +2271,19 @@ void GuiDocument::biblioChanged() } +void GuiDocument::citeEngineChanged(int n) +{ + QString const engine = biblioModule->citeEngineCO->itemData(n).toString(); + + vector<string> const engs = + theCiteEnginesList[fromqstr(engine)]->getEngineType(); + + updateCiteStyles(engs); + + biblioChanged(); +} + + void GuiDocument::bibtexChanged(int n) { biblioModule->bibtexOptionsLE->setEnabled( @@ -2289,7 +2295,8 @@ void GuiDocument::bibtexChanged(int n) void GuiDocument::setAuthorYear(bool authoryear) { if (authoryear) - biblioModule->citeStyleCO->setCurrentIndex(0); + biblioModule->citeStyleCO->setCurrentIndex( + biblioModule->citeStyleCO->findData(ENGINE_TYPE_AUTHORYEAR)); biblioChanged(); } @@ -2297,11 +2304,39 @@ void GuiDocument::setAuthorYear(bool authoryear) void GuiDocument::setNumerical(bool numerical) { if (numerical) - biblioModule->citeStyleCO->setCurrentIndex(1); + biblioModule->citeStyleCO->setCurrentIndex( + biblioModule->citeStyleCO->findData(ENGINE_TYPE_NUMERICAL)); biblioChanged(); } +void GuiDocument::updateCiteStyles(vector<string> const & engs, CiteEngineType const & sel) +{ + biblioModule->citeStyleCO->clear(); + + vector<string>::const_iterator it = engs.begin(); + vector<string>::const_iterator end = engs.end(); + for (; it != end; ++it) { + if (*it == "default") + biblioModule->citeStyleCO->addItem(qt_("Basic numerical"), + ENGINE_TYPE_DEFAULT); + else if (*it == "authoryear") + biblioModule->citeStyleCO->addItem(qt_("Author-year"), + ENGINE_TYPE_AUTHORYEAR); + else if (*it == "numerical") + biblioModule->citeStyleCO->addItem(qt_("Author-number"), + ENGINE_TYPE_NUMERICAL); + } + int i = biblioModule->citeStyleCO->findData(sel); + if (biblioModule->citeStyleCO->findData(sel) == -1) + i = 0; + biblioModule->citeStyleCO->setCurrentIndex(i); + + biblioModule->citationStyleL->setEnabled(engs.size() > 1); + biblioModule->citeStyleCO->setEnabled(engs.size() > 1); +} + + void GuiDocument::updateEngineType(string const & items, CiteEngineType const & sel) { engine_types_.clear(); @@ -2314,28 +2349,7 @@ void GuiDocument::updateEngineType(string const & items, CiteEngineType const & engine_types_.push_back(style); } - switch (sel) { - case ENGINE_TYPE_AUTHORYEAR: - biblioModule->citeStyleCO->setCurrentIndex(0); - break; - case ENGINE_TYPE_NUMERICAL: - case ENGINE_TYPE_DEFAULT: - biblioModule->citeStyleCO->setCurrentIndex(1); - break; - } - - biblioModule->citationStyleL->setEnabled(nn > 1); - biblioModule->citeStyleCO->setEnabled(nn > 1); - - if (nn != 1) - return; - - // If the textclass allows only one of authoryear or numerical, - // we have no choice but to force that engine type. - if (engine_types_[0] == "authoryear") - biblioModule->citeStyleCO->setCurrentIndex(0); - else - biblioModule->citeStyleCO->setCurrentIndex(1); + updateCiteStyles(engine_types_, sel); } @@ -2588,19 +2602,17 @@ void GuiDocument::applyView() bp_.use_refstyle = latexModule->refstyleCB->isChecked(); // biblio - if (biblioModule->citeNatbibRB->isChecked()) - bp_.setCiteEngine("natbib"); - else if (biblioModule->citeJurabibRB->isChecked()) - bp_.setCiteEngine("jurabib"); - if (biblioModule->citeDefaultRB->isChecked()) { - bp_.setCiteEngine("basic"); - bp_.setCiteEngineType(ENGINE_TYPE_DEFAULT); - } - else - if (biblioModule->citeStyleCO->currentIndex()) - bp_.setCiteEngineType(ENGINE_TYPE_NUMERICAL); + string const engine = + fromqstr(biblioModule->citeEngineCO->itemData( + biblioModule->citeEngineCO->currentIndex()).toString()); + bp_.setCiteEngine(engine); + + CiteEngineType const style = CiteEngineType(biblioModule->citeStyleCO->itemData( + biblioModule->citeStyleCO->currentIndex()).toInt()); + if (theCiteEnginesList[engine]->hasEngineType(style)) + bp_.setCiteEngineType(style); else - bp_.setCiteEngineType(ENGINE_TYPE_AUTHORYEAR); + bp_.setCiteEngineType(ENGINE_TYPE_DEFAULT); bp_.use_bibtopic = biblioModule->bibtopicCB->isChecked(); @@ -3016,21 +3028,15 @@ void GuiDocument::paramsToDialog() // biblio string const cite_engine = bp_.citeEngine().list().front(); - biblioModule->citeDefaultRB->setChecked( - cite_engine == "basic"); - - biblioModule->citeJurabibRB->setChecked( - cite_engine == "jurabib"); - - biblioModule->citeNatbibRB->setChecked( - cite_engine == "natbib"); - - biblioModule->citeStyleCO->setCurrentIndex( - bp_.citeEngineType() & ENGINE_TYPE_NUMERICAL); + biblioModule->citeEngineCO->setCurrentIndex( + biblioModule->citeEngineCO->findData(toqstr(cite_engine))); updateEngineType(documentClass().opt_enginetype(), bp_.citeEngineType()); + biblioModule->citeStyleCO->setCurrentIndex( + biblioModule->citeStyleCO->findData(bp_.citeEngineType())); + biblioModule->bibtopicCB->setChecked( bp_.use_bibtopic); diff --git a/src/frontends/qt4/GuiDocument.h b/src/frontends/qt4/GuiDocument.h index c055378..e5aa4fa 100644 --- a/src/frontends/qt4/GuiDocument.h +++ b/src/frontends/qt4/GuiDocument.h @@ -75,6 +75,8 @@ public: void updateFontsize(std::string const &, std::string const &); void updateFontlist(); void updateDefaultFormat(); + void updateCiteStyles(std::vector<std::string> const &, + CiteEngineType const & sel = ENGINE_TYPE_AUTHORYEAR); void updateEngineType(std::string const &, CiteEngineType const &); void updatePagestyle(std::string const &, std::string const &); bool isChildIncluded(std::string const &); @@ -113,6 +115,7 @@ private Q_SLOTS: void classChanged_adaptor(); void languagePackageChanged(int); void biblioChanged(); + void citeEngineChanged(int); void bibtexChanged(int); void setAuthorYear(bool); void setNumerical(bool); diff --git a/src/frontends/qt4/ui/BiblioUi.ui b/src/frontends/qt4/ui/BiblioUi.ui index f0103cf..7cc821b 100644 --- a/src/frontends/qt4/ui/BiblioUi.ui +++ b/src/frontends/qt4/ui/BiblioUi.ui @@ -1,7 +1,8 @@ -<ui version="4.0" > +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> <class>BiblioUi</class> - <widget class="QWidget" name="BiblioUi" > - <property name="geometry" > + <widget class="QWidget" name="BiblioUi"> + <property name="geometry"> <rect> <x>0</x> <y>0</y> @@ -9,81 +10,93 @@ <height>394</height> </rect> </property> - <property name="windowTitle" > + <property name="windowTitle"> <string/> </property> - <layout class="QGridLayout" name="gridLayout_3" > - <item row="0" column="0" > - <widget class="QGroupBox" name="CiteStyleBG" > - <property name="title" > + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <widget class="QGroupBox" name="CiteStyleBG"> + <property name="title"> <string>Citation Style</string> </property> - <property name="flat" > + <property name="flat"> <bool>true</bool> </property> - <layout class="QGridLayout" name="gridLayout" > - <item row="0" column="0" > - <widget class="QRadioButton" name="citeDefaultRB" > - <property name="toolTip" > - <string>Use BibTeX's default numerical styles</string> - </property> - <property name="text" > - <string>&Default (numerical)</string> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> </property> - </widget> - </item> - <item row="1" column="0" > - <widget class="QRadioButton" name="citeNatbibRB" > - <property name="toolTip" > - <string>Use the natbib styles for natural sciences and arts. Set additional parameters in document class options.</string> + <property name="leftMargin"> + <number>0</number> </property> - <property name="text" > - <string>&Natbib</string> + <property name="topMargin"> + <number>0</number> </property> - </widget> - </item> - <item row="1" column="1" > - <layout class="QHBoxLayout" > - <property name="spacing" > - <number>6</number> + <property name="rightMargin"> + <number>0</number> </property> - <property name="margin" > + <property name="bottomMargin"> <number>0</number> </property> <item> - <widget class="QLabel" name="citationStyleL" > - <property name="enabled" > + <widget class="QLabel" name="citeEngineLA"> + <property name="toolTip"> + <string/> + </property> + <property name="text"> + <string>Sty&le Engine:</string> + </property> + <property name="buddy"> + <cstring>citeEngineCO</cstring> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="citeEngineCO"> + <property name="toolTip"> + <string>A selection of different style engines (such as natbib) that respectively provide support for specific citytion and bibliography styles. Expand to get more information.</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="citationStyleL"> + <property name="enabled"> <bool>false</bool> </property> - <property name="text" > - <string>Natbib &style:</string> + <property name="text"> + <string>&Variant:</string> </property> - <property name="buddy" > + <property name="buddy"> <cstring>citeStyleCO</cstring> </property> </widget> </item> <item> - <widget class="QComboBox" name="citeStyleCO" > - <property name="enabled" > + <widget class="QComboBox" name="citeStyleCO"> + <property name="enabled"> <bool>false</bool> </property> - <property name="sizePolicy" > - <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> + <property name="toolTip"> + <string>Provides available cite style variants.</string> + </property> </widget> </item> </layout> </item> - <item row="1" column="2" > + <item row="0" column="1"> <spacer> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="sizeHint" stdset="0" > + <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> @@ -91,55 +104,45 @@ </property> </spacer> </item> - <item row="2" column="0" > - <widget class="QRadioButton" name="citeJurabibRB" > - <property name="toolTip" > - <string>Use the jurabib styles for law and humanities</string> - </property> - <property name="text" > - <string>&Jurabib</string> - </property> - </widget> - </item> </layout> </widget> </item> - <item row="1" column="0" > - <widget class="QGroupBox" name="BiblioStyleBG" > - <property name="title" > + <item row="1" column="0"> + <widget class="QGroupBox" name="BiblioStyleBG"> + <property name="title"> <string>Bibliography Style</string> </property> - <property name="flat" > + <property name="flat"> <bool>true</bool> </property> - <layout class="QGridLayout" name="gridLayout_1" > - <item row="0" column="0" > - <layout class="QHBoxLayout" name="horizontalLayout_1" > + <layout class="QGridLayout" name="gridLayout_1"> + <item row="0" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_1"> <item> - <widget class="QLabel" name="bibtexStyleLA" > - <property name="text" > + <widget class="QLabel" name="bibtexStyleLA"> + <property name="text"> <string>Default st&yle:</string> </property> - <property name="buddy" > + <property name="buddy"> <cstring>bibtexStyleLE</cstring> </property> </widget> </item> <item> - <widget class="QLineEdit" name="bibtexStyleLE" > - <property name="toolTip" > + <widget class="QLineEdit" name="bibtexStyleLE"> + <property name="toolTip"> <string>Define the default BibTeX style</string> </property> </widget> </item> </layout> </item> - <item row="1" column="0" > - <widget class="QCheckBox" name="bibtopicCB" > - <property name="toolTip" > + <item row="1" column="0"> + <widget class="QCheckBox" name="bibtopicCB"> + <property name="toolTip"> <string>Select this if you want to split your bibliography into sections</string> </property> - <property name="text" > + <property name="text"> <string>S&ectioned bibliography</string> </property> </widget> @@ -147,45 +150,45 @@ </layout> </widget> </item> - <item row="2" column="0" > - <widget class="QGroupBox" name="bibtexGB" > - <property name="toolTip" > + <item row="2" column="0"> + <widget class="QGroupBox" name="bibtexGB"> + <property name="toolTip"> <string>Here you can define an alternative program to or specific options of BibTeX.</string> </property> - <property name="title" > + <property name="title"> <string>Bibliography Generation</string> </property> - <property name="flat" > + <property name="flat"> <bool>true</bool> </property> - <layout class="QGridLayout" name="gridLayout_2" > - <item row="0" column="0" > - <layout class="QHBoxLayout" name="horizontalLayout" > + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout"> <item> - <widget class="QLabel" name="bibtexLA" > - <property name="text" > + <widget class="QLabel" name="bibtexLA"> + <property name="text"> <string>&Processor:</string> </property> - <property name="buddy" > + <property name="buddy"> <cstring>bibtexCO</cstring> </property> </widget> </item> <item> - <widget class="QComboBox" name="bibtexCO" > - <property name="toolTip" > + <widget class="QComboBox" name="bibtexCO"> + <property name="toolTip"> <string>Select a processor</string> </property> </widget> </item> </layout> </item> - <item rowspan="2" row="0" column="1" > - <spacer name="horizontalSpacer" > - <property name="orientation" > + <item row="0" column="1" rowspan="2"> + <spacer name="horizontalSpacer"> + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="sizeHint" stdset="0" > + <property name="sizeHint" stdset="0"> <size> <width>183</width> <height>20</height> @@ -193,21 +196,21 @@ </property> </spacer> </item> - <item row="1" column="0" > - <layout class="QHBoxLayout" name="horizontalLayout_2" > + <item row="1" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> - <widget class="QLabel" name="bibtexOptionsLA" > - <property name="text" > - <string>&Options:</string> + <widget class="QLabel" name="bibtexOptionsLA"> + <property name="text"> + <string>Op&tions:</string> </property> - <property name="buddy" > + <property name="buddy"> <cstring>bibtexOptionsLE</cstring> </property> </widget> </item> <item> - <widget class="QLineEdit" name="bibtexOptionsLE" > - <property name="toolTip" > + <widget class="QLineEdit" name="bibtexOptionsLE"> + <property name="toolTip"> <string>Define options such as --min-crossrefs (see the documentation of BibTeX)</string> </property> </widget> @@ -217,15 +220,15 @@ </layout> </widget> </item> - <item row="3" column="0" > + <item row="3" column="0"> <spacer> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Vertical</enum> </property> - <property name="sizeType" > + <property name="sizeType"> <enum>QSizePolicy::Expanding</enum> </property> - <property name="sizeHint" stdset="0" > + <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>20</height> @@ -236,7 +239,7 @@ </layout> </widget> <includes> - <include location="local" >qt_i18n.h</include> + <include location="local">qt_i18n.h</include> </includes> <resources/> <connections/> commit 0e6a3ac40427ec3107cb88aa678fbe92473e7d45 Author: Juergen Spitzmueller <[email protected]> Date: Fri Dec 30 16:22:08 2016 +0100 Disentangle CiteEngines and Modules These two are different beasts and thus should be handled differently. diff --git a/lib/Makefile.am b/lib/Makefile.am index ee7e2b1..36c9c0c 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -2107,7 +2107,6 @@ dist_layouts_DATA =\ layouts/arab-article.layout \ layouts/article.layout \ layouts/article-beamer.layout \ - layouts/basic.module \ layouts/beamer.layout \ layouts/beamerposter.layout \ layouts/bicaption.module \ @@ -2185,7 +2184,6 @@ dist_layouts_DATA =\ layouts/jsarticle.layout \ layouts/jsbook.layout \ layouts/jss.layout \ - layouts/jurabib.module \ layouts/kluwer.layout \ layouts/knitr.module \ layouts/latex8.layout \ @@ -2205,7 +2203,6 @@ dist_layouts_DATA =\ layouts/mwart.layout \ layouts/mwbk.layout \ layouts/mwrep.layout \ - layouts/natbib.module \ layouts/natbibapa.module \ layouts/noweb.module \ layouts/numarticle.inc \ @@ -2302,6 +2299,12 @@ dist_layouts_DATA =\ layouts/tufte-handout.layout \ layouts/varwidth.module +citeenginesdir = $(pkgdatadir)/citeengines +dist_citeengines_DATA = \ + citeengines/basic.citeengine \ + citeengines/jurabib.citeengine \ + citeengines/natbib.citeengine + scriptsdir = $(pkgdatadir)/scripts dist_scripts_DATA = \ scripts/bash_completion \ diff --git a/lib/chkconfig.ltx b/lib/chkconfig.ltx index 140014a..9daca8f 100644 --- a/lib/chkconfig.ltx +++ b/lib/chkconfig.ltx @@ -492,6 +492,7 @@ % configure script. \input{chklayouts} \input{chkmodules} +\input{chkciteengines} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%% END ACTUAL CONFIGURATION INSPECTION CODE %%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/layouts/basic.module b/lib/citeengines/basic.citeengine similarity index 93% rename from lib/layouts/basic.module rename to lib/citeengines/basic.citeengine index 8e0ed1c..dc4941b 100644 --- a/lib/layouts/basic.module +++ b/lib/citeengines/basic.citeengine @@ -1,9 +1,8 @@ -# \DeclareLyXModule{Default (basic)} +# \DeclareLyXCiteEngine{BibTeX (basic)} # DescriptionBegin # Use the basic citation capabilities provided by plain LaTeX. # DescriptionEnd # Excludes: jurabib | natbib -# Category: Citation engine # Author: Julien Rioux <[email protected]> diff --git a/lib/layouts/jurabib.module b/lib/citeengines/jurabib.citeengine similarity index 98% rename from lib/layouts/jurabib.module rename to lib/citeengines/jurabib.citeengine index 63bae5a..13bbc6f 100644 --- a/lib/layouts/jurabib.module +++ b/lib/citeengines/jurabib.citeengine @@ -1,11 +1,10 @@ -# \DeclareLyXModule[jurabib.sty]{Jurabib} +# \DeclareLyXCiteEngine[jurabib.sty]{Jurabib} # DescriptionBegin # Loads the LaTeX package jurabib, a citation engine. Jurabib supports annotations, # author-year style citations and hyphenation patterns for bibliography entries in # English, German, French, Dutch, Spanish and Italian. # DescriptionEnd # Excludes: basic | natbib -# Category: Citation engine # Author: Julien Rioux <[email protected]> diff --git a/lib/layouts/natbib.module b/lib/citeengines/natbib.citeengine similarity index 97% rename from lib/layouts/natbib.module rename to lib/citeengines/natbib.citeengine index d4d250e..63bf1cb 100644 --- a/lib/layouts/natbib.module +++ b/lib/citeengines/natbib.citeengine @@ -1,4 +1,4 @@ -# \DeclareLyXModule[natbib.sty]{Natbib} +# \DeclareLyXCiteEngine[natbib.sty]{Natbib} # DescriptionBegin # Loads the LaTeX package natbib, a citation engine. Natbib supports # both author-year and numerical styles for citations, automatic sorting @@ -6,7 +6,6 @@ # `van' part of author names, shortened and full author lists, and more. # DescriptionEnd # Excludes: basic | jurabib -# Category: Citation engine # Author: Julien Rioux <[email protected]> diff --git a/lib/configure.py b/lib/configure.py index fb1abd3..680e32a 100644 --- a/lib/configure.py +++ b/lib/configure.py @@ -1502,6 +1502,132 @@ def processModuleFile(file, filename, bool_docbook): return '"%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, filename, desc, pkgs, req, excl, catgy) +def checkCiteEnginesConfig(): + removeFiles(['lyxciteengines.lst', 'chkciteengines.tex']) + + logger.info('+checking list of cite engines... ') + tx = open('lyxciteengines.lst', 'w') + tx.write('''## This file declares cite engines and their associated definition files. +## It has been automatically generated by configure +## Use "Options/Reconfigure" if you need to update it after a +## configuration change. +## "CiteEngineName" "filename" "CiteEngineType" "Description" "Packages" "Requires" "Excludes" +''') + + # build the list of available modules + seen = [] + # note that this searches the local directory first, then the + # system directory. that way, we pick up the user's version first. + for file in glob.glob( os.path.join('citeengines', '*.citeengine') ) + \ + glob.glob( os.path.join(srcdir, 'citeengines', '*.citeengine' ) ) : + # valid file? + logger.info(file) + if not os.path.isfile(file): + continue + + filename = file.split(os.sep)[-1] + filename = filename[:-11] + if seen.count(filename): + continue + + seen.append(filename) + retval = processCiteEngineFile(file, filename, bool_docbook) + if retval != "": + tx.write(retval) + tx.close() + logger.info('\tdone') + + +def processCiteEngineFile(file, filename, bool_docbook): + ''' process cite engines file and get a line of result + + The top of a cite engine file should look like this: + #\DeclareLyXCiteEngine[LaTeX Packages]{CiteEngineName} + #DescriptionBegin + #...body of description... + #DescriptionEnd + #Requires: [list of required engines] + #Excludes: [list of excluded engines] + The last two lines are optional. + We expect output: + "CiteEngineName" "filename" "CiteEngineType" "Description" "Packages" "Requires" "Excludes" + ''' + remods = re.compile(r'\DeclareLyXCiteEngine\s*(?:\[([^]]*?)\])?{(.*)}') + rereqs = re.compile(r'#+\s*Requires: (.*)') + reexcs = re.compile(r'#+\s*Excludes: (.*)') + redbeg = re.compile(r'#+\s*DescriptionBegin\s*$') + redend = re.compile(r'#+\s*DescriptionEnd\s*$') + recet = re.compile(r'\s*CiteEngineType (.*)') + + modname = desc = pkgs = req = excl = cet = "" + readingDescription = False + descLines = [] + + for line in open(file).readlines(): + if readingDescription: + res = redend.search(line) + if res != None: + readingDescription = False + desc = " ".join(descLines) + # Escape quotes. + desc = desc.replace('"', '\\"') + continue + descLines.append(line[1:].strip()) + continue + res = redbeg.search(line) + if res != None: + readingDescription = True + continue + res = remods.search(line) + if res != None: + (pkgs, modname) = res.groups() + if pkgs == None: + pkgs = "" + else: + tmp = [s.strip() for s in pkgs.split(",")] + pkgs = ",".join(tmp) + continue + res = rereqs.search(line) + if res != None: + req = res.group(1) + tmp = [s.strip() for s in req.split("|")] + req = "|".join(tmp) + continue + res = reexcs.search(line) + if res != None: + excl = res.group(1) + tmp = [s.strip() for s in excl.split("|")] + excl = "|".join(tmp) + continue + res = recet.search(line) + if res != None: + cet = res.group(1) + continue + + if modname == "": + logger.warning("Cite Engine File file without \DeclareLyXCiteEngine line. ") + return "" + + if pkgs != "": + # this cite engine has some latex dependencies: + # append the dependencies to chkciteengines.tex, + # which is \input'ed by chkconfig.ltx + testpackages = list() + for pkg in pkgs.split(","): + if "->" in pkg: + # this is a converter dependency: skip + continue + if pkg.endswith(".sty"): + pkg = pkg[:-4] + testpackages.append("\\TestPackage{%s}" % (pkg,)) + cm = open('chkciteengines.tex', 'a') + for line in testpackages: + cm.write(line + '\n') + cm.close() + + return '"%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, filename, cet, desc, pkgs, req, excl) + + def checkTeXAllowSpaces(): ''' Let's check whether spaces are allowed in TeX file names ''' tex_allows_spaces = 'false' @@ -1543,8 +1669,8 @@ def removeTempFiles(): # Final clean-up if not lyx_keep_temps: removeFiles(['chkconfig.vars', 'chklatex.ltx', 'chklatex.log', - 'chklayouts.tex', 'chkmodules.tex', 'missfont.log', - 'wrap_chkconfig.ltx', 'wrap_chkconfig.log']) + 'chklayouts.tex', 'chkmodules.tex', 'chkciteengines.tex', + 'missfont.log', 'wrap_chkconfig.ltx', 'wrap_chkconfig.log']) if __name__ == '__main__': @@ -1623,6 +1749,7 @@ Format %i if lyx_kpsewhich: rescanTeXFiles() checkModulesConfig() + checkCiteEnginesConfig() # --without-latex-config can disable lyx_check_config ret = checkLatexConfig(lyx_check_config and LATEX != '', bool_docbook) removeTempFiles() diff --git a/po/Rules-lyx b/po/Rules-lyx index 42998f2..23d4c06 100644 --- a/po/Rules-lyx +++ b/po/Rules-lyx @@ -34,7 +34,7 @@ layouts_l10n.pot: $(top_srcdir)/lib/layouts/*.layout \ # Read translatable strings from layouts and translations from the po files and # create the layouttranslations file containing all LaTeX relevant translations $(top_srcdir)/lib/layouttranslations: $(POFILES) $(top_srcdir)/lib/layouts/*.layout \ - $(top_srcdir)/lib/layouts/*.inc $(top_srcdir)/lib/layouts/*.module + $(top_srcdir)/lib/layouts/*.inc $(top_srcdir)/lib/layouts/*.module $(top_srcdir)/lib/citeengines/*.citeengines $(LYX_POT) -o $@ -t layouttranslations ${top_srcdir}/lib/layouts/*.layout ${top_srcdir}/lib/layouts/*.inc ${top_srcdir}/lib/layouts/*.module languages_l10n.pot: $(top_srcdir)/lib/languages diff --git a/po/lyx_pot.py b/po/lyx_pot.py index 761e3dd..0fc7ee4 100755 --- a/po/lyx_pot.py +++ b/po/lyx_pot.py @@ -91,6 +91,7 @@ def layouts_l10n(input_files, output, base, layouttranslations): ListName = re.compile(r'^\s*ListName\s+(.*\S)\s*$', re.IGNORECASE) CategoryName = re.compile(r'^\s*Category\s+(.*\S)\s*$', re.IGNORECASE) NameRE = re.compile(r'^\s*#\s*\\DeclareLyXModule.*{(.*)}$', re.IGNORECASE) + CiteNameRE = re.compile(r'^\s*#\s*\\DeclareLyXCiteEngine.*{(.*)}$', re.IGNORECASE) InsetLayout = re.compile(r'^InsetLayout\s+\"?(.*)\"?\s*$', re.IGNORECASE) FlexCheck = re.compile(r'^Flex:(.*)', re.IGNORECASE) CaptionCheck = re.compile(r'^Caption:(.*)', re.IGNORECASE) @@ -234,6 +235,12 @@ def layouts_l10n(input_files, output, base, layouttranslations): if not layouttranslations: writeString(out, src, base, lineno + 1, string) continue + res = CiteNameRE.search(line) + if res != None: + string = res.group(1) + if not layouttranslations: + writeString(out, src, base, lineno + 1, string) + continue res = Style.search(line) if res != None: string = res.group(1) diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp index fa0b7c3..326d487 100644 --- a/src/BufferParams.cpp +++ b/src/BufferParams.cpp @@ -2333,6 +2333,7 @@ void BufferParams::makeDocumentClass(bool const clone) invalidateConverterCache(); LayoutModuleList mods; + LayoutModuleList ces; LayoutModuleList::iterator it = layout_modules_.begin(); LayoutModuleList::iterator en = layout_modules_.end(); for (; it != en; ++it) @@ -2341,9 +2342,9 @@ void BufferParams::makeDocumentClass(bool const clone) it = cite_engine_.begin(); en = cite_engine_.end(); for (; it != en; ++it) - mods.push_back(*it); + ces.push_back(*it); - doc_class_ = getDocumentClass(*baseClass(), mods, clone); + doc_class_ = getDocumentClass(*baseClass(), mods, ces, clone); TextClass::ReturnValues success = TextClass::OK; if (!forced_local_layout_.empty()) diff --git a/src/CiteEnginesList.cpp b/src/CiteEnginesList.cpp new file mode 100644 index 0000000..48222cb --- /dev/null +++ b/src/CiteEnginesList.cpp @@ -0,0 +1,280 @@ +// -*- C++ -*- +/** + * \file CiteEnginesList.cpp + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Richard Heck + * \author Jürgen Spitzmüller + * + * Full author contact details are available in file CREDITS. + */ + +#include <config.h> + +#include "CiteEnginesList.h" + +#include "LaTeXFeatures.h" +#include "Lexer.h" + +#include "support/debug.h" +#include "support/FileName.h" +#include "support/gettext.h" +#include "support/filetools.h" +#include "support/lstrings.h" + +#include <algorithm> + +using namespace std; +using namespace lyx::support; + +namespace lyx { + + +//global variable: cite engine list +CiteEnginesList theCiteEnginesList; + + +LyXCiteEngine::LyXCiteEngine(string const & n, string const & i, + vector<string> const & cet, string const & d, + vector<string> const & p, + vector<string> const & r, vector<string> const & e): + name_(n), id_(i), engine_types_(cet), description_(d), package_list_(p), + required_engines_(r), excluded_engines_(e), + checked_(false), available_(false) +{ + filename_ = id_ + ".citeengine"; +} + + +vector<string> LyXCiteEngine::prerequisites() const +{ + if (!checked_) + isAvailable(); + return prerequisites_; +} + + +bool LyXCiteEngine::isAvailable() const +{ + if (package_list_.empty()) + return true; + if (checked_) + return available_; + checked_ = true; + available_ = true; + //check whether all of the required packages are available + vector<string>::const_iterator it = package_list_.begin(); + vector<string>::const_iterator end = package_list_.end(); + for (; it != end; ++it) { + if (!LaTeXFeatures::isAvailable(*it)) { + available_ = false; + prerequisites_.push_back(*it); + } + } + return available_; +} + + +bool LyXCiteEngine::isCompatible(string const & cename) const +{ + // do we exclude it? + if (find(excluded_engines_.begin(), excluded_engines_.end(), cename) != + excluded_engines_.end()) + return false; + + LyXCiteEngine const * const lm = theCiteEnginesList[cename]; + if (!lm) + return true; + + // does it exclude us? + vector<string> const excengs = lm->getExcludedEngines(); + if (find(excengs.begin(), excengs.end(), id_) != excengs.end()) + return false; + + return true; +} + + +bool LyXCiteEngine::areCompatible(string const & eng1, string const & eng2) +{ + LyXCiteEngine const * const lm1 = theCiteEnginesList[eng1]; + if (lm1) + return lm1->isCompatible(eng2); + LyXCiteEngine const * const lm2 = theCiteEnginesList[eng2]; + if (lm2) + return lm2->isCompatible(eng1); + // Can't check it either way. + return true; +} + + +// used when sorting the cite engine list. +class EngineSorter { +public: + int operator()(LyXCiteEngine const & ce1, LyXCiteEngine const & ce2) const + { + return _(ce1.getName()) < _(ce2.getName()); + } +}; + + +// Much of this is borrowed from LayoutFileList::read() +bool CiteEnginesList::read() +{ + FileName const real_file = libFileSearch("", "lyxciteengines.lst"); + LYXERR(Debug::TCLASS, "Reading cite engines from `" << real_file << '\''); + + if (real_file.empty()) { + LYXERR0("unable to find cite engines file `citeengines.lst'.\n" + << "No cite engines will be available."); + return false; + } + + Lexer lex; + if (!lex.setFile(real_file)) { + LYXERR0("lyxlex was not able to set file: " + << real_file << ".\nNo cite engines will be available."); + return false; + } + + if (!lex.isOK()) { + LYXERR0("unable to open cite engines file `" + << to_utf8(makeDisplayPath(real_file.absFileName(), 1000)) + << "'\nNo cite engines will be available."); + return false; + } + + bool finished = false; + // Parse cite engines files + LYXERR(Debug::TCLASS, "Starting parsing of lyxciteengines.lst"); + while (lex.isOK() && !finished) { + LYXERR(Debug::TCLASS, "\tline by line"); + switch (lex.lex()) { + case Lexer::LEX_FEOF: + finished = true; + break; + default: + string const cename = lex.getString(); + LYXERR(Debug::TCLASS, "Engine name: " << cename); + if (!lex.next()) + break; + string const fname = lex.getString(); + LYXERR(Debug::TCLASS, "Filename: " << fname); + if (!lex.next(true)) + break; + string cet = lex.getString(); + LYXERR(Debug::TCLASS, "Engine Type: " << cet); + vector<string> cets; + while (!cet.empty()) { + string p; + cet = split(cet, p, '|'); + cets.push_back(p); + } + if (!lex.next(true)) + break; + string const desc = lex.getString(); + LYXERR(Debug::TCLASS, "Description: " << desc); + //FIXME Add packages + if (!lex.next()) + break; + string str = lex.getString(); + LYXERR(Debug::TCLASS, "Packages: " << str); + vector<string> pkgs; + while (!str.empty()) { + string p; + str = split(str, p, ','); + pkgs.push_back(p); + } + if (!lex.next()) + break; + str = lex.getString(); + LYXERR(Debug::TCLASS, "Required: " << str); + vector<string> req; + while (!str.empty()) { + string p; + str = split(str, p, '|'); + req.push_back(p); + } + if (!lex.next()) + break; + str = lex.getString(); + LYXERR(Debug::TCLASS, "Excluded: " << str); + vector<string> exc; + while (!str.empty()) { + string p; + str = split(str, p, '|'); + exc.push_back(p); + } + // This code is run when we have + // cename, fname, desc, pkgs, req and exc + addCiteEngine(cename, fname, cets, desc, pkgs, req, exc); + } // end switch + } //end while + + LYXERR(Debug::TCLASS, "End of parsing of lyxciteengines.lst"); + + if (!theCiteEnginesList.empty()) + sort(theCiteEnginesList.begin(), theCiteEnginesList.end(), EngineSorter()); + return true; +} + + +void CiteEnginesList::addCiteEngine(string const & cename, + string const & filename, vector<string> const & cets, string const & description, + vector<string> const & pkgs, vector<string> const & req, + vector<string> const & exc) +{ + LyXCiteEngine ce(cename, filename, cets, description, pkgs, req, exc); + englist_.push_back(ce); +} + + +LyXCiteEnginesList::const_iterator CiteEnginesList::begin() const +{ + return englist_.begin(); +} + + +LyXCiteEnginesList::iterator CiteEnginesList::begin() +{ + return englist_.begin(); +} + + +LyXCiteEnginesList::const_iterator CiteEnginesList::end() const +{ + return englist_.end(); +} + + +LyXCiteEnginesList::iterator CiteEnginesList::end() +{ + return englist_.end(); +} + + +LyXCiteEngine const * CiteEnginesList::operator[](string const & str) const +{ + LyXCiteEnginesList::const_iterator it = englist_.begin(); + for (; it != englist_.end(); ++it) + if (it->getID() == str) { + LyXCiteEngine const & eng = *it; + return ŋ + } + return 0; +} + + +LyXCiteEngine * CiteEnginesList::operator[](string const & str) +{ + LyXCiteEnginesList::iterator it = englist_.begin(); + for (; it != englist_.end(); ++it) + if (it->getID() == str) { + LyXCiteEngine & eng = *it; + return ŋ + } + return 0; +} + +} // namespace lyx diff --git a/src/CiteEnginesList.h b/src/CiteEnginesList.h new file mode 100644 index 0000000..0e6d119 --- /dev/null +++ b/src/CiteEnginesList.h @@ -0,0 +1,156 @@ +// -*- C++ -*- +/** + * \file CiteEnginesList.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Richard Heck + * \author Jürgen Spitzmüller + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef CITEENGINESLIST_H +#define CITEENGINESLIST_H + +#include <string> +#include <vector> + +namespace lyx { + +/** + * This class represents a particular LyX "cite engine", which defines the features + * of a particular citation backend such as natbib or biblatex. In that sense, it is more like + * a LaTeX package, where a layout file corresponds to a LaTeX class. + * + * In general, a given cite engine can be used with any document class. That said, + * one cite engine may `require' another, or it may `exclude' some other cite engine. + * The requires and excludes are given in comments within the cite engine file, + * which must begin roughly so: + * # \DeclareLyXCiteEngine[natbib.sty]{Natbib} + * # DescriptionBegin + * # Loads the LaTeX package natbib, a citation engine. Natbib supports + * # both author-year and numerical styles for citations, automatic sorting + * # and merging of numerical citations, annotations, capitalization of the + * # `van' part of author names, shortened and full author lists, and more. + * # DescriptionEnd + * # Excludes: basic | jurabib + * The description might be used in the gui to give information to the user. The + * Requires and Excludes lines are read by the configuration script + * and written to a file citeengines.lst in the user configuration directory. + * That file is then read on startup to populate the CiteEnginesList, below. + * + * Engines can also be "provided" or "excluded" by document classes, using + * the ProvidesEngine and ExcludesEngine tags. + */ + +class LyXCiteEngine { +public: + /// + LyXCiteEngine(std::string const & name, std::string const & id, + std::vector<std::string> const & enginetypes, + std::string const & description, + std::vector<std::string> const & packagelist, + std::vector<std::string> const & requires, + std::vector<std::string> const & excludes); + /// whether the required packages are available + bool isAvailable() const; + /// the missing prerequisites, if any + std::vector<std::string> prerequisites() const; + /// + std::string const & getName() const { return name_; } + /// + std::string const & getID() const { return id_; } + /// + std::string const & getFilename() const { return filename_; } + /// + std::vector<std::string> const & getEngineType() const { return engine_types_; } + /// + std::string const & getDescription() const { return description_; } + /// + std::vector<std::string> const & getPackageList() const + { return package_list_; } + /// + std::vector<std::string> const & getRequiredEngines() const + { return required_engines_; } + /// Engines this one excludes: the list should be treated disjunctively + std::vector<std::string> const & getExcludedEngines() const + { return excluded_engines_; } + /// \return true if the engine is compatible with this one, i.e., + /// it does not exclude us and we do not exclude it. + /// this will also return true if cename is unknown and we do not + /// exclude it, since in that case we cannot check its exclusions. + bool isCompatible(std::string const & cename) const; + /// + static bool areCompatible(std::string const & eng1, std::string const & eng2); +private: + /// what appears in the ui + std::string name_; + /// the engine's unique identifier + /// at present, this is the filename, without the extension + std::string id_; + /// the filename + std::string filename_; + /// the engine type(s) + std::vector<std::string> engine_types_; + /// a short description for use in the ui + std::string description_; + /// the LaTeX packages on which this depends, if any + std::vector<std::string> package_list_; + /// Engines this one requires: at least one + std::vector<std::string> required_engines_; + /// Engines this one excludes: none of these + std::vector<std::string> excluded_engines_; + // these are mutable because they are used to cache the results + // or an otherwise const operation. + /// + mutable bool checked_; + /// + mutable bool available_; + /// + mutable std::vector<std::string> prerequisites_; +}; + +typedef std::vector<LyXCiteEngine> LyXCiteEnginesList; + +/** + * The CiteEnginesList represents the various LyXCiteEngine's that are available at + * present. + */ +class CiteEnginesList { +public: + /// + CiteEnginesList() {} + /// reads the engines from a file generated by configure.py + bool read(); + /// + LyXCiteEnginesList::const_iterator begin() const; + /// + LyXCiteEnginesList::iterator begin(); + /// + LyXCiteEnginesList::const_iterator end() const; + /// + LyXCiteEnginesList::iterator end(); + /// + bool empty() const { return englist_.empty(); } + /// Returns a pointer to the LyXCiteEngine with filename str. + /// Returns a null pointer if no such engine is found. + LyXCiteEngine const * operator[](std::string const & str) const; + /// + LyXCiteEngine * operator[](std::string const & str); + private: + /// noncopyable + CiteEnginesList(CiteEnginesList const &); + /// + void operator=(CiteEnginesList const &); + /// add an engine to the list + void addCiteEngine(std::string const &, std::string const &, + std::vector<std::string> const &, std::string const &, std::vector<std::string> const &, + std::vector<std::string> const &, std::vector<std::string> const &); + /// + std::vector<LyXCiteEngine> englist_; +}; + +extern CiteEnginesList theCiteEnginesList; +} +#endif diff --git a/src/LyX.cpp b/src/LyX.cpp index 047e265..157d432 100644 --- a/src/LyX.cpp +++ b/src/LyX.cpp @@ -22,6 +22,7 @@ #include "Buffer.h" #include "BufferList.h" #include "CmdDef.h" +#include "CiteEnginesList.h" #include "ColorSet.h" #include "ConverterCache.h" #include "Converter.h" @@ -935,8 +936,10 @@ bool LyX::init() LYXERR(Debug::INIT, "Reading layouts..."); // Load the layouts LayoutFileList::get().read(); - //...and the modules + //... the modules theModuleList.read(); + //... and the cite engines + theCiteEnginesList.read(); // read keymap and ui files in batch mode as well // because InsetInfo needs to know these to produce @@ -1020,7 +1023,8 @@ bool LyX::queryUserLyXDir(bool explicit_userdir) return configFileNeedsUpdate("lyxrc.defaults") || configFileNeedsUpdate("lyxmodules.lst") || configFileNeedsUpdate("textclass.lst") - || configFileNeedsUpdate("packages.lst"); + || configFileNeedsUpdate("packages.lst") + || configFileNeedsUpdate("lyxciteengines.lst"); } first_start = !explicit_userdir; diff --git a/src/Makefile.am b/src/Makefile.am index f87d029..4cb38b5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -108,6 +108,7 @@ SOURCEFILESCORE = \ Bullet.cpp \ Changes.cpp \ Chktex.cpp \ + CiteEnginesList.cpp \ CmdDef.cpp \ Color.cpp \ ConverterCache.cpp \ @@ -201,6 +202,7 @@ HEADERFILESCORE = \ BufferView.h \ Bullet.h \ Citation.h \ + CiteEnginesList.h \ Changes.h \ Chktex.h \ CmdDef.h \ diff --git a/src/TextClass.cpp b/src/TextClass.cpp index 46a96e4..d14ef29 100644 --- a/src/TextClass.cpp +++ b/src/TextClass.cpp @@ -17,6 +17,7 @@ #include "TextClass.h" #include "LayoutFile.h" +#include "CiteEnginesList.h" #include "Color.h" #include "Counters.h" #include "Floating.h" @@ -123,6 +124,8 @@ string translateReadType(TextClass::ReadType rt) return "input file"; case TextClass::MODULE: return "module file"; + case TextClass::CITE_ENGINE: + return "cite engine"; case TextClass::VALIDATION: return "validation"; } @@ -1585,6 +1588,7 @@ Layout TextClass::createBasicLayout(docstring const & name, bool unknown) const DocumentClassPtr getDocumentClass( LayoutFile const & baseClass, LayoutModuleList const & modlist, + LayoutModuleList const & celist, bool const clone) { DocumentClassPtr doc_class = @@ -1623,6 +1627,42 @@ DocumentClassPtr getDocumentClass( frontend::Alert::warning(_("Read Error"), msg); } } + + LayoutModuleList::const_iterator cit = celist.begin(); + LayoutModuleList::const_iterator cen = celist.end(); + for (; cit != cen; ++cit) { + string const ceName = *cit; + LyXCiteEngine * ce = theCiteEnginesList[ceName]; + if (!ce) { + docstring const msg = + bformat(_("The cite engine %1$s has been requested by\n" + "this document but has not been found in the list of\n" + "available engines. If you recently installed it, you\n" + "probably need to reconfigure LyX.\n"), from_utf8(ceName)); + if (!clone) + frontend::Alert::warning(_("Cite Engine not available"), msg); + continue; + } + if (!ce->isAvailable() && !clone) { + docstring const prereqs = from_utf8(getStringFromVector(ce->prerequisites(), "\n\t")); + docstring const msg = + bformat(_("The cite engine %1$s requires a package that is not\n" + "available in your LaTeX installation, or a converter that\n" + "you have not installed. LaTeX output may not be possible.\n" + "Missing prerequisites:\n" + "\t%2$s\n" + "See section 3.1.2.3 (Modules) of the User's Guide for more information."), + from_utf8(ceName), prereqs); + frontend::Alert::warning(_("Package not available"), msg, true); + } + FileName layout_file = libFileSearch("citeengines", ce->getFilename()); + if (!doc_class->read(layout_file, TextClass::CITE_ENGINE)) { + docstring const msg = + bformat(_("Error reading cite engine %1$s\n"), from_utf8(ceName)); + frontend::Alert::warning(_("Read Error"), msg); + } + } + return doc_class; } diff --git a/src/TextClass.h b/src/TextClass.h index 22d426c..d082e10 100644 --- a/src/TextClass.h +++ b/src/TextClass.h @@ -151,6 +151,7 @@ public: BASECLASS, //>This is a base class, i.e., top-level layout file MERGE, //>This is a file included in a layout file MODULE, //>This is a layout module + CITE_ENGINE, //>This is a cite engine VALIDATION //>We're just validating }; /// return values for read() @@ -498,6 +499,7 @@ private: /// The only way to make a DocumentClass is to call this function. friend DocumentClassPtr getDocumentClass(LayoutFile const &, LayoutModuleList const &, + LayoutModuleList const &, bool const clone); }; @@ -508,6 +510,7 @@ private: /// on the CutStack. DocumentClassPtr getDocumentClass(LayoutFile const & baseClass, LayoutModuleList const & modlist, + LayoutModuleList const & celist, bool const clone = false); /// convert page sides option to text 1 or 2 diff --git a/src/tex2lyx/Makefile.am b/src/tex2lyx/Makefile.am index bf2d66d..a4a5fdc 100644 --- a/src/tex2lyx/Makefile.am +++ b/src/tex2lyx/Makefile.am @@ -83,6 +83,7 @@ updatetests: tex2lyx LINKED_FILES = \ ../Author.cpp \ + ../CiteEnginesList.cpp \ ../Color.cpp \ ../Counters.cpp \ ../Encoding.cpp \ diff --git a/src/tex2lyx/tex2lyx.cpp b/src/tex2lyx/tex2lyx.cpp index 7a6bbb0..3f6fe73 100644 --- a/src/tex2lyx/tex2lyx.cpp +++ b/src/tex2lyx/tex2lyx.cpp @@ -282,10 +282,11 @@ void initModules() for (; it != end; ++it) { string const module = it->getID(); LayoutModuleList m; + LayoutModuleList c; vector<string> v; if (!addModule(module, baseClass, m, v)) continue; - modules[module] = getDocumentClass(baseClass, m); + modules[module] = getDocumentClass(baseClass, m, c); } init = false; } ----------------------------------------------------------------------- Summary of changes: lib/Makefile.am | 9 +- lib/chkconfig.ltx | 1 + .../basic.module => citeengines/basic.citeengine} | 6 +- .../jurabib.citeengine} | 9 +- .../natbib.citeengine} | 11 +- lib/configure.py | 131 ++++++++- po/Rules-lyx | 2 +- po/lyx_pot.py | 7 + src/BufferParams.cpp | 31 +-- src/CiteEnginesList.cpp | 326 ++++++++++++++++++++ src/CiteEnginesList.h | 164 ++++++++++ src/LyX.cpp | 8 +- src/Makefile.am | 2 + src/TextClass.cpp | 40 +++ src/TextClass.h | 3 + src/frontends/qt4/GuiDocument.cpp | 136 +++++---- src/frontends/qt4/GuiDocument.h | 3 + src/frontends/qt4/ui/BiblioUi.ui | 203 ++++++------ src/tex2lyx/Makefile.am | 1 + src/tex2lyx/tex2lyx.cpp | 3 +- 20 files changed, 883 insertions(+), 213 deletions(-) rename lib/{layouts/basic.module => citeengines/basic.citeengine} (83%) rename lib/{layouts/jurabib.module => citeengines/jurabib.citeengine} (91%) rename lib/{layouts/natbib.module => citeengines/natbib.citeengine} (89%) create mode 100644 src/CiteEnginesList.cpp create mode 100644 src/CiteEnginesList.h hooks/post-receive -- Repository for new features
