Introduce a simple macro facility for citation formats. Also introduce

simple, translatable units for use in such formats.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@33924 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Richard Heck 2010-03-29 20:01:28 +00:00
parent 6c8ace9e7d
commit 808ff6650c
6 changed files with 97 additions and 18 deletions

View File

@ -4,12 +4,30 @@
Format 26 Format 26
CiteFormat CiteFormat
article %author%, "%title%", {!<i>!}%journal%{!</i>!} {%volume%[[ %volume%{%number%[[, %number%]]}]]} (%year%){%pages%[[, pp. %pages%]]}.{%note%[[ %note%]]} # translatable bits
_pptext pp.
book {%author%[[%author%, ]][[{%editor%[[%editor%, %ed_text%, ]]}]]}{!<i>!}%title%{!</i>!}{%volume%[[ vol. %volume%]][[{%number%[[no. %number%]]}]]}{%edition%[[%edition%]]} ({%address%[[%address%: ]]}%publisher%, %year%).{%note%[[ %note%]]} _edtext ed.
_voltext vol.
_numtext no.
_in in
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%]]} # macros
!pages {%pages%[[, %_pptext% %pages%]]}
!authoredit {%author%[[%author%, ]][[{%editor%[[%editor%, %_edtext%, ]]}]]}
!volnum {%volume%[[ %_voltext% %volume%]][[{%number%[[%_numtext% %number%]]}]]}
!quotetitle "%title%"
!emphtitle {!<i>!}%title%{!</i>!}
!emphjournal {!<i>!}%journal%{!</i>!}
!insomething %author%, %!quotetitle%, %_in%{%editor%[[ %editor%, %_edtext%,]]} {!<i>!}%booktitle%{!</i>!}%!volnum%{%edition%[[%edition%]]} ({%address%[[%address%: ]]}%publisher%, %year%)%!pages%.{%note%[[ %note%]]}
article %author%, %!quotetitle%, %!emphjournal% {%volume%[[ %volume%{%number%[[, %number%]]}]]} (%year%)%!pages%.{%note%[[ %note%]]}
book %!authoredit%%!emphtitle%%!volnum%{%edition%[[%edition%]]} ({%address%[[%address%: ]]}%publisher%, %year%).{%note%[[ %note%]]}
incollection %!insomething%
inproceedings %!insomething%
thesis %author%, %title% ({%address%[[%address%: ]]}%school%, %year%).{%note%[[ %note%]]} thesis %author%, %title% ({%address%[[%address%: ]]}%school%, %year%).{%note%[[ %note%]]}
End End

View File

@ -92,10 +92,14 @@ def layouts_l10n(input_files, output, base):
EndI18nPreamble = re.compile(r'\s*End(Lang)|(Babel)Preamble\s*$') EndI18nPreamble = re.compile(r'\s*End(Lang)|(Babel)Preamble\s*$')
I18nString = re.compile(r'_\(([^\)]+)\)') I18nString = re.compile(r'_\(([^\)]+)\)')
CounterFormat = re.compile(r'\s*PrettyFormat\s+"?(.*)"?') CounterFormat = re.compile(r'\s*PrettyFormat\s+"?(.*)"?')
CiteFormat = re.compile(r'\s*CiteFormat')
KeyVal = re.compile(r'^\s*_\w+\s+(.*)$')
End = re.compile(r'\s*End')
for src in input_files: for src in input_files:
readingDescription = False readingDescription = False
readingI18nPreamble = False readingI18nPreamble = False
readingCiteFormats = False
descStartLine = -1 descStartLine = -1
descLines = [] descLines = []
lineno = 0 lineno = 0
@ -179,6 +183,18 @@ def layouts_l10n(input_files, output, base):
string = res.group(1) string = res.group(1)
writeString(out, src, base, lineno, string) writeString(out, src, base, lineno, string)
continue continue
res = CiteFormat.search(line)
if res != None:
readingCiteFormats = True
res = End.search(line)
if res != None and readingCiteFormats:
readingCiteFormats = False
if readingCiteFormats:
res = KeyVal.search(line)
if res != None:
val = res.group(1)
writeString(out, src, base, lineno, val)
out.close() out.close()

View File

