Read the citation formats from a file, rather than hardcoding them. This

allows for layout- or module-level customization of the display in the
citation dialog and of the XHTML bibliography output.

There is more of this to come, by the way. The next step is to allow
macros. That will make it easier to deal with translation issues, which
ought to be the final step.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@33920 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Richard Heck 2010-03-29 18:37:25 +00:00
parent 63844ddbf9
commit f1912e1c33
12 changed files with 83 additions and 62 deletions

View File

@ -1127,6 +1127,7 @@ dist_layouts_DATA =\
layouts/singlecol-new.layout \ layouts/singlecol-new.layout \
layouts/slides.layout \ layouts/slides.layout \
layouts/spie.layout \ layouts/spie.layout \
layouts/stdciteformats.inc \
layouts/stdclass.inc \ layouts/stdclass.inc \
layouts/stdcharstyles.inc \ layouts/stdcharstyles.inc \
layouts/stdcounters.inc \ layouts/stdcounters.inc \

View File

@ -36,4 +36,3 @@ Style Part*
Size Larger Size Larger
EndFont EndFont
End End

View File

@ -0,0 +1,15 @@
# Standard formats for citations.
#
# Author: Richard Heck <rgheck@comcast.net>
Format 26
CiteFormat
article %author%, "%title%", {!<i>!}%journal%{!</i>!} {%volume%[[ %volume%{%number%[[, %number%]]}]]} (%year%){%pages%[[, pp. %pages%]]}.{%note%[[ %note%]]}
book {%author%[[%author%, ]][[{%editor%[[%editor%, %ed_text%, ]]}]]}{!<i>!}%title%{!</i>!}{%volume%[[ vol. %volume%]][[{%number%[[no. %number%]]}]]}{%edition%[[%edition%]]} ({%address%[[%address%: ]]}%publisher%, %year%).{%note%[[ %note%]]}
incollection %author%, \"%title%\", in{%editor%[[ %editor%, %ed_text%,]]} {!<i>!}%booktitle%{!</i>!}{%volume%[[ vol. %volume%]][[{%number%[[no. %number%]]}]]}{%edition%[[%edition%]]} ({%address%[[%address%: ]]}%publisher%, %year%){%pages%[[, pp. %pages%]]}.{%note%[[ %note%]]}
thesis %author%, %title% ({%address%[[%address%: ]]}%school%, %year%).{%note%[[ %note%]]}
End

View File

@ -55,3 +55,4 @@ Input stdtitle.inc
Input stdstruct.inc Input stdstruct.inc
Input lyxmacros.inc Input lyxmacros.inc
Input stdlayouts.inc Input stdlayouts.inc
Input stdciteformats.inc

View File

@ -91,6 +91,9 @@ import os, re, string, sys
# Incremented to format 25, 12 March 2010 by rgh # Incremented to format 25, 12 March 2010 by rgh
# Added RefPrefix tag for layouts and floats. # Added RefPrefix tag for layouts and floats.
# Incremented to format 26, 29 March 2010 by rgh
# Added CiteFormat.
# Do not forget to document format change in Customization # Do not forget to document format change in Customization
# Manual (section "Declaring a new text class"). # Manual (section "Declaring a new text class").
@ -98,7 +101,7 @@ import os, re, string, sys
# development/tools/updatelayouts.sh script to update all # development/tools/updatelayouts.sh script to update all
# layout files to the new format. # layout files to the new format.
currentFormat = 25 currentFormat = 26
def usage(prog_name): def usage(prog_name):
@ -271,7 +274,7 @@ def convert(lines):
continue continue
# Only new features # Only new features
if format == 24: if format >= 24 and format <= 25:
i += 1 i += 1
continue continue

View File

