Move the citation engine machinery to layouts.

Add a new layout syntax CiteEngine to define the citation commands
available for a given citation engine.

Also extend the CiteFormat syntax to allow more customization. This
mechanism, previously used to produce bibliography entries in the
citation GUI based on the BibTeX entrytype, is now also used to
produce the textual labels for citation insets in the buffer view.

Thus citation styles are almost completely customizable by modules.
Modules for the basic, jurabib and natbib engines are implemented.

Layout format incremented to 37.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@40820 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Julien Rioux 2012-03-01 00:41:30 +00:00
parent 69b2843d46
commit 1e947e3a18
21 changed files with 979 additions and 781 deletions

View File

@ -1334,6 +1334,7 @@ dist_layouts_DATA =\
layouts/armenian-article.layout \
layouts/article.layout \
layouts/article-beamer.layout \
layouts/basic.module \
layouts/beamer.layout \
layouts/bicaption.module \
layouts/book.layout \
@ -1401,6 +1402,7 @@ dist_layouts_DATA =\
layouts/jsarticle.layout \
layouts/jsbook.layout \
layouts/jss.layout \
layouts/jurabib.module \
layouts/kluwer.layout \
layouts/knitr.module \
layouts/latex8.layout \
@ -1423,6 +1425,7 @@ dist_layouts_DATA =\
layouts/mwart.layout \
layouts/mwbk.layout \
layouts/mwrep.layout \
layouts/natbib.module \
layouts/noweb.module \
layouts/numarticle.inc \
layouts/numreport.inc \

41
lib/layouts/basic.module Normal file
View File