@ -395,17 +395,27 @@ namespace {
docstring BibTeXInfo::expandFormat(string const & format, docstring BibTeXInfo::expandFormat(string const & format,
BibTeXInfo const * const xref, bool richtext) const BibTeXInfo const * const xref, Buffer const & buf,
bool richtext) const
{ {
// incorrect use of macros could put us in an infinite loop
static int max_passes = 1000;
docstring ret; // return value docstring ret; // return value
string key; string key;
bool scanning_key = false; bool scanning_key = false;
bool scanning_rich = false; bool scanning_rich = false;
int passes = 0;
string fmt = format; string fmt = format;
// we'll remove characters from the front of fmt as we // we'll remove characters from the front of fmt as we
// deal with them // deal with them
while (fmt.size()) { while (fmt.size()) {
if (passes++ > max_passes) {
LYXERR0("Recursion limit reached while parsing `"
<< format << "'.");
return _("ERROR!");
}
char_type thischar = fmt[0]; char_type thischar = fmt[0];
if (thischar == '%') { if (thischar == '%') {
// beginning or end of key // beginning or end of key
@ -413,14 +423,27 @@ 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
docstring const val = getValueForKey(key, xref); if (key[0] == '!') {
ret += val; // macro
key.clear(); string const val =
buf.params().documentClass().getCiteMacro(key);
fmt = val + fmt.substr(1);
continue;
} else if (key[0] == '_') {
// a translatable bit
string const val =
buf.params().documentClass().getCiteMacro(key);
ret += _(val);
} else {
docstring const val = getValueForKey(key, xref);
ret += val;
}
} else { } else {
// beginning of key // beginning of key
key.clear();
scanning_key = true; scanning_key = true;
} }
} }
else if (thischar == '{') { else if (thischar == '{') {
// beginning of option? // beginning of option?
if (scanning_key) { if (scanning_key) {
@ -440,9 +463,9 @@ docstring BibTeXInfo::expandFormat(string const & format,
fmt = newfmt; fmt = newfmt;
docstring const val = getValueForKey(optkey, xref); docstring const val = getValueForKey(optkey, xref);
if (!val.empty()) if (!val.empty())
ret += expandFormat(ifpart, xref, richtext); ret += expandFormat(ifpart, xref, buf, richtext);
else if (!elsepart.empty()) else if (!elsepart.empty())
ret += expandFormat(elsepart, xref, richtext); ret += expandFormat(elsepart, xref, buf, richtext);
// fmt will have been shortened for us already // fmt will have been shortened for us already
continue; continue;
} }
@ -453,7 +476,8 @@ docstring BibTeXInfo::expandFormat(string const & format,
continue; continue;
} }
} }
// we are here if the '{' was at the end of the format. hmm. // we are here if '{' was not followed by % or !.
// So it's just a character.
ret += thischar; ret += thischar;
} }
else if (scanning_rich && thischar == '!' else if (scanning_rich && thischar == '!'
@ -497,7 +521,7 @@ docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref,
DocumentClass const & dc = buf.params().documentClass(); DocumentClass const & dc = buf.params().documentClass();
string const & format = dc.getCiteFormat(to_utf8(entry_type_)); string const & format = dc.getCiteFormat(to_utf8(entry_type_));
info_ = expandFormat(format, xref, richtext); info_ = expandFormat(format, xref, buf, richtext);
if (!info_.empty()) if (!info_.empty())
info_ = convertLaTeXCommands(info_); info_ = convertLaTeXCommands(info_);

View File

@ -117,8 +117,9 @@ private:
/// material intended only for rich text (HTML) output should be /// material intended only for rich text (HTML) output should be
/// wrapped in "{!" and "!}". it will be removed if richtext is /// wrapped in "{!" and "!}". it will be removed if richtext is
/// false. /// false.
docstring expandFormat(std::string const & fmt, docstring expandFormat(std::string const & fmt,
BibTeXInfo const * const xref, bool richtext) const; BibTeXInfo const * const xref,
Buffer const & buf, bool richtext) const;
/// true if from BibTeX; false if from bibliography environment /// true if from BibTeX; false if from bibliography environment
bool is_bibtex_; bool is_bibtex_;
/// the BibTeX key for this entry /// the BibTeX key for this entry

View File

@ -863,7 +863,13 @@ void TextClass::readCiteFormat(Lexer & lexrc)
break; break;
lexrc.eatLine(); lexrc.eatLine();
definition = lexrc.getString(); definition = lexrc.getString();
cite_formats_[etype] = definition; char initchar = etype[0];
if (initchar == '#')
continue;
if (initchar == '!' || initchar == '_')
cite_macros_[etype] = definition;
else
cite_formats_[etype] = definition;
} }
} }
@ -1361,6 +1367,16 @@ string const & DocumentClass::getCiteFormat(string const & entry_type) const
} }
string const & DocumentClass::getCiteMacro(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;
}
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// PageSides // PageSides

View File

@ -306,6 +306,8 @@ protected:
int max_toclevel_; int max_toclevel_;
/// Citation formatting information /// Citation formatting information
std::map<std::string, std::string> cite_formats_; std::map<std::string, std::string> cite_formats_;
/// Citation macros
std::map<std::string, std::string> cite_macros_;
private: private:
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
// helper routines for reading layout files // helper routines for reading layout files
@ -429,6 +431,8 @@ public:
bool hasTocLevels() const; bool hasTocLevels() const;
/// ///
std::string const & getCiteFormat(std::string const & entry_type) const; std::string const & getCiteFormat(std::string const & entry_type) const;
///
std::string const & getCiteMacro(std::string const & macro) 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);