@ -19,6 +19,7 @@
#include "Encoding.h" #include "Encoding.h"
#include "InsetIterator.h" #include "InsetIterator.h"
#include "Paragraph.h" #include "Paragraph.h"
#include "TextClass.h"
#include "TocBackend.h" #include "TocBackend.h"
#include "insets/Inset.h" #include "insets/Inset.h"
@ -195,12 +196,6 @@ docstring convertLaTeXCommands(docstring const & str)
return ret; return ret;
} }
// these are used in the expandFormat() routine, etc.
static string const pp_text = N_("pp.");
static string const ed_text = N_("ed.");
static string const edby_text = N_("ed. by");
} // anon namespace } // anon namespace
@ -418,16 +413,8 @@ docstring BibTeXInfo::expandFormat(string const & format,
// end of key // end of key
scanning_key = false; scanning_key = false;
// so we replace the key with its value, which may be empty // so we replace the key with its value, which may be empty
if (key == "pp_text") docstring const val = getValueForKey(key, xref);
ret += _(pp_text); ret += val;
else if (key == "ed_text")
ret += _(ed_text);
else if(key == "edby_text")
ret += _(edby_text);
else {
docstring const val = getValueForKey(key, xref);
ret += val;
}
key.clear(); key.clear();
} else { } else {
// beginning of key // beginning of key
@ -496,25 +483,8 @@ docstring BibTeXInfo::expandFormat(string const & format,
} }
namespace {
// FIXME These would be better read from a file, so that they
// could be customized.
static string articleFormat = "%author%, \"%title%\", {!<i>!}%journal%{!</i>!} {%volume%[[ %volume%{%number%[[, %number%]]}]]} (%year%){%pages%[[, %pp_text% %pages%]]}.{%note%[[ %note%]]}";
static string bookFormat = "{%author%[[%author%]][[%editor%, %ed_text%]]}, {!<i>!}%title%{!</i>!}{%volume%[[ vol. %volume%]][[{%number%[[no. %number%]]}]]}{%edition%[[%edition%]]} ({%address%[[%address%: ]]}%publisher%, %year%).{%note%[[ %note%]]}";
static string inSomething = "%author%, \"%title%\", in{%editor%[[ %editor%, %ed_text%,]]} {!<i>!}%booktitle%{!</i>!}{%volume%[[ vol. %volume%]][[{%number%[[no. %number%]]}]]}{%edition%[[%edition%]]} ({%address%[[%address%: ]]}%publisher%, %year%){%pages%[[, %pp_text% %pages%]]}.{%note%[[ %note%]]}";
static string thesis = "%author%, %title% ({%address%[[%address%: ]]}%school%, %year%).{%note%[[ %note%]]}";
static string defaultFormat = "{%author%[[%author%, ]][[{%editor%[[%editor%, %ed_text%, ]]}]]}\"%title%\"{%journal%[[, {!<i>!}%journal%{!</i>!}]][[{%publisher%[[, %publisher%]][[{%institution%[[, %institution%]]}]]}]]}{%year%[[ (%year%)]]}{%pages%[[, %pages%]]}.";
}
docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref, docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref,
bool richtext) const Buffer const & buf, bool richtext) const
{ {
if (!info_.empty()) if (!info_.empty())
return info_; return info_;
@ -525,16 +495,9 @@ docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref,
return info_; return info_;
} }
if (entry_type_ == "article") DocumentClass const & dc = buf.params().documentClass();
info_ = expandFormat(articleFormat, xref, richtext); string const & format = dc.getCiteFormat(to_utf8(entry_type_));
else if (entry_type_ == "book") info_ = expandFormat(format, xref, richtext);
info_ = expandFormat(bookFormat, xref, richtext);
else if (entry_type_.substr(0,2) == "in")
info_ = expandFormat(inSomething, xref, richtext);
else if (entry_type_ == "phdthesis" || entry_type_ == "mastersthesis")
info_ = expandFormat(thesis, xref, richtext);
else
info_ = expandFormat(defaultFormat, xref, richtext);
if (!info_.empty()) if (!info_.empty())
info_ = convertLaTeXCommands(info_); info_ = convertLaTeXCommands(info_);
@ -665,7 +628,8 @@ docstring const BiblioInfo::getYear(docstring const & key, bool use_modifier) co
} }
docstring const BiblioInfo::getInfo(docstring const & key, bool richtext) const docstring const BiblioInfo::getInfo(docstring const & key,
Buffer const & buf, bool richtext) const
{ {
BiblioInfo::const_iterator it = find(key); BiblioInfo::const_iterator it = find(key);
if (it == end()) if (it == end())
@ -678,7 +642,7 @@ docstring const BiblioInfo::getInfo(docstring const & key, bool richtext) const
if (xrefit != end()) if (xrefit != end())
xrefptr = &(xrefit->second); xrefptr = &(xrefit->second);
} }
return data.getInfo(xrefptr, richtext); return data.getInfo(xrefptr, buf, richtext);
} }

View File