@ -0,0 +1,41 @@
# \DeclareLyXModule{Default (basic)}
# DescriptionBegin
# Use the basic citation capabilities provided by plain LaTeX.
# DescriptionEnd
# Excludes: jurabib | natbib
# Category: Citation engine
# Author: Julien Rioux <jrioux@lyx.org>
Format 37
CiteEngineType numerical
DefaultBiblio plain
CiteEngine default
cite[]
nocite
End
CiteFormat default
# translatable bits
_notcited not cited
_addtobib Add to bibliography only.
# macros
!open [
!sep ,
!close ]
!cite {%label%[[%label%]][[#%key%]]}%!nextcite%
!nextcite {%next%[[%!sep% %!cite%]]}
!nexthashkey {%next%[[%!sep% #%key%%!nexthashkey%]]}
!nextkey {%next%[[%!sep% %key%%!nextkey%]]}
!textafter {%textafter%[[, %textafter%]]}
# cite styles
cite %!open%{%dialog%[[#ID]][[%!cite%]]}%!textafter%%!close%
nocite {%dialog%[[%_addtobib%]][[%key%%!nextkey% (%_notcited%)]]}
End

101
lib/layouts/jurabib.module Normal file
View File

@ -0,0 +1,101 @@
# \DeclareLyXModule[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 <jrioux@lyx.org>
Format 37
Requires jurabib
CiteEngineType authoryear
DefaultBiblio jurabib
# FIXME: support for these jurabib styles (fileformat)
# citefield []{}
# footcite [][]
# footcitetitle [][]
# footcitet [][]
# footcitep [][]
# footcitealt [][]
# footcitealp [][]
# footciteauthor [][]
# footciteyear [][]
# footciteyearpar [][]
# footfullcite [][]
CiteEngine authoryear
# \cite* is not implemented: use \cite instead, it's the same
cite [][]
citetitle [][]
citet [][]
citep [][]
citealt [][]
citealp [][]
citeauthor [][]
citeyear [][]
citeyearpar [][]
fullcite [][]
nocite
End
CiteFormat authoryear
# translatable bits
_notcited not cited
_addtobib Add to bibliography only.
_fullcite bibliography entry
_bibentry Bibliography entry.
_before before
_shorttitle short title
# macros
!open (
!sep ;
!close )
!cite %!shortauthor%%!textbefore2%%!textafter2%%!nextcite%
!citetitle %!shortauthor%%!textbefore2%%!shorttitle%%!textafter2%%!nextcitetitle%
!citet %!textbefore%%!shortauthor% %!open%%!year%%!textafter%%!close%%!nextcitet%
!citep %!open%%!citealp%%!close%
!citealt %!textbefore%%!shortauthor% %!year%%!textafter%%!nextcitealt%
!citealp %!textbefore%%!shortauthor%, %!year%%!textafter%%!nextcitealp%
!citeauthor %!textbefore%%!shortauthor%%!textafter%%!nextauthor%
!citeyear %!textbefore%%!year%%!textafter%%!nextyear%
!citeyearpar %!textbefore%%!open%%!year%%!close%%!textafter%%!nextyearpar%
!nextcite {%next%[[%!sep% %!shortauthor%%!textafter2%%!nextcite%]]}
!nextcitetitle {%next%[[%!sep% %!shortauthor%%!shorttitle%%!textafter2%%!nextcitetitle%]]}
!nextcitet {%next%[[%!sep% %!citet%]]}
!nextcitealt {%next%[[%!sep% %!citealt%]]}
!nextcitealp {%next%[[%!sep% %!citealp%]]}
!nextauthor {%next%[[%!sep% %!citeauthor%]]}
!nextyear {%next%[[%!sep% %!citeyear%]]}
!nextyearpar {%next%[[%!sep% %!citeyearpar%]]}
!nextkey {%next%[[%!sep% %key%%!nextkey%]]}
!shortauthor {%shortauthor%[[%shortauthor%]][[??]]}
!shorttitle {%shorttitle%[[ %shorttitle%]][[{%dialog%[[ <%_shorttitle%>]]}]]}
!textbefore {%textbefore%[[%textbefore% ]]}
!textbefore2 {%textbefore%[[/%textbefore%]][[{%dialog%[[/<%_before%>]]}]]}
!textafter {%textafter%[[, %textafter%]]}
!textafter2 {%textafter%[[ %textafter%]]}
!year {%year%[[%year%]][[??]]}
# cite styles
cite %!cite%
citetitle %!citetitle%
citet %!citet%
citep %!citep%
citealt %!citealt%
citealp %!citealp%
citeauthor %!citeauthor%
citeyear %!citeyear%
citeyearpar %!citeyearpar%
fullcite {%dialog%[[%_bibentry%]][[%key%%!nextkey% (%_fullcite%)]]}
nocite {%dialog%[[%_addtobib%]][[%key%%!nextkey% (%_notcited%)]]}
End

100
lib/layouts/natbib.module Normal file
View File

@ -0,0 +1,100 @@
# \DeclareLyXModule[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
# Category: Citation engine
# Author: Julien Rioux <jrioux@lyx.org>
Format 37
Requires natbib
CiteEngineType authoryear|numerical
DefaultBiblio plainnat
CiteEngine authoryear
Citet*[][]
Citep*[][]
Citealt*[][]
Citealp*[][]
Citeauthor*[]
citeyear[]
citeyearpar[][]
nocite
End
CiteEngine numerical
Citep*[][]
Citealp*[][]
Citet*[][]
Citealt*[][]
Citeauthor*
citeyearpar[][]
citeyear
nocite
End
CiteFormat default
# translatable bits
_notcited not cited
_addtobib Add to bibliography only.
# macros
!open [
!sep ,
!close ]
!nextauthor {%next%[[%!sep% %!abbrvauthor%%!nextauthor%]]}
!nextkey {%next%[[%!sep% %key%%!nextkey%]]}
!nextyear {%next%[[%!sep% %!year%%!nextyear%]]}
!abbrvauthor {%abbrvauthor%[[%abbrvauthor%]][[??]]}
!textbefore {%textbefore%[[%textbefore% ]]}
!textafter {%textafter%[[, %textafter%]]}
!year {%year%[[%year%]][[??]]}
# cite styles
citet %!citet%%!textafter%%!close%
citealt %!citealt%%!textafter%
citeyearpar %!open%%!textbefore%%!year%%!nextyear%%!textafter%%!close%
nocite {%dialog%[[%_addtobib%]][[%key%%!nextkey% (%_notcited%)]]}
End
CiteFormat authoryear
!citet %!abbrvauthor% %!open%%!textbefore%%!year%%!nextcitet%
!citealt %!abbrvauthor% %!textbefore%%!year%%!nextcitealt%
!citealp %!abbrvauthor%, %!year%%!nextcitealp%
!nextcitet {%next%[[%!close%%!sep% %!citet%]]}
!nextcitealt {%next%[[%!sep% %!citealt%]]}
!nextcitealp {%next%[[%!sep% %!citealp%]]}
cite %!citet%%!textafter%%!close%
citep %!open%%!textbefore%%!citealp%%!textafter%%!close%
citealp %!textbefore%%!citealp%%!textafter%
citeauthor %!abbrvauthor%%!nextauthor%%!textafter%
citeyear %!year%%!nextyear%%!textafter%
End
CiteFormat numerical
!citet %!abbrvauthor% %!open%%!textbefore%{%dialog%[[#ID]][[#%key%]]}%!nextcitet%
!citealt %!abbrvauthor% %!textbefore%{%dialog%[[#ID]][[#%key%]]}%!nextcitealt%
!hashkey {%dialog%[[#ID]][[#%key%%!nexthashkey%]]}
!nextcitet {%next%[[%!close%%!sep% %!citet%]]}
!nextcitealt {%next%[[%!sep% %!citealt%]]}
!nexthashid {%next%[[%!sep% #ID%!nexthashid%]]}
!nexthashkey {%next%[[%!sep% #%key%%!nexthashkey%]]}
cite %!open%%!textbefore%%!hashkey%%!textafter%%!close%
citep %!open%%!textbefore%%!hashkey%%!textafter%%!close%
citealp %!textbefore%%!hashkey%%!textafter%
citeauthor %!abbrvauthor%%!nextauthor%
citeyear %!year%%!nextyear%
End

View File

@ -125,6 +125,10 @@ import os, re, string, sys
# Incremented to format 36, 7 December 2011, by rgh
# Added HTMLStyles and AddToHTMLStyles tags.
# Incremented to format 37, 29 February 2012 by jrioux
# Implement the citation engine machinery in layouts.
# Change CiteFormat to CiteFormat (default|authoryear|numerical).
# Do not forget to document format change in Customization
# Manual (section "Declaring a new text class").
@ -132,7 +136,7 @@ import os, re, string, sys
# development/tools/updatelayouts.sh script to update all
# layout files to the new format.
currentFormat = 36
currentFormat = 37
def usage(prog_name):
@ -206,6 +210,7 @@ def convert(lines):
re_End = re.compile(r'^(\s*)(End)(\s*)$', re.IGNORECASE)
re_Provides = re.compile(r'^(\s*)Provides(\S+)(\s+)(\S+)', re.IGNORECASE)
re_CharStyle = re.compile(r'^(\s*)CharStyle(\s+)(\S+)$', re.IGNORECASE)
re_CiteFormat = re.compile(r'^(\s*)(CiteFormat)(?:(\s*)()|(\s+)(default|authoryear|numerical))', re.IGNORECASE)
re_AMSMaths = re.compile(r'^\s*Input ams(?:math|def)s.inc\s*')
re_AMSMathsPlain = re.compile(r'^\s*Input amsmaths-plain.inc\s*')
re_AMSMathsSeq = re.compile(r'^\s*Input amsmaths-seq.inc\s*')
@ -317,6 +322,13 @@ def convert(lines):
i += 1
continue
if format == 36:
match = re_CiteFormat.match(lines[i]);
if match and match.group(4) == "":
lines[i] = match.group(0) + " default"
i += 1
continue
if format == 35:
i += 1
continue

View File

@ -206,7 +206,7 @@ BibTeXInfo::BibTeXInfo(docstring const & key, docstring const & type)
{}
docstring const BibTeXInfo::getAbbreviatedAuthor() const
docstring const BibTeXInfo::getAbbreviatedAuthor(bool jurabib_style) const
{
if (!is_bibtex_) {
docstring const opt = label();
@ -226,7 +226,7 @@ docstring const BibTeXInfo::getAbbreviatedAuthor() const
if (author.empty()) {
author = convertLaTeXCommands(operator[]("editor"));
if (author.empty())
return bib_key_;
return author;
}
// FIXME Move this to a separate routine that can
@ -237,6 +237,14 @@ docstring const BibTeXInfo::getAbbreviatedAuthor() const
vector<docstring> const authors =
getVectorFromString(author, from_ascii(" and "));
if (jurabib_style && (authors.size() == 2 || authors.size() == 3)) {
docstring shortauthor = familyName(authors[0])
+ "/" + familyName(authors[1]);
if (authors.size() == 3)
shortauthor += "/" + familyName(authors[2]);
return shortauthor;
}
if (authors.size() == 2)
return bformat(_("%1$s and %2$s"),
familyName(authors[0]), familyName(authors[1]));
@ -391,7 +399,7 @@ namespace {
docstring BibTeXInfo::expandFormat(string const & format,
BibTeXInfo const * const xref, int & counter, Buffer const & buf,
bool richtext) const
bool richtext, docstring before, docstring after, docstring dialog, bool next) const
{
// incorrect use of macros could put us in an infinite loop
static int max_passes = 5000;
@ -400,6 +408,7 @@ docstring BibTeXInfo::expandFormat(string const & format,
bool scanning_key = false;
bool scanning_rich = false;
CiteEngineType const engine_type = buf.params().citeEngineType();
string fmt = format;
// we'll remove characters from the front of fmt as we
// deal with them
@ -419,19 +428,21 @@ docstring BibTeXInfo::expandFormat(string const & format,
// so we replace the key with its value, which may be empty
if (key[0] == '!') {
// macro
// FIXME: instead of passing the buf, just past the macros
// FIXME: and the language code
string const val =
buf.params().documentClass().getCiteMacro(key);
buf.params().documentClass().getCiteMacro(engine_type, key);
fmt = val + fmt.substr(1);
continue;
} else if (key[0] == '_') {
// a translatable bit
string const val =
buf.params().documentClass().getCiteMacro(key);
buf.params().documentClass().getCiteMacro(engine_type, key);
docstring const trans =
translateIfPossible(from_utf8(val), buf.params().language->code());
ret += trans;
} else {
docstring const val = getValueForKey(key, xref);
docstring const val = getValueForKey(key, before, after, dialog, xref);
ret += val;
}
} else {
@ -457,11 +468,15 @@ docstring BibTeXInfo::expandFormat(string const & format,
if (newfmt == fmt) // parse error
return _("ERROR!");
fmt = newfmt;
docstring const val = getValueForKey(optkey, xref);
if (!val.empty())
ret += expandFormat(ifpart, xref, counter, buf, richtext);
docstring const val = getValueForKey(optkey, before, after, dialog, xref);
if (optkey == "next" && next)
ret += from_utf8(ifpart); // without expansion
else if (!val.empty())
ret += expandFormat(ifpart, xref, counter, buf,
richtext, before, after, dialog, next);
else if (!elsepart.empty())
ret += expandFormat(elsepart, xref, counter, buf, richtext);
ret += expandFormat(elsepart, xref, counter, buf,
richtext, before, after, dialog, next);
// fmt will have been shortened for us already
continue;
}
@ -527,8 +542,9 @@ docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref,
return info_;
}
CiteEngineType const engine_type = buf.params().citeEngineType();
DocumentClass const & dc = buf.params().documentClass();
string const & format = dc.getCiteFormat(to_utf8(entry_type_));
string const & format = dc.getCiteFormat(engine_type, to_utf8(entry_type_));
int counter = 0;
info_ = expandFormat(format, xref, counter, buf, richtext);
@ -538,6 +554,30 @@ docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref,
}
docstring const BibTeXInfo::getLabel(BibTeXInfo const * const xref,
Buffer const & buf, string const & format, bool richtext,
docstring before, docstring after, docstring dialog, bool next) const
{
docstring loclabel_;
/*
if (!is_bibtex_) {
BibTeXInfo::const_iterator it = find(from_ascii("ref"));
label_ = it->second;
return label_;
}
*/
int counter = 0;
loclabel_ = expandFormat(format, xref, counter, buf, richtext,
before, after, dialog, next);
if (!loclabel_.empty())
loclabel_ = convertLaTeXCommands(loclabel_);
return loclabel_;
}
docstring const & BibTeXInfo::operator[](docstring const & field) const
{
BibTeXInfo::const_iterator it = find(field);
@ -555,12 +595,48 @@ docstring const & BibTeXInfo::operator[](string const & field) const
docstring BibTeXInfo::getValueForKey(string const & key,
BibTeXInfo const * const xref) const
docstring const & before, docstring const & after, docstring const & dialog,
BibTeXInfo const * const xref) const
{
docstring const ret = operator[](key);
if (!ret.empty() || !xref)
docstring ret = operator[](key);
if (ret.empty() && xref)
ret = (*xref)[key];
if (!ret.empty())
return ret;
return (*xref)[key];
// some special keys
// FIXME: dialog, textbefore and textafter have nothing to do with this
if (key == "dialog")
return dialog;
else if (key == "entrytype")
return entry_type_;
else if (key == "key")
return bib_key_;
else if (key == "label")
return label_;
else if (key == "abbrvauthor")
// Special key to provide abbreviated author names.
return getAbbreviatedAuthor();
else if (key == "shortauthor")
// When shortauthor is not defined, jurabib automatically
// provides jurabib-style abbreviated author names. We do
// this as well.
return getAbbreviatedAuthor(true);
else if (key == "shorttitle") {
// When shorttitle is not defined, jurabib uses for `article'
// and `periodical' entries the form `journal volume [year]'
// and for other types of entries it uses the `title' field.
if (entry_type_ == "article" || entry_type_ == "periodical")
return operator[]("journal") + " " + operator[]("volume")
+ " [" + operator[]("year") + "]";
else
return operator[]("title");
} else if (key == "textbefore")
return before;
else if (key == "textafter")
return after;
else if (key == "year")
return getYear();
return ret;
}
@ -679,6 +755,38 @@ docstring const BiblioInfo::getInfo(docstring const & key,
}
docstring const BiblioInfo::getLabel(vector<docstring> const & keys,
Buffer const & buf, string const & style, bool richtext,
docstring const & before, docstring const & after, docstring const & dialog) const
{
CiteEngineType const engine_type = buf.params().citeEngineType();
DocumentClass const & dc = buf.params().documentClass();
string const & format = dc.getCiteFormat(engine_type, style, "cite");
docstring ret = from_utf8(format);
vector<docstring>::const_iterator key = keys.begin();
vector<docstring>::const_iterator ken = keys.end();
for (; key != ken; ++key) {
BiblioInfo::const_iterator it = find(*key);
BibTeXInfo empty_data;
empty_data.key(*key);
BibTeXInfo & data = empty_data;
BibTeXInfo const * xrefptr = 0;
if (it != end()) {
data = it->second;
docstring const xref = data.getXRef();
if (!xref.empty()) {
BiblioInfo::const_iterator const xrefit = find(xref);
if (xrefit != end())
xrefptr = &(xrefit->second);
}
}
ret = data.getLabel(xrefptr, buf, to_utf8(ret), richtext,
before, after, dialog, key+1 != ken);
}
return ret;
}
bool BiblioInfo::isBibtex(docstring const & key) const
{
BiblioInfo::const_iterator it = find(key);
@ -688,141 +796,25 @@ bool BiblioInfo::isBibtex(docstring const & key) const
}
vector<docstring> const BiblioInfo::getCiteStrings(
docstring const & key, Buffer const & buf) const
{
CiteEngineType const engine_type = buf.params().citeEngineType();
if (engine_type == ENGINE_TYPE_NUMERICAL)
return getNumericalStrings(key, buf);
else
return getAuthorYearStrings(key, buf);
}
vector<docstring> const BiblioInfo::getNumericalStrings(
docstring const & key, Buffer const & buf) const
vector<docstring> const & keys, vector<CitationStyle> const & styles,
Buffer const & buf, bool richtext, docstring const & before,
docstring const & after, docstring const & dialog) const
{
if (empty())
return vector<docstring>();
docstring const author = getAbbreviatedAuthor(key);
docstring const year = getYear(key);
if (author.empty() || year.empty())
return vector<docstring>();
vector<CiteStyle> const & styles = citeStyles(buf.params().citeEngine(),
buf.params().citeEngineType());
string style;
vector<docstring> vec(styles.size());
for (size_t i = 0; i != vec.size(); ++i) {
docstring str;
switch (styles[i]) {
case CITE:
case CITEP:
str = from_ascii("[#ID]");
break;
case NOCITE:
str = _("Add to bibliography only.");
break;
case CITET:
str = author + " [#ID]";
break;
case CITEALT:
str = author + " #ID";
break;
case CITEALP:
str = from_ascii("#ID");
break;
case CITEAUTHOR:
str = author;
break;
case CITEYEAR:
str = year;
break;
case CITEYEARPAR:
str = '(' + year + ')';
break;
}
vec[i] = str;
style = styles[i].cmd;
vec[i] = getLabel(keys, buf, style, richtext, before, after, dialog);
}
return vec;
}
vector<docstring> const BiblioInfo::getAuthorYearStrings(
docstring const & key, Buffer const & buf) const
{
if (empty())
return vector<docstring>();
docstring const author = getAbbreviatedAuthor(key);
docstring const year = getYear(key);
if (author.empty() || year.empty())
return vector<docstring>();
vector<CiteStyle> const & styles = citeStyles(buf.params().citeEngine(),
buf.params().citeEngineType());
vector<docstring> vec(styles.size());
for (size_t i = 0; i != vec.size(); ++i) {
docstring str;
switch (styles[i]) {
case CITE:
// jurabib only: Author/Annotator
// (i.e. the "before" field, 2nd opt arg)
str = author + "/<" + _("before") + '>';
break;
case NOCITE:
str = _("Add to bibliography only.");
break;
case CITET:
str = author + " (" + year + ')';
break;
case CITEP:
str = '(' + author + ", " + year + ')';
break;
case CITEALT:
str = author + ' ' + year ;
break;
case CITEALP:
str = author + ", " + year ;
break;
case CITEAUTHOR:
str = author;
break;
case CITEYEAR:
str = year;
break;
case CITEYEARPAR:
str = '(' + year + ')';
break;
}
vec[i] = str;
}
return vec;
}
void BiblioInfo::mergeBiblioInfo(BiblioInfo const & info)
{
bimap_.insert(info.begin(), info.end());
@ -947,128 +939,38 @@ void BiblioInfo::makeCitationLabels(Buffer const & buf)
//
//////////////////////////////////////////////////////////////////////
namespace {
char const * const citeCommands[] = {
"cite", "citet", "citep", "citealt", "citealp",
"citeauthor", "citeyear", "citeyearpar", "nocite" };
unsigned int const nCiteCommands =
sizeof(citeCommands) / sizeof(char *);
CiteStyle const citeStylesArray[] = {
CITE, CITET, CITEP, CITEALT, CITEALP,
CITEAUTHOR, CITEYEAR, CITEYEARPAR, NOCITE };
unsigned int const nCiteStyles =
sizeof(citeStylesArray) / sizeof(CiteStyle);
CiteStyle const citeStylesFull[] = {
CITET, CITEP, CITEALT, CITEALP, CITEAUTHOR };
unsigned int const nCiteStylesFull =
sizeof(citeStylesFull) / sizeof(CiteStyle);
CiteStyle const citeStylesUCase[] = {
CITET, CITEP, CITEALT, CITEALP, CITEAUTHOR };
unsigned int const nCiteStylesUCase =
sizeof(citeStylesUCase) / sizeof(CiteStyle);
} // namespace anon
CitationStyle citationStyleFromString(string const & command)
{
CitationStyle s;
CitationStyle cs;
if (command.empty())
return s;
return cs;
string cmd = command;
if (cmd[0] == 'C') {
s.forceUpperCase = true;
cs.forceUpperCase = true;
cmd[0] = 'c';
}
size_t const n = cmd.size() - 1;
if (cmd != "cite" && cmd[n] == '*') {
s.full = true;
if (cmd[n] == '*') {
cs.fullAuthorList = true;
cmd = cmd.substr(0, n);
}
char const * const * const last = citeCommands + nCiteCommands;
char const * const * const ptr = find(citeCommands, last, cmd);
if (ptr != last) {
size_t idx = ptr - citeCommands;
s.style = citeStylesArray[idx];
}
return s;
cs.cmd = cmd;
return cs;
}
string citationStyleToString(const CitationStyle & s)
string citationStyleToString(const CitationStyle & cs)
{
string cite = citeCommands[s.style];
if (s.full) {
CiteStyle const * last = citeStylesFull + nCiteStylesFull;
if (std::find(citeStylesFull, last, s.style) != last)
cite += '*';
}
if (s.forceUpperCase) {
CiteStyle const * last = citeStylesUCase + nCiteStylesUCase;
if (std::find(citeStylesUCase, last, s.style) != last)
cite[0] = 'C';
}
return cite;
}
vector<CiteStyle> citeStyles(CiteEngine engine, CiteEngineType engine_type)
{
vector<CiteStyle> styles(0);
if (engine_type == ENGINE_TYPE_AUTHORYEAR) {
switch (engine) {
case ENGINE_BASIC:
styles.push_back(CITE);
break;
case ENGINE_JURABIB:
styles.push_back(CITE);
case ENGINE_NATBIB:
styles.push_back(CITET);
styles.push_back(CITEP);
styles.push_back(CITEALT);
styles.push_back(CITEALP);
styles.push_back(CITEAUTHOR);
styles.push_back(CITEYEAR);
styles.push_back(CITEYEARPAR);
break;
}
} else {
switch (engine) {
case ENGINE_BASIC:
styles.push_back(CITE);
break;
case ENGINE_JURABIB:
styles.push_back(CITE);
case ENGINE_NATBIB:
styles.push_back(CITET);
styles.push_back(CITEALT);
styles.push_back(CITEAUTHOR);
styles.push_back(CITEP);
styles.push_back(CITEALP);
styles.push_back(CITEYEAR);
styles.push_back(CITEYEARPAR);
break;
}
}
styles.push_back(NOCITE);
return styles;
string cmd = cs.cmd;
if (cs.forceUpperCase)
cmd[0] = 'C';
if (cs.fullAuthorList)
cmd += '*';
return cmd;
}
} // namespace lyx

View File

@ -27,9 +27,6 @@ namespace lyx {
class Buffer;
/// FIXME: To Citation.cpp?
/// Returns a vector of available Citation styles.
std::vector<CiteStyle> citeStyles(CiteEngine, CiteEngineType);
/// \param latex_str a LaTeX command, "cite", "Citep*", etc
CitationStyle citationStyleFromString(std::string const & latex_str);
/// the other way round
@ -54,7 +51,7 @@ public:
/// constructor that sets the entryType
BibTeXInfo(docstring const & key, docstring const & type);
/// \return the short form of an authorlist
docstring const getAbbreviatedAuthor() const;
docstring const getAbbreviatedAuthor(bool jurabib_style = false) const;
///
docstring const getYear() const;
///
@ -63,6 +60,10 @@ public:
/// \param pointer to crossref information
docstring const & getInfo(BibTeXInfo const * const xref,
Buffer const & buf, bool richtext) const;
/// \return formatted BibTeX data for a citation label
docstring const getLabel(BibTeXInfo const * const xref,
Buffer const & buf, std::string const & format, bool richtext,
docstring before, docstring after, docstring dialog, bool next = false) const;
///
const_iterator find(docstring const & f) const { return bimap_.find(f); }
///
@ -84,6 +85,8 @@ public:
///
void label(docstring const & d) { label_= d; }
///
void key(docstring const & d) { bib_key_= d; }
///
docstring const & label() const { return label_; }
///
docstring const & key() const { return bib_key_; }
@ -106,7 +109,8 @@ private:
/// to get the data from xref BibTeXInfo object, which would normally
/// be the one referenced in the crossref field.
docstring getValueForKey(std::string const & key,
BibTeXInfo const * const xref = 0) const;
docstring const & before, docstring const & after, docstring const & dialog,
BibTeXInfo const * const xref = 0) const;
/// replace %keys% in a format string with their values
/// called from getInfo()
/// format strings may contain:
@ -122,8 +126,9 @@ private:
/// moreover, keys that look like "%_key%" are treated as translatable
/// so that things like "pp." and "vol." can be translated.
docstring expandFormat(std::string const & fmt,
BibTeXInfo const * const xref, int & counter,
Buffer const & buf, bool richtext) const;
BibTeXInfo const * const xref, int & counter,
Buffer const & buf, bool richtext, docstring before = docstring(),
docstring after = docstring(), docstring dialog = docstring(), bool next = false) const;
/// true if from BibTeX; false if from bibliography environment
bool is_bibtex_;
/// the BibTeX key for this entry
@ -177,38 +182,24 @@ public:
/// marked in the citation format and escape < and > elsewhere.
docstring const getInfo(docstring const & key, Buffer const & buf,
bool richtext = false) const;
/// \return formatted BibTeX data for citation labels.
/// Citation labels can have more than one key.
docstring const getLabel(std::vector<docstring> const & keys,
Buffer const & buf, std::string const & style, bool richtext = false,
docstring const & before = docstring(),
docstring const & after = docstring(),
docstring const & dialog = docstring()) const;
/// Is this a reference from a bibtex database
/// or from a bibliography environment?
bool isBibtex(docstring const & key) const;
/**
* "Translates" the available Citation Styles into strings for a given key,
* either numerical or author-year depending upon the active engine. (See
* below for those methods.)
*/
std::vector<docstring> const
getCiteStrings(docstring const & key, Buffer const & buf) const;
/**
* "Translates" the available Citation Styles into strings for a given key.
* The returned string is displayed by the GUI.
* [XX] is used in place of the actual reference
* Eg, the vector will contain: [XX], Jones et al. [XX], ...
* User supplies :
* the key,
* the buffer
*/
std::vector<docstring> const
getNumericalStrings(docstring const & key, Buffer const & buf) const;
/**
* "Translates" the available Citation Styles into strings for a given key.
* The returned string is displayed by the GUI.
* Eg, the vector will contain:
* Jones et al. (1990), (Jones et al. 1990), Jones et al. 1990, ...
* User supplies :
* the key,
* the buffer
*/
std::vector<docstring> const
getAuthorYearStrings(docstring const & key, Buffer const & buf) const;
/// Translates the available citation styles into strings for a given
/// list of keys, using either numerical or author-year style depending
/// upon the active engine.
std::vector<docstring> const getCiteStrings(std::vector<docstring> const & keys,
std::vector<CitationStyle> const & styles, Buffer const & buf, bool richtext = false,
docstring const & before = docstring(),
docstring const & after = docstring(),
docstring const & dialog = docstring()) const;
/// Collects the cited entries from buf.
void collectCitedEntries(Buffer const & buf);
/// A list of BibTeX keys cited in the current document, sorted by

View File

@ -259,25 +259,6 @@ PackageTranslator const & packagetranslator()
// Cite engine
typedef Translator<string, CiteEngine> CiteEngineTranslator;
CiteEngineTranslator const init_citeenginetranslator()
{
CiteEngineTranslator translator("basic", ENGINE_BASIC);
translator.addPair("natbib", ENGINE_NATBIB);
translator.addPair("jurabib", ENGINE_JURABIB);
return translator;
}
CiteEngineTranslator const & citeenginetranslator()
{
static CiteEngineTranslator translator = init_citeenginetranslator();
return translator;
}
typedef Translator<string, CiteEngineType> CiteEngineTypeTranslator;
@ -378,7 +359,7 @@ BufferParams::BufferParams()
papersize = PAPER_DEFAULT;
orientation = ORIENTATION_PORTRAIT;
use_geometry = false;
cite_engine_ = ENGINE_BASIC;
cite_engine_.push_back("basic");
cite_engine_type_ = ENGINE_TYPE_NUMERICAL;
biblio_style = "plain";
use_bibtopic = false;
@ -726,9 +707,9 @@ string BufferParams::readToken(Lexer & lex, string const & token,
lex >> use;
use_package(package, packagetranslator().find(use));
} else if (token == "\\cite_engine") {
string engine;
lex >> engine;
cite_engine_ = citeenginetranslator().find(engine);
lex.eatLine();
vector<string> engine = getVectorFromString(lex.getString());
setCiteEngine(engine);
} else if (token == "\\cite_engine_type") {
string engine_type;
lex >> engine_type;
@ -1037,8 +1018,22 @@ void BufferParams::writeFile(ostream & os) const
for (size_t i = 0; i < packages.size(); ++i)
os << "\n\\use_package " << packages[i] << ' '
<< use_package(packages[i]);
os << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
<< "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
os << "\n\\cite_engine ";
if (!cite_engine_.empty()) {
LayoutModuleList::const_iterator be = cite_engine_.begin();
LayoutModuleList::const_iterator en = cite_engine_.end();
for (LayoutModuleList::const_iterator it = be; it != en; ++it) {
if (it != be)
os << ',';
os << *it;
}
} else {
os << "basic";
}
os << "\n\\cite_engine_type " << citeenginetypetranslator().find(cite_engine_type_)
<< "\n\\biblio_style " << biblio_style
<< "\n\\use_bibtopic " << convert<string>(use_bibtopic)
<< "\n\\use_indices " << convert<string>(use_indices)
@ -2024,7 +2019,19 @@ void BufferParams::makeDocumentClass()
if (!baseClass())
return;
doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layout_modules_));
LayoutModuleList mods;
LayoutModuleList::iterator it;
LayoutModuleList::iterator en;
it = layout_modules_.begin();
en = layout_modules_.end();
for (; it != en; it++)
mods.push_back(*it);
it = cite_engine_.begin();
en = cite_engine_.end();
for (; it != en; it++)
mods.push_back(*it);
doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), mods));
if (!local_layout.empty()) {
TextClass::ReturnValues success =
@ -2039,7 +2046,8 @@ void BufferParams::makeDocumentClass()
bool BufferParams::moduleCanBeAdded(string const & modName) const
{
return layout_modules_.moduleCanBeAdded(modName, baseClass());
return cite_engine_.moduleCanBeAdded(modName, baseClass()) &&
layout_modules_.moduleCanBeAdded(modName, baseClass());
}
@ -2941,19 +2949,75 @@ Encoding const & BufferParams::encoding() const
}
CiteEngine BufferParams::citeEngine() const
bool BufferParams::addCiteEngine(string const & engine)
{
// FIXME the class should provide the numerical/
// authoryear choice
if (documentClass().provides("natbib"))
return ENGINE_NATBIB;
return cite_engine_;
LayoutModuleList::const_iterator it = cite_engine_.begin();
LayoutModuleList::const_iterator en = cite_engine_.end();
for (; it != en; ++it)
if (*it == engine)
return false;
cite_engine_.push_back(engine);
return true;
}
void BufferParams::setCiteEngine(CiteEngine cite_engine)
bool BufferParams::addCiteEngine(vector<string> const & engine)
{
cite_engine_ = cite_engine;
vector<string>::const_iterator it = engine.begin();
vector<string>::const_iterator en = engine.end();
bool ret = true;
for (; it != en; ++it)
if (!addCiteEngine(*it))
ret = false;
return ret;
}
string const & BufferParams::defaultBiblioStyle() const
{
return documentClass().defaultBiblioStyle();
}
bool const & BufferParams::fullAuthorList() const
{
return documentClass().fullAuthorList();
}
void BufferParams::setCiteEngine(string const & engine)
{
clearCiteEngine();
addCiteEngine(engine);
}
void BufferParams::setCiteEngine(vector<string> const & engine)
{
clearCiteEngine();
addCiteEngine(engine);
}
vector<string> BufferParams::citeCommands() const
{
static CitationStyle const default_style;
vector<string> commands =
documentClass().citeCommands(citeEngineType());
if (commands.empty())
commands.push_back(default_style.cmd);
return commands;
}
vector<CitationStyle> BufferParams::citeStyles() const
{
static CitationStyle const default_style;
vector<CitationStyle> styles =
documentClass().citeStyles(citeEngineType());
if (styles.empty())
styles.push_back(default_style);
return styles;
}
} // namespace lyx

View File

@ -404,20 +404,37 @@ public:
bool const & use_nonlatexfonts,
LaTeXFeatures & features) const;
/// get the appropriate cite engine (natbib handling)
CiteEngine citeEngine() const;
///
void setCiteEngine(CiteEngine const);
/// the cite engine modules
LayoutModuleList const & citeEngine() const
{ return cite_engine_; }
/// the type of cite engine (authoryear or numerical)
CiteEngineType const & citeEngineType() const
{ return cite_engine_type_; }
/// add the module to the cite engine modules
bool addCiteEngine(std::string const &);
/// add the modules to the cite engine modules
bool addCiteEngine(std::vector<std::string> const &);
/// clear the list of cite engine modules
void clearCiteEngine() { cite_engine_.clear(); }
/// set the cite engine module
void setCiteEngine(std::string const &);
/// set the cite engine modules
void setCiteEngine(std::vector<std::string> const &);
/// set the cite engine type
void setCiteEngineType(CiteEngineType const & engine_type)
{ cite_engine_type_ = engine_type; }
/// the available citation commands
std::vector<std::string> citeCommands() const;
/// the available citation styles
std::vector<CitationStyle> citeStyles() const;
/// the default BibTeX style file for the document
std::string biblio_style;
/// the default BibTeX style file from the TextClass
std::string const & defaultBiblioStyle() const;
/// whether the BibTeX style supports full author lists
bool const & fullAuthorList() const;
/// options for pdf output
PDFOptions & pdfoptions();
@ -477,8 +494,8 @@ private:
typedef std::map<std::string, OutputParams::FLAVOR> DefaultFlavorCache;
///
mutable DefaultFlavorCache default_flavors_;
/// for use with natbib
CiteEngine cite_engine_;
/// the cite engine modules
LayoutModuleList cite_engine_;
/// the type of cite engine (authoryear or numerical)
CiteEngineType cite_engine_type_;
///

View File

@ -12,46 +12,36 @@
#ifndef CITATION_H
#define CITATION_H
#include <string>
namespace lyx {
class Buffer;
enum CiteEngine {
ENGINE_BASIC,
ENGINE_NATBIB,
ENGINE_JURABIB
};
enum CiteEngineType {
ENGINE_TYPE_AUTHORYEAR = 1,
ENGINE_TYPE_NUMERICAL = 2,
};
enum CiteStyle {
CITE,
CITET,
CITEP,
CITEALT,
CITEALP,
CITEAUTHOR,
CITEYEAR,
CITEYEARPAR,
NOCITE
};
class CitationStyle
{
public:
///
CitationStyle() : style(CITE), full(false), forceUpperCase(false) {}
CitationStyle() : cmd("cite"), forceUpperCase(false), fullAuthorList(false),
textAfter(false), textBefore(false) {}
///
CiteStyle style;
///
bool full;
///
/// the LaTeX command
std::string cmd;
/// upper casing author prefixes (van -> Van)
bool forceUpperCase;
/// expanding the full author list
bool fullAuthorList;
/// supports text after the citation
bool textAfter;
/// supports text before the citation
bool textBefore;
};
} // namespace lyx

View File

@ -60,7 +60,7 @@ namespace lyx {
// development/updatelayouts.sh script, to update the format of
// all of our layout files.
//
int const LAYOUT_FORMAT = 36;
int const LAYOUT_FORMAT = 37; //jrioux : move citation engine stuff into layouts
namespace {
@ -147,8 +147,10 @@ TextClass::TextClass()
tocdepth_ = 3;
pagestyle_ = "default";
defaultfont_ = sane_font;
opt_enginetype_ = "authoryear|numerical";
opt_fontsize_ = "10|11|12";
opt_pagestyle_ = "empty|plain|headings|fancy";
cite_full_author_list_ = true;
titletype_ = TITLE_COMMAND_AFTER;
titlename_ = "maketitle";
loaded_ = false;
@ -210,7 +212,11 @@ enum TextClassTags {
TC_PROVIDESMODULE,
TC_EXCLUDESMODULE,
TC_HTMLTOCSECTION,
TC_CITEFORMAT
TC_CITEENGINE,
TC_CITEENGINETYPE,
TC_CITEFORMAT,
TC_DEFAULTBIBLIO,
TC_FULLAUTHORLIST,
};
@ -220,16 +226,20 @@ namespace {
{ "addtohtmlpreamble", TC_ADDTOHTMLPREAMBLE },
{ "addtohtmlstyles", TC_ADDTOHTMLSTYLES },
{ "addtopreamble", TC_ADDTOPREAMBLE },
{ "citeengine", TC_CITEENGINE },
{ "citeenginetype", TC_CITEENGINETYPE },
{ "citeformat", TC_CITEFORMAT },
{ "classoptions", TC_CLASSOPTIONS },
{ "columns", TC_COLUMNS },
{ "counter", TC_COUNTER },
{ "defaultbiblio", TC_DEFAULTBIBLIO },
{ "defaultfont", TC_DEFAULTFONT },
{ "defaultmodule", TC_DEFAULTMODULE },
{ "defaultstyle", TC_DEFAULTSTYLE },
{ "excludesmodule", TC_EXCLUDESMODULE },
{ "float", TC_FLOAT },
{ "format", TC_FORMAT },
{ "fullauthorlist", TC_FULLAUTHORLIST },
{ "htmlpreamble", TC_HTMLPREAMBLE },
{ "htmlstyles", TC_HTMLSTYLES },
{ "htmltocsection", TC_HTMLTOCSECTION },
@ -684,8 +694,27 @@ TextClass::ReturnValues TextClass::read(Lexer & lexrc, ReadType rt)
error = !readFloat(lexrc);
break;
case TC_CITEENGINE:
error = !readCiteEngine(lexrc);
break;
case TC_CITEENGINETYPE:
if (lexrc.next())
opt_enginetype_ = rtrim(lexrc.getString());
break;
case TC_CITEFORMAT:
readCiteFormat(lexrc);
error = !readCiteFormat(lexrc);
break;
case TC_DEFAULTBIBLIO:
if (lexrc.next())
cite_default_biblio_style_ = rtrim(lexrc.getString());
break;
case TC_FULLAUTHORLIST:
if (lexrc.next())
cite_full_author_list_ &= lexrc.getBool();
break;
case TC_NOCOUNTER:
@ -913,25 +942,109 @@ void TextClass::readClassOptions(Lexer & lexrc)
}
void TextClass::readCiteFormat(Lexer & lexrc)
bool TextClass::readCiteEngine(Lexer & lexrc)
{
int const type = readCiteEngineType(lexrc);
if (type & ENGINE_TYPE_AUTHORYEAR)
cite_styles_[ENGINE_TYPE_AUTHORYEAR].clear();
if (type & ENGINE_TYPE_NUMERICAL)
cite_styles_[ENGINE_TYPE_NUMERICAL].clear();
string def;
bool getout = false;
while (!getout && lexrc.isOK()) {
lexrc.eatLine();
def = lexrc.getString();
def = subst(def, " ", "");
def = subst(def, "\t", "");
if (compare_ascii_no_case(def, "end") == 0) {
getout = true;
continue;
}
string cmd;
CitationStyle cs;
char ichar = def[0];
if (ichar == '#')
continue;
if (ichar == 'C') {
cs.forceUpperCase = true;
def[0] = 'c';
}
size_t const n = def.size();
for (size_t i = 0; i != n; ++i) {
ichar = def[i];
if (ichar == '*')
cs.fullAuthorList = true;
else if (ichar == '[' && cs.textAfter)
cs.textBefore = true;
else if (ichar == '[')
cs.textAfter = true;
else if (ichar != ']')
cmd += ichar;
}
cs.cmd = cmd;
if (type & ENGINE_TYPE_AUTHORYEAR)
cite_styles_[ENGINE_TYPE_AUTHORYEAR].push_back(cs);
if (type & ENGINE_TYPE_NUMERICAL)
cite_styles_[ENGINE_TYPE_NUMERICAL].push_back(cs);
}
return getout;
}
int TextClass::readCiteEngineType(Lexer & lexrc) const
{
int const ENGINE_TYPE_DEFAULT =
ENGINE_TYPE_AUTHORYEAR | ENGINE_TYPE_NUMERICAL;
if (!lexrc.next()) {
lexrc.printError("No cite engine type given for token: `$$Token'.");
return ENGINE_TYPE_DEFAULT;
}
string const type = rtrim(lexrc.getString());
if (compare_ascii_no_case(type, "authoryear") == 0)
return ENGINE_TYPE_AUTHORYEAR;
else if (compare_ascii_no_case(type, "numerical") == 0)
return ENGINE_TYPE_NUMERICAL;
else if (compare_ascii_no_case(type, "default") != 0) {
string const s = "Unknown cite engine type `" + type
+ "' given for token: `$$Token',";
lexrc.printError(s);
}
return ENGINE_TYPE_DEFAULT;
}
bool TextClass::readCiteFormat(Lexer & lexrc)
{
int const type = readCiteEngineType(lexrc);
string etype;
string definition;
while (lexrc.isOK()) {
lexrc.next();
etype = lexrc.getString();
if (!lexrc.isOK() || compare_ascii_no_case(etype, "end") == 0)
if (compare_ascii_no_case(etype, "end") == 0)
break;
if (!lexrc.isOK())
return false;
lexrc.eatLine();
definition = lexrc.getString();
char initchar = etype[0];
if (initchar == '#')
continue;
if (initchar == '!' || initchar == '_')
cite_macros_[etype] = definition;
else
cite_formats_[etype] = definition;
if (initchar == '!' || initchar == '_') {
if (type & ENGINE_TYPE_AUTHORYEAR)
cite_macros_[ENGINE_TYPE_AUTHORYEAR][etype] = definition;
if (type & ENGINE_TYPE_NUMERICAL)
cite_macros_[ENGINE_TYPE_NUMERICAL][etype] = definition;
} else {
if (type & ENGINE_TYPE_AUTHORYEAR)
cite_formats_[ENGINE_TYPE_AUTHORYEAR][etype] = definition;
if (type & ENGINE_TYPE_NUMERICAL)
cite_formats_[ENGINE_TYPE_NUMERICAL][etype] = definition;
}
}
return true;
}
@ -1447,24 +1560,60 @@ Layout const & DocumentClass::htmlTOCLayout() const
}
string const & DocumentClass::getCiteFormat(string const & entry_type) const
string const & DocumentClass::getCiteFormat(CiteEngineType const & type,
string const & entry, string const & fallback) const
{
static string default_format = "{%author%[[%author%, ]][[{%editor%[[%editor%, ed., ]]}]]}\"%title%\"{%journal%[[, {!<i>!}%journal%{!</i>!}]][[{%publisher%[[, %publisher%]][[{%institution%[[, %institution%]]}]]}]]}{%year%[[ (%year%)]]}{%pages%[[, %pages%]]}.";
map<string, string>::const_iterator it = cite_formats_.find(entry_type);
if (it != cite_formats_.end())
return it->second;
return default_format;
map<CiteEngineType, map<string, string> >::const_iterator itype = cite_formats_.find(type);
if (itype == cite_formats_.end())
return default_format;
map<string, string>::const_iterator it = itype->second.find(entry);
if (it == itype->second.end() && !fallback.empty())
it = itype->second.find(fallback);
if (it == itype->second.end())
return default_format;
return it->second;
}
string const & DocumentClass::getCiteMacro(string const & macro) const
string const & DocumentClass::getCiteMacro(CiteEngineType const & type,
string const & macro) const
{
static string empty;
map<string, string>::const_iterator it = cite_macros_.find(macro);
if (it != cite_macros_.end())
return it->second;
return empty;
map<CiteEngineType, map<string, string> >::const_iterator itype = cite_macros_.find(type);
if (itype == cite_macros_.end())
return empty;
map<string, string>::const_iterator it = itype->second.find(macro);
if (it == itype->second.end())
return empty;
return it->second;
}
vector<string> const DocumentClass::citeCommands(
CiteEngineType const & type) const
{
vector<CitationStyle> const styles = citeStyles(type);
vector<CitationStyle>::const_iterator it = styles.begin();
vector<CitationStyle>::const_iterator end = styles.end();
vector<string> cmds;
for (; it != end; ++it) {
CitationStyle const cite = *it;
cmds.push_back(cite.cmd);
}
return cmds;
}
vector<CitationStyle> const & DocumentClass::citeStyles(
CiteEngineType const & type) const
{
static vector<CitationStyle> empty;
map<CiteEngineType, vector<CitationStyle> >::const_iterator it = cite_styles_.find(type);
if (it == cite_styles_.end())
return empty;
return it->second;
}

View File

@ -10,6 +10,7 @@
#ifndef TEXTCLASS_H
#define TEXTCLASS_H
#include "Citation.h"
#include "ColorCode.h"
#include "Counters.h"
#include "FloatList.h"
@ -245,6 +246,8 @@ protected:
bool tex_class_avail_;
/// document class prerequisites
mutable std::string prerequisites_;
/// The possible cite engine types
std::string opt_enginetype_;
///
std::string opt_fontsize_;
///
@ -311,9 +314,15 @@ protected:
/// The maximal TocLevel of sectioning layouts
int max_toclevel_;
/// Citation formatting information
std::map<std::string, std::string> cite_formats_;
std::map<CiteEngineType, std::map<std::string, std::string> > cite_formats_;
/// Citation macros
std::map<std::string, std::string> cite_macros_;
std::map<CiteEngineType, std::map<std::string, std::string> > cite_macros_;
/// The default BibTeX bibliography style file
std::string cite_default_biblio_style_;
/// Whether full author lists are supported
bool cite_full_author_list_;
/// The possible citation styles
std::map<CiteEngineType, std::vector<CitationStyle> > cite_styles_;
private:
///////////////////////////////////////////////////////////////////
// helper routines for reading layout files
@ -339,7 +348,11 @@ private:
///
bool readFloat(Lexer &);
///
void readCiteFormat(Lexer &);
bool readCiteEngine(Lexer &);
///
int readCiteEngineType(Lexer &) const;
///
bool readCiteFormat(Lexer &);
};
@ -390,6 +403,8 @@ public:
///
Counters & counters() const { return counters_; }
///
std::string const & opt_enginetype() const { return opt_enginetype_; }
///
std::string const & opt_fontsize() const { return opt_fontsize_; }
///
std::string const & opt_pagestyle() const { return opt_pagestyle_; }
@ -439,9 +454,19 @@ public:
/// returns true if the class has a ToC structure
bool hasTocLevels() const;
///
std::string const & getCiteFormat(std::string const & entry_type) const;
std::string const & getCiteFormat(CiteEngineType const & type,
std::string const & entry, std::string const & fallback = "") const;
///
std::string const & getCiteMacro(std::string const & macro) const;
std::string const & getCiteMacro(CiteEngineType const & type,
std::string const & macro) const;
///
std::vector<std::string> const citeCommands(CiteEngineType const &) const;
///
std::vector<CitationStyle> const & citeStyles(CiteEngineType const &) const;
///
std::string const & defaultBiblioStyle() const { return cite_default_biblio_style_; }
///
bool const & fullAuthorList() const { return cite_full_author_list_; }
protected:
/// Constructs a DocumentClass based upon a LayoutFile.
DocumentClass(LayoutFile const & tc);

View File

@ -504,19 +504,7 @@ QString GuiBibtex::styleFile() const
{
// the different bibtex packages have (and need) their
// own "plain" stylefiles
CiteEngine const engine = buffer().params().citeEngine();
QString defaultstyle;
switch (engine) {
case ENGINE_BASIC:
defaultstyle = "plain";
break;
case ENGINE_NATBIB:
defaultstyle = "plainnat";
break;
case ENGINE_JURABIB:
defaultstyle = "jurabib";
break;
}
QString defaultstyle = toqstr(buffer().params().defaultBiblioStyle());
QString bst = toqstr(params_["options"]);
if (bibtotoc()){

View File

@ -54,7 +54,8 @@ using namespace lyx::support;
namespace lyx {
namespace frontend {
static vector<CiteStyle> citeStyles_;
static vector<string> citeCmds_;
static vector<CitationStyle> citeStyles_;
template<typename String>
@ -96,9 +97,9 @@ GuiCitation::GuiCitation(GuiView & lv)
connect(forceuppercaseCB, SIGNAL(clicked()),
this, SLOT(changed()));
connect(textBeforeED, SIGNAL(textChanged(QString)),
this, SLOT(changed()));
this, SLOT(updateStyles()));
connect(textAfterED, SIGNAL(textChanged(QString)),
this, SLOT(changed()));
this, SLOT(updateStyles()));
connect(findLE, SIGNAL(returnPressed()),
this, SLOT(on_searchPB_clicked()));
connect(textBeforeED, SIGNAL(returnPressed()),
@ -191,84 +192,50 @@ void GuiCitation::updateControls()
// The main point of separating this out is that the fill*() methods
// called in update() do not need to be called for INTERNAL updates,
// such as when addPB is pressed, as the list of fields, entries, etc,
// will not have changed. At the moment, however, the division between
// fillStyles() and updateStyle() doesn't lend itself to dividing the
// two methods, though they should be divisible. That is, we should
// not have to call fillStyles() every time through here.
// will not have changed.
void GuiCitation::updateControls(BiblioInfo const & bi)
{
QModelIndex idx = selectionManager->getSelectedIndex();
updateInfo(bi, idx);
setButtons();
textBeforeED->setText(toqstr(params_["before"]));
textAfterED->setText(toqstr(params_["after"]));
fillStyles(bi);
updateStyle();
selectionManager->update();
}
void GuiCitation::updateFormatting(CiteStyle currentStyle)
void GuiCitation::updateFormatting(CitationStyle currentStyle)
{
CiteEngine const engine = citeEngine();
bool const natbib_engine = engine == ENGINE_NATBIB;
bool const basic_engine = engine == ENGINE_BASIC;
bool const force = currentStyle.forceUpperCase;
bool const full = currentStyle.fullAuthorList &&
documentBuffer().params().fullAuthorList();
bool const textbefore = currentStyle.textBefore;
bool const textafter = currentStyle.textAfter;
bool const haveSelection =
selectedLV->model()->rowCount() > 0;
bool const isNocite = currentStyle == NOCITE;
bool const isCiteyear =
currentStyle == CITEYEAR ||
currentStyle == CITEYEARPAR;
fulllistCB->setEnabled(natbib_engine && haveSelection && !isNocite
&& !isCiteyear);
forceuppercaseCB->setEnabled(natbib_engine && haveSelection
&& !isNocite && !isCiteyear);
textBeforeED->setEnabled(!basic_engine && haveSelection && !isNocite);
textBeforeLA->setEnabled(!basic_engine && haveSelection && !isNocite);
textAfterED->setEnabled(haveSelection && !isNocite);
textAfterLA->setEnabled(haveSelection && !isNocite);
forceuppercaseCB->setEnabled(force && haveSelection);
fulllistCB->setEnabled(full && haveSelection);
textBeforeED->setEnabled(textbefore && haveSelection);
textBeforeLA->setEnabled(textbefore && haveSelection);
textAfterED->setEnabled(textafter && haveSelection);
textAfterLA->setEnabled(textafter && haveSelection);
citationStyleCO->setEnabled(haveSelection);
citationStyleLA->setEnabled(haveSelection);
}
void GuiCitation::updateStyle()
// Update the styles for the style combo, citationStyleCO, and mark the
// settings as changed. Called upon changing the cited keys (including
// merely reordering the keys) or editing the text before/after fields.
void GuiCitation::updateStyles()
{
string const & command = params_.getCmdName();
// Find the style of the citekeys
vector<CiteStyle> const & styles = citeStyles_;
CitationStyle const cs = citationStyleFromString(command);
vector<CiteStyle>::const_iterator cit =
std::find(styles.begin(), styles.end(), cs.style);
if (cit != styles.end()) {
fulllistCB->setChecked(cs.full);
forceuppercaseCB->setChecked(cs.forceUpperCase);
} else {
// restore the last used natbib style
if (style_ >= 0 && style_ < citationStyleCO->count()) {
// the necessary update will be performed later
citationStyleCO->blockSignals(true);
citationStyleCO->setCurrentIndex(style_);
citationStyleCO->blockSignals(false);
}
fulllistCB->setChecked(false);
forceuppercaseCB->setChecked(false);
}
updateFormatting(cs.style);
BiblioInfo const & bi = bibInfo();
updateStyles(bi);
changed();
}
// This one needs to be called whenever citationStyleCO needs
// to be updated---and this would be on anything that changes the
// selection in selectedLV, or on a general update.
void GuiCitation::fillStyles(BiblioInfo const & bi)
// Update the styles for the style combo, citationStyleCO.
void GuiCitation::updateStyles(BiblioInfo const & bi)
{
QStringList selected_keys = selected_model_.stringList();
int curr = selectedLV->model()->rowCount() - 1;
@ -283,7 +250,7 @@ void GuiCitation::fillStyles(BiblioInfo const & bi)
if (!selectedLV->selectionModel()->selectedIndexes().empty())
curr = selectedLV->selectionModel()->selectedIndexes()[0].row();
QStringList sty = citationStyles(bi, curr);
QStringList sty = citationStyles(bi);
if (sty.isEmpty()) {
// some error
@ -347,7 +314,6 @@ bool GuiCitation::isSelected(QModelIndex const & idx)
void GuiCitation::setButtons()
{
selectionManager->update();
int const srows = selectedLV->model()->rowCount();
applyPB->setEnabled(srows > 0);
okPB->setEnabled(srows > 0);
@ -421,8 +387,9 @@ void GuiCitation::on_entriesCO_currentIndexChanged(int /*index*/)
void GuiCitation::on_citationStyleCO_currentIndexChanged(int index)
{
if (index >= 0 && index < citationStyleCO->count()) {
vector<CiteStyle> const & styles = citeStyles_;
vector<CitationStyle> const & styles = citeStyles_;
updateFormatting(styles[index]);
changed();
}
}
@ -479,19 +446,18 @@ void GuiCitation::apply(int const choice, bool full, bool force,
if (cited_keys_.isEmpty())
return;
vector<CiteStyle> const & styles = citeStyles_;
if (styles[choice] == NOCITE) {
full = false;
force = false;
before.clear();
after.clear();
}
vector<CitationStyle> const & styles = citeStyles_;
CitationStyle s;
s.style = styles[choice];
s.full = full;
s.forceUpperCase = force;
string const command = citationStyleToString(s);
CitationStyle cs = styles[choice];
if (!cs.textBefore)
before.clear();
if (!cs.textAfter)
after.clear();
cs.forceUpperCase &= force;
cs.fullAuthorList &= full;
string const command = citationStyleToString(cs);
params_.setCmdName(command);
params_["key"] = qstring_to_ucs4(cited_keys_.join(","));
@ -522,6 +488,23 @@ void GuiCitation::init()
else
cited_keys_ = str.split(",");
selected_model_.setStringList(cited_keys_);
// Initialize the drop downs
fillEntries(bi);
fillFields(bi);
// Initialize the citation formatting
string const & cmd = params_.getCmdName();
CitationStyle const cs = citationStyleFromString(cmd);
forceuppercaseCB->setChecked(cs.forceUpperCase);
fulllistCB->setChecked(cs.fullAuthorList &&
documentBuffer().params().fullAuthorList());
textBeforeED->setText(toqstr(params_["before"]));
textAfterED->setText(toqstr(params_["after"]));
// Update the interface
updateControls(bi);
updateStyles(bi);
if (selected_model_.rowCount()) {
selectedLV->blockSignals(true);
selectedLV->setFocus();
@ -530,25 +513,24 @@ void GuiCitation::init()
QItemSelectionModel::ClearAndSelect);
selectedLV->blockSignals(false);
// set the style combo appropriately
string const & command = params_.getCmdName();
vector<CiteStyle> const & styles = citeStyles_;
CitationStyle const cs = citationStyleFromString(command);
// Find the citation style
vector<string> const & cmds = citeCmds_;
vector<string>::const_iterator cit =
std::find(cmds.begin(), cmds.end(), cs.cmd);
int i = 0;
if (cit != cmds.end())
i = int(cit - cmds.begin());
vector<CiteStyle>::const_iterator cit =
std::find(styles.begin(), styles.end(), cs.style);
if (cit != styles.end()) {
int const i = int(cit - styles.begin());
// the necessary update will be performed later
citationStyleCO->blockSignals(true);
citationStyleCO->setCurrentIndex(i);
citationStyleCO->blockSignals(false);
}
// Set the style combo appropriately
citationStyleCO->blockSignals(true);
citationStyleCO->setCurrentIndex(i);
citationStyleCO->blockSignals(false);
updateFormatting(citeStyles_[i]);
} else
availableLV->setFocus();
fillFields(bi);
fillEntries(bi);
updateControls(bi);
applyPB->setEnabled(false);
okPB->setEnabled(false);
}
@ -605,25 +587,31 @@ void GuiCitation::findKey(BiblioInfo const & bi,
}
QStringList GuiCitation::citationStyles(BiblioInfo const & bi, int sel)
QStringList GuiCitation::citationStyles(BiblioInfo const & bi)
{
docstring const key = qstring_to_ucs4(cited_keys_[sel]);
return to_qstring_list(bi.getCiteStrings(key, documentBuffer()));
docstring const before = qstring_to_ucs4(textBeforeED->text());
docstring const after = qstring_to_ucs4(textAfterED->text());
vector<docstring> const keys = to_docstring_vector(cited_keys_);
vector<CitationStyle> styles = citeStyles_;
// FIXME: pass a dictionary instead of individual before, after, dialog, etc.
vector<docstring> ret = bi.getCiteStrings(keys, styles, documentBuffer(),
false, before, after, from_utf8("dialog"));
return to_qstring_list(ret);
}
void GuiCitation::setCitedKeys()
{
cited_keys_ = selected_model_.stringList();
updateStyles();
}
bool GuiCitation::initialiseParams(string const & data)
{
InsetCommand::string2params(data, params_);
CiteEngine const engine = citeEngine();
CiteEngineType const engine_type = citeEngineType();
citeStyles_ = citeStyles(engine, engine_type);
citeCmds_ = documentBuffer().params().citeCommands();
citeStyles_ = documentBuffer().params().citeStyles();
init();
return true;
}
@ -657,18 +645,6 @@ void GuiCitation::filterByEntryType(BiblioInfo const & bi,
}
CiteEngine GuiCitation::citeEngine() const
{
return documentBuffer().params().citeEngine();
}
CiteEngineType GuiCitation::citeEngineType() const
{
return documentBuffer().params().citeEngineType();
}
// Escape special chars.
// All characters are literals except: '.|*?+(){}[]^$\'
// These characters are literals when preceded by a "\", which is done here

View File

@ -57,8 +57,10 @@ private Q_SLOTS:
void on_regexCB_stateChanged(int);
void on_asTypeCB_stateChanged(int);
void changed();
///
/// set the citation keys, mark as changed
void setCitedKeys();
/// update the styles for the style combo, mark as changed
void updateStyles();
/// performs a limited update, suitable for internal call
void updateControls();
@ -93,16 +95,14 @@ private:
void updateInfo(BiblioInfo const & bi, QModelIndex const &);
/// enable/disable buttons
void setButtons();
/// fill the styles combo
void fillStyles(BiblioInfo const & bi);
/// fill the fields combo
void fillFields(BiblioInfo const & bi);
/// fill the entries combo
void fillEntries(BiblioInfo const & bi);
/// set the styles combo
void updateStyle();
void updateStyles(BiblioInfo const & bi);
/// set the formatting widgets
void updateFormatting(CiteStyle currentStyle);
void updateFormatting(CitationStyle currentStyle);
///
void updateControls(BiblioInfo const & bi);
///
@ -123,7 +123,7 @@ private:
);
/// List of example cite strings
QStringList citationStyles(BiblioInfo const & bi, int);
QStringList citationStyles(BiblioInfo const & bi);
/// Set the Params variable for the Controller.
void apply(int const choice, bool const full, bool const force,
@ -132,10 +132,6 @@ private:
///
void filterByEntryType(BiblioInfo const & bi,
std::vector<docstring> & keyVector, docstring entryType);
///
CiteEngine citeEngine() const;
///
CiteEngineType citeEngineType() const;
/// Search a given string within the passed keys.
/// \return the vector of matched keys.

View File

@ -202,6 +202,7 @@ char const * packages_gui[][4] =
};
vector<string> engine_types_;
vector<pair<string, QString> > pagestyles;
@ -2065,6 +2066,42 @@ void GuiDocument::setNumerical(bool numerical)
}
void GuiDocument::updateEngineType(string const & items, CiteEngineType const & sel)
{
engine_types_.clear();
int nn = 0;
for (int n = 0; !token(items, '|', n).empty(); ++n) {
nn += 1;
string style = token(items, '|', n);
engine_types_.push_back(style);
}
switch (sel) {
case ENGINE_TYPE_AUTHORYEAR:
biblioModule->citeStyleCO->setCurrentIndex(0);
break;
case ENGINE_TYPE_NUMERICAL:
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);
}
namespace {
// FIXME unicode
// both of these should take a vector<docstring>
@ -2297,12 +2334,12 @@ void GuiDocument::applyView()
bp_.use_refstyle = latexModule->refstyleCB->isChecked();
// biblio
bp_.setCiteEngine(ENGINE_BASIC);
if (biblioModule->citeNatbibRB->isChecked())
bp_.setCiteEngine(ENGINE_NATBIB);
bp_.setCiteEngine("natbib");
else if (biblioModule->citeJurabibRB->isChecked())
bp_.setCiteEngine(ENGINE_JURABIB);
bp_.setCiteEngine("jurabib");
else
bp_.setCiteEngine("basic");
if (biblioModule->citeStyleCO->currentIndex())
bp_.setCiteEngineType(ENGINE_TYPE_NUMERICAL);
@ -2707,17 +2744,22 @@ void GuiDocument::paramsToDialog()
latexModule->refstyleCB->setChecked(bp_.use_refstyle);
// biblio
string const cite_engine = bp_.citeEngine().list().front();
biblioModule->citeDefaultRB->setChecked(
bp_.citeEngine() == ENGINE_BASIC);
cite_engine == "basic");
biblioModule->citeJurabibRB->setChecked(
cite_engine == "jurabib");
biblioModule->citeNatbibRB->setChecked(
bp_.citeEngine() == ENGINE_NATBIB);
cite_engine == "natbib");
biblioModule->citeStyleCO->setCurrentIndex(
bp_.citeEngineType() == ENGINE_TYPE_NUMERICAL);
biblioModule->citeJurabibRB->setChecked(
bp_.citeEngine() == ENGINE_JURABIB);
updateEngineType(documentClass().opt_enginetype(),
bp_.citeEngineType());
biblioModule->bibtopicCB->setChecked(
bp_.use_bibtopic);

View File

@ -75,6 +75,7 @@ public:
void updateFontsize(std::string const &, std::string const &);
void updateFontlist();
void updateDefaultFormat();
void updateEngineType(std::string const &, CiteEngineType const &);
void updatePagestyle(std::string const &, std::string const &);
bool isChildIncluded(std::string const &);

View File

@ -1485,24 +1485,38 @@ void MenuDefinition::expandCiteStyles(BufferView const * bv)
static_cast<InsetCommand const *>(inset);
Buffer const * buf = &bv->buffer();
docstring key = citinset->getParam("key");
// we can only handle one key currently
if (contains(key, ','))
key = qstring_to_ucs4(toqstr(key).split(',')[0]);
string const cmd = citinset->params().getCmdName();
vector<CiteStyle> citeStyleList = citeStyles(buf->params().citeEngine(),
buf->params().citeEngineType());
docstring_list citeStrings =
buf->masterBibInfo().getCiteStrings(key, bv->buffer());
docstring const & key = citinset->getParam("key");
if (key.empty()) {
add(MenuItem(MenuItem::Command,
qt_("No citations selected!"),
FuncRequest(LFUN_NOACTION)));
return;
}
docstring_list::const_iterator cit = citeStrings.begin();
docstring_list::const_iterator end = citeStrings.end();
docstring const & before = citinset->getParam("before");
docstring const & after = citinset->getParam("after");
size_t const n = cmd.size();
bool const force = cmd[0] == 'C';
bool const full = cmd[n] == '*';
vector<docstring> const keys = getVectorFromString(key);
vector<CitationStyle> const citeStyleList = buf->params().citeStyles();
vector<docstring> citeStrings =
buf->masterBibInfo().getCiteStrings(keys, citeStyleList, bv->buffer(),
false, before, after, from_utf8("dialog"));
vector<docstring>::const_iterator cit = citeStrings.begin();
vector<docstring>::const_iterator end = citeStrings.end();
for (int ii = 1; cit != end; ++cit, ++ii) {
docstring label = *cit;
CitationStyle cs;
CiteStyle cst = citeStyleList[ii - 1];
cs.style = cst;
CitationStyle cs = citeStyleList[ii - 1];
cs.forceUpperCase &= force;
cs.fullAuthorList &= full;
addWithStatusCheck(MenuItem(MenuItem::Command, toqstr(label),
FuncRequest(LFUN_INSET_MODIFY,
"changetype " + from_utf8(citationStyleToString(cs)))));

View File

@ -314,8 +314,10 @@ docstring bibitemWidest(Buffer const & buffer, OutputParams const & runparams)
void InsetBibitem::collectBibKeys(InsetIterator const & it) const
{
docstring const key = getParam("key");
docstring const label = getParam("label");
BibTeXInfo keyvalmap(false);
keyvalmap.label(bibLabel());
keyvalmap.key(key);
keyvalmap.label(label);
DocIterator doc_it(it);
doc_it.forwardPos();
keyvalmap[from_ascii("ref")] = doc_it.paragraph().asString(

View File

@ -93,6 +93,8 @@ vector<string> const & possibleCiteCommands()
} // anon namespace
// FIXME: use the citeCommands provided by the TextClass
// instead of possibleCiteCommands defined in this file.
bool InsetCitation::isCompatibleCommand(string const & cmd)
{
vector<string> const & possibles = possibleCiteCommands();
@ -142,71 +144,36 @@ docstring InsetCitation::toolTip(BufferView const & bv, int, int) const
namespace {
// FIXME See the header for the issue.
string defaultCiteCommand(CiteEngine engine, CiteEngineType engine_type)
{
string str;
switch (engine) {
case ENGINE_BASIC:
str = "cite";
break;
case ENGINE_NATBIB:
if (engine_type == ENGINE_TYPE_AUTHORYEAR)
str = "citet";
else
str = "citep";
break;
case ENGINE_JURABIB:
str = "cite";
break;
}
return str;
}
string asValidLatexCommand(string const & input, CiteEngine const engine,
CiteEngineType const engine_type)
CitationStyle asValidLatexCommand(string const & input, vector<CitationStyle> const valid_styles)
{
string const default_str = defaultCiteCommand(engine, engine_type);
CitationStyle cs = valid_styles[0];
cs.forceUpperCase = false;
cs.fullAuthorList = false;
if (!InsetCitation::isCompatibleCommand(input))
return default_str;
return cs;
string output;
switch (engine) {
case ENGINE_BASIC:
if (input == "nocite")
output = input;
else
output = default_str;
break;
case ENGINE_NATBIB:
if (input == "cite" || input == "citefield"
|| input == "citetitle" || input == "cite*")
output = default_str;
else if (prefixIs(input, "foot"))
output = input.substr(4);
else
output = input;
break;
case ENGINE_JURABIB: {
// Jurabib does not support the 'uppercase' natbib style.
if (input[0] == 'C')
output = string(1, 'c') + input.substr(1);
else
output = input;
// Jurabib does not support the 'full' natbib style.
string::size_type const n = output.size() - 1;
if (output != "cite*" && output[n] == '*')
output = output.substr(0, n);
string normalized_input = input;
string::size_type const n = input.size() - 1;
if (input[0] == 'C')
normalized_input[0] = 'c';
if (input[n] == '*')
normalized_input = normalized_input.substr(0, n);
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) {
cs = *it;
break;
}
}
return output;
cs.forceUpperCase &= input[0] == 'C';
cs.fullAuthorList &= input[n] == '*';
return cs;
}
@ -247,21 +214,12 @@ docstring InsetCitation::complexLabel(bool for_xhtml) const
if (biblist.empty())
return docstring();
// the natbib citation-styles
// CITET: author (year)
// CITEP: (author,year)
// CITEALT: author year
// CITEALP: author, year
// CITEAUTHOR: author
// CITEYEAR: year
// CITEYEARPAR: (year)
// jurabib supports these plus
// CITE: author/<before field>
docstring const & key = getParam("key");
if (key.empty())
return _("No citations selected!");
CiteEngine const engine = buffer().params().citeEngine();
CiteEngineType const engine_type = buffer().params().citeEngineType();
// We don't currently use the full or forceUCase fields.
string cite_type = asValidLatexCommand(getCmdName(), engine, engine_type);
string cite_type = getCmdName();
if (cite_type[0] == 'C')
// If we were going to use them, this would mean ForceUCase
cite_type = string(1, 'c') + cite_type.substr(1);
@ -270,172 +228,16 @@ docstring InsetCitation::complexLabel(bool for_xhtml) const
cite_type = cite_type.substr(0, cite_type.size() - 1);
docstring const & before = getParam("before");
docstring before_str;
if (!before.empty()) {
// In CITET and CITEALT mode, the "before" string is
// attached to the label associated with each and every key.
// In CITEP, CITEALP and CITEYEARPAR mode, it is attached
// to the front of the whole only.
// In other modes, it is not used at all.
if (cite_type == "citet" ||
cite_type == "citealt" ||
cite_type == "citep" ||
cite_type == "citealp" ||
cite_type == "citeyearpar")
before_str = before + ' ';
// In CITE (jurabib), the "before" string is used to attach
// the annotator (of legal texts) to the author(s) of the
// first reference.
else if (cite_type == "cite")
before_str = '/' + before;
}
docstring const & after = getParam("after");
docstring after_str;
// The "after" key is appended only to the end of the whole.
if (cite_type == "nocite")
after_str = " (" + _("not cited") + ')';
else if (!after.empty()) {
after_str = ", " + after;
}
// One day, these might be tunable (as they are in BibTeX).
char op, cp; // opening and closing parenthesis.
const char * sep; // punctuation mark separating citation entries.
if (engine == ENGINE_BASIC) {
op = '[';
cp = ']';
sep = ",";
} else {
op = '(';
cp = ')';
sep = ";";
}
docstring const op_str = ' ' + docstring(1, op);
docstring const cp_str = docstring(1, cp) + ' ';
docstring const sep_str = from_ascii(sep) + ' ';
// FIXME: allow to add cite macros
/*
buffer().params().documentClass().addCiteMacro("!textbefore", to_utf8(before));
buffer().params().documentClass().addCiteMacro("!textafter", to_utf8(after));
*/
docstring label;
vector<docstring> keys = getVectorFromString(getParam("key"));
vector<docstring>::const_iterator it = keys.begin();
vector<docstring>::const_iterator end = keys.end();
for (; it != end; ++it) {
// get the bibdata corresponding to the key
docstring const author = biblist.getAbbreviatedAuthor(*it);
docstring const year = biblist.getYear(*it, for_xhtml);
docstring const citenum = for_xhtml ? biblist.getCiteNumber(*it) : *it;
if (author.empty() || year.empty())
// We can't construct a "complex" label without that info.
// So fail safely.
return docstring();
// authors1/<before>; ... ;
// authors_last, <after>
if (cite_type == "cite") {
if (engine == ENGINE_BASIC) {
label += wrapCitation(*it, citenum, for_xhtml) + sep_str;
} else if (engine == ENGINE_JURABIB) {
if (it == keys.begin())
label += wrapCitation(*it, author, for_xhtml) + before_str + sep_str;
else
label += wrapCitation(*it, author, for_xhtml) + sep_str;
}
}
// nocite
else if (cite_type == "nocite") {
label += *it + sep_str;
}
// (authors1 (<before> year); ... ;
// authors_last (<before> year, <after>)
else if (cite_type == "citet") {
switch (engine) {
case ENGINE_NATBIB:
if (engine_type == ENGINE_TYPE_AUTHORYEAR)
label += author + op_str + before_str +
wrapCitation(*it, year, for_xhtml) + cp + sep_str;
else
label += author + op_str + before_str +
wrapCitation(*it, citenum, for_xhtml) + cp + sep_str;
break;
case ENGINE_JURABIB:
label += before_str + author + op_str +
wrapCitation(*it, year, for_xhtml) + cp + sep_str;
break;
case ENGINE_BASIC:
break;
}
}
// author, year; author, year; ...
else if (cite_type == "citep" ||
cite_type == "citealp") {
if (engine_type == ENGINE_TYPE_NUMERICAL) {
label += wrapCitation(*it, citenum, for_xhtml) + sep_str;
} else {
label += wrapCitation(*it, author + ", " + year, for_xhtml) + sep_str;
}
}
// (authors1 <before> year;
// authors_last <before> year, <after>)
else if (cite_type == "citealt") {
switch (engine) {
case ENGINE_NATBIB:
if (engine_type == ENGINE_TYPE_AUTHORYEAR)
label += author + ' ' + before_str +
wrapCitation(*it, year, for_xhtml) + sep_str;
else
label += author + ' ' + before_str + '#' +
wrapCitation(*it, citenum, for_xhtml) + sep_str;
break;
case ENGINE_JURABIB:
label += before_str +
wrapCitation(*it, author + ' ' + year, for_xhtml) + sep_str;
break;
case ENGINE_BASIC:
break;
}
}
// author; author; ...
else if (cite_type == "citeauthor") {
label += wrapCitation(*it, author, for_xhtml) + sep_str;
}
// year; year; ...
else if (cite_type == "citeyear" ||
cite_type == "citeyearpar") {
label += wrapCitation(*it, year, for_xhtml) + sep_str;
}
}
label = rtrim(rtrim(label), sep);
if (!after_str.empty()) {
if (cite_type == "citet") {
// insert "after" before last ')'
label.insert(label.size() - 1, after_str);
} else {
bool const add =
!(engine == ENGINE_NATBIB &&
engine_type == ENGINE_TYPE_NUMERICAL &&
(cite_type == "citeauthor" ||
cite_type == "citeyear"));
if (add)
label += after_str;
}
}
if (!before_str.empty() && (cite_type == "citep" ||
cite_type == "citealp" ||
cite_type == "citeyearpar")) {
label = before_str + label;
}
if (cite_type == "citep" || cite_type == "citeyearpar" ||
(cite_type == "cite" && engine == ENGINE_BASIC) )
label = op + label + cp;
vector<docstring> const keys = getVectorFromString(key);
label = biblist.getLabel(keys, buffer(), cite_type, for_xhtml, before, after);
return label;
}
@ -565,15 +367,15 @@ void InsetCitation::forToc(docstring & os, size_t) const
// Have to overwrite the default InsetCommand method in order to check that
// the \cite command is valid. Eg, the user has natbib enabled, inputs some
// citations and then changes his mind, turning natbib support off. The output
// should revert to \cite[]{}
// should revert to the default citation command as provided by the citation
// engine, e.g. \cite[]{} for the basic engine.
void InsetCitation::latex(otexstream & os, OutputParams const & runparams) const
{
CiteEngine cite_engine = buffer().params().citeEngine();
CiteEngineType cite_engine_type = buffer().params().citeEngineType();
vector<CitationStyle> citation_styles = buffer().params().citeStyles();
CitationStyle cs = asValidLatexCommand(getCmdName(), citation_styles);
BiblioInfo const & bi = buffer().masterBibInfo();
// FIXME UNICODE
docstring const cite_str = from_utf8(
asValidLatexCommand(getCmdName(), cite_engine, cite_engine_type));
docstring const cite_str = from_utf8(citationStyleToString(cs));
if (runparams.inulemcmd)
os << "\\mbox{";
@ -582,9 +384,9 @@ void InsetCitation::latex(otexstream & os, OutputParams const & runparams) const
docstring const & before = getParam("before");
docstring const & after = getParam("after");
if (!before.empty() && cite_engine != ENGINE_BASIC)
if (!before.empty() && cs.textBefore)
os << '[' << before << "][" << after << ']';
else if (!after.empty())
else if (!after.empty() && cs.textAfter)
os << '[' << after << ']';
if (!bi.isBibtex(getParam("key")))
@ -598,21 +400,6 @@ void InsetCitation::latex(otexstream & os, OutputParams const & runparams) const
}
void InsetCitation::validate(LaTeXFeatures & features) const
{
switch (features.bufferParams().citeEngine()) {
case ENGINE_BASIC:
break;
case ENGINE_NATBIB:
features.require("natbib");
break;
case ENGINE_JURABIB:
features.require("jurabib");
break;
}
}
string InsetCitation::contextMenuName() const
{
return "context-citation";

View File

@ -57,7 +57,7 @@ public:
///
void forToc(docstring &, size_t) const;
///
void validate(LaTeXFeatures &) const;
void validate(LaTeXFeatures &) const {}
///
void updateBuffer(ParIterator const & it, UpdateType);
///
@ -70,10 +70,7 @@ public:
//@{
///
static ParamInfo const & findInfo(std::string const &);
// FIXME This is the locus of the design problem we have.
// It really ought to do what default_cite_command() does,
// but to do that it needs to know what CiteEngine we are
// using.
///
static std::string defaultCommand() { return "cite"; }
///
static bool isCompatibleCommand(std::string const & cmd);