@ -62,7 +62,7 @@ public:
/// \return formatted BibTeX data suitable for framing. /// \return formatted BibTeX data suitable for framing.
/// \param pointer to crossref information /// \param pointer to crossref information
docstring const & getInfo(BibTeXInfo const * const xref, docstring const & getInfo(BibTeXInfo const * const xref,
bool richtext) const; Buffer const & buf, bool richtext) const;
/// ///
const_iterator find(docstring const & f) const { return bimap_.find(f); } const_iterator find(docstring const & f) const { return bimap_.find(f); }
/// ///
@ -168,7 +168,7 @@ public:
/// \return formatted BibTeX data associated with a given key. /// \return formatted BibTeX data associated with a given key.
/// Empty if no info exists. /// Empty if no info exists.
/// Note that this will retrieve data from the crossref as needed. /// Note that this will retrieve data from the crossref as needed.
docstring const getInfo(docstring const & key, docstring const getInfo(docstring const & key, Buffer const & buf,
bool richtext = false) const; bool richtext = false) const;
/// Is this a reference from a bibtex database /// Is this a reference from a bibtex database
/// or from a bibliography environment? /// or from a bibliography environment?

View File

@ -66,7 +66,7 @@ private:
}; };
// Keep the changes documented in the Customization manual. // Keep the changes documented in the Customization manual.
int const FORMAT = 25; int const FORMAT = 26;
bool layout2layout(FileName const & filename, FileName const & tempfile) bool layout2layout(FileName const & filename, FileName const & tempfile)
@ -197,7 +197,8 @@ enum TextClassTags {
TC_DEFAULTMODULE, TC_DEFAULTMODULE,
TC_PROVIDESMODULE, TC_PROVIDESMODULE,
TC_EXCLUDESMODULE, TC_EXCLUDESMODULE,
TC_HTMLTOCSECTION TC_HTMLTOCSECTION,
TC_CITEFORMAT
}; };
@ -206,6 +207,7 @@ namespace {
LexerKeyword textClassTags[] = { LexerKeyword textClassTags[] = {
{ "addtohtmlpreamble", TC_ADDTOHTMLPREAMBLE }, { "addtohtmlpreamble", TC_ADDTOHTMLPREAMBLE },
{ "addtopreamble", TC_ADDTOPREAMBLE }, { "addtopreamble", TC_ADDTOPREAMBLE },
{ "citeformat", TC_CITEFORMAT },
{ "classoptions", TC_CLASSOPTIONS }, { "classoptions", TC_CLASSOPTIONS },
{ "columns", TC_COLUMNS }, { "columns", TC_COLUMNS },
{ "counter", TC_COUNTER }, { "counter", TC_COUNTER },
@ -634,6 +636,10 @@ TextClass::ReturnValues TextClass::read(Lexer & lexrc, ReadType rt)
case TC_FLOAT: case TC_FLOAT:
readFloat(lexrc); readFloat(lexrc);
break; break;
case TC_CITEFORMAT:
readCiteFormat(lexrc);
break;
case TC_IFCOUNTER: case TC_IFCOUNTER:
ifcounter = true; ifcounter = true;
@ -846,6 +852,22 @@ void TextClass::readClassOptions(Lexer & lexrc)
} }
void TextClass::readCiteFormat(Lexer & lexrc)
{
string etype;
string definition;
while (lexrc.isOK()) {
lexrc.next();
etype = lexrc.getString();
if (!lexrc.isOK() || compare_ascii_no_case(etype, "end") == 0)
break;
lexrc.eatLine();
definition = lexrc.getString();
cite_formats_[etype] = definition;
}
}
void TextClass::readFloat(Lexer & lexrc) void TextClass::readFloat(Lexer & lexrc)
{ {
enum { enum {
@ -1328,6 +1350,17 @@ Layout const & DocumentClass::htmlTOCLayout() const
} }
string const & DocumentClass::getCiteFormat(string const & entry_type) const
{
static string default_format = "{%author%[[%author%, ]][[{%editor%[[%editor%, %ed_text%, ]]}]]}\"%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;
}
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// PageSides // PageSides

View File

@ -25,10 +25,11 @@
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <list>
#include <map> #include <map>
#include <set> #include <set>
#include <string>
#include <vector> #include <vector>
#include <list>
namespace lyx { namespace lyx {
@ -81,22 +82,20 @@ public:
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
// typedefs // typedefs
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
/// The individual paragraph layouts comprising the document class
// NOTE Do NOT try to make this a container of Layout pointers, e.g., // NOTE Do NOT try to make this a container of Layout pointers, e.g.,
// std::vector<Layout *>. This will lead to problems. The reason is // std::list<Layout *>. This will lead to problems. The reason is
// that DocumentClass objects are generally created by copying a // that DocumentClass objects are generally created by copying a
// LayoutFile, which serves as a base for the DocumentClass. If the // LayoutFile, which serves as a base for the DocumentClass. If the
// LayoutList is a container of pointers, then every DocumentClass // LayoutList is a container of pointers, then every DocumentClass
// that derives from a given LayoutFile (e.g., article) will SHARE // that derives from a given LayoutFile (e.g., article) will SHARE
// a basic set of layouts. So if one Buffer were to modify a layout // a basic set of layouts. So if one Buffer were to modify a layout
// (say, Standard), that would modify that layout for EVERY Buffer // (say, Standard), that would modify that layout for EVERY Buffer
// that was based upon the same DocumentClass. (Of course, if you // that was based upon the same DocumentClass.
// really, REALLY want to make LayoutList a vector<Layout *>, then
// you can implement custom assignment and copy constructors.)
// //
// NOTE: Layout pointers are directly assigned to paragraphs so a // NOTE: Layout pointers are directly assigned to paragraphs so a
// container that does not invalidate these pointers after insertion // container that does not invalidate these pointers after insertion
// is needed. // is needed.
/// The individual paragraph layouts comprising the document class
typedef std::list<Layout> LayoutList; typedef std::list<Layout> LayoutList;
/// The inset layouts available to this class /// The inset layouts available to this class
typedef std::map<docstring, InsetLayout> InsetLayouts; typedef std::map<docstring, InsetLayout> InsetLayouts;
@ -305,6 +304,8 @@ protected:
int min_toclevel_; int min_toclevel_;
/// The maximal TocLevel of sectioning layouts /// The maximal TocLevel of sectioning layouts
int max_toclevel_; int max_toclevel_;
/// Citation formatting information
std::map<std::string, std::string> cite_formats_;
private: private:
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
// helper routines for reading layout files // helper routines for reading layout files
@ -329,6 +330,8 @@ private:
void readCharStyle(Lexer &, std::string const &); void readCharStyle(Lexer &, std::string const &);
/// ///
void readFloat(Lexer &); void readFloat(Lexer &);
///
void readCiteFormat(Lexer &);
}; };
@ -424,6 +427,8 @@ public:
int max_toclevel() const { return max_toclevel_; } int max_toclevel() const { return max_toclevel_; }
/// returns true if the class has a ToC structure /// returns true if the class has a ToC structure
bool hasTocLevels() const; bool hasTocLevels() const;
///
std::string const & getCiteFormat(std::string const & entry_type) const;
protected: protected:
/// Constructs a DocumentClass based upon a LayoutFile. /// Constructs a DocumentClass based upon a LayoutFile.
DocumentClass(LayoutFile const & tc); DocumentClass(LayoutFile const & tc);

View File

@ -364,7 +364,7 @@ void GuiCitation::updateInfo(BiblioInfo const & bi, QModelIndex const & idx)
} }
QString const keytxt = toqstr( QString const keytxt = toqstr(
bi.getInfo(qstring_to_ucs4(idx.data().toString()), true)); bi.getInfo(qstring_to_ucs4(idx.data().toString()), buffer(), true));
infoML->document()->setHtml(keytxt); infoML->document()->setHtml(keytxt);
} }

View File

@ -960,7 +960,7 @@ docstring InsetBibtex::xhtml(XHTMLStream & xs, OutputParams const &) const
// which will give us all the cross-referenced info. But for every // which will give us all the cross-referenced info. But for every
// entry, so there's a lot of repitition. This should be fixed. // entry, so there's a lot of repitition. This should be fixed.
xs << html::StartTag("span", "class='bibtexinfo'") xs << html::StartTag("span", "class='bibtexinfo'")
<< bibinfo.getInfo(entry.key(), true) << bibinfo.getInfo(entry.key(), buffer(), true)
<< html::EndTag("span") << html::EndTag("span")
<< html::EndTag("div"); << html::EndTag("div");
xs.cr(); xs.cr();

View File

@ -119,7 +119,7 @@ docstring InsetCitation::toolTip(BufferView const & bv, int, int) const
vector<docstring>::const_iterator en = keys.end(); vector<docstring>::const_iterator en = keys.end();
docstring tip; docstring tip;
for (; it != en; ++it) { for (; it != en; ++it) {
docstring const key_info = bi.getInfo(*it); docstring const key_info = bi.getInfo(*it, buffer());
if (key_info.empty()) if (key_info.empty())
continue; continue;
if (!tip.empty()) if (!tip.empty())