From 808ff6650c731d20005ace719287841366dfb504 Mon Sep 17 00:00:00 2001 From: Richard Heck Date: Mon, 29 Mar 2010 20:01:28 +0000 Subject: [PATCH] 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 --- lib/layouts/stdciteformats.inc | 26 +++++++++++++++++---- po/lyx_pot.py | 18 ++++++++++++++- src/BiblioInfo.cpp | 42 ++++++++++++++++++++++++++-------- src/BiblioInfo.h | 5 ++-- src/TextClass.cpp | 18 ++++++++++++++- src/TextClass.h | 4 ++++ 6 files changed, 96 insertions(+), 17 deletions(-) diff --git a/lib/layouts/stdciteformats.inc b/lib/layouts/stdciteformats.inc index 6247a647fa..a5e4dd97a0 100644 --- a/lib/layouts/stdciteformats.inc +++ b/lib/layouts/stdciteformats.inc @@ -4,12 +4,30 @@ Format 26 -CiteFormat - article %author%, "%title%", {!!}%journal%{!!} {%volume%[[ %volume%{%number%[[, %number%]]}]]} (%year%){%pages%[[, pp. %pages%]]}.{%note%[[ %note%]]} +CiteFormat + # translatable bits + _pptext pp. + _edtext ed. + _voltext vol. + _numtext no. + _in in + + # macros + !pages {%pages%[[, %_pptext% %pages%]]} + !authoredit {%author%[[%author%, ]][[{%editor%[[%editor%, %_edtext%, ]]}]]} + !volnum {%volume%[[ %_voltext% %volume%]][[{%number%[[%_numtext% %number%]]}]]} + !quotetitle "%title%" + !emphtitle {!!}%title%{!!} + !emphjournal {!!}%journal%{!!} + + !insomething %author%, %!quotetitle%, %_in%{%editor%[[ %editor%, %_edtext%,]]} {!!}%booktitle%{!!}%!volnum%{%edition%[[%edition%]]} ({%address%[[%address%: ]]}%publisher%, %year%)%!pages%.{%note%[[ %note%]]} + + article %author%, %!quotetitle%, %!emphjournal% {%volume%[[ %volume%{%number%[[, %number%]]}]]} (%year%)%!pages%.{%note%[[ %note%]]} - book {%author%[[%author%, ]][[{%editor%[[%editor%, %ed_text%, ]]}]]}{!!}%title%{!!}{%volume%[[ vol. %volume%]][[{%number%[[no. %number%]]}]]}{%edition%[[%edition%]]} ({%address%[[%address%: ]]}%publisher%, %year%).{%note%[[ %note%]]} + book %!authoredit%%!emphtitle%%!volnum%{%edition%[[%edition%]]} ({%address%[[%address%: ]]}%publisher%, %year%).{%note%[[ %note%]]} - incollection %author%, \"%title%\", in{%editor%[[ %editor%, %ed_text%,]]} {!!}%booktitle%{!!}{%volume%[[ vol. %volume%]][[{%number%[[no. %number%]]}]]}{%edition%[[%edition%]]} ({%address%[[%address%: ]]}%publisher%, %year%){%pages%[[, pp. %pages%]]}.{%note%[[ %note%]]} + incollection %!insomething% + inproceedings %!insomething% thesis %author%, %title% ({%address%[[%address%: ]]}%school%, %year%).{%note%[[ %note%]]} End diff --git a/po/lyx_pot.py b/po/lyx_pot.py index 0ac580ad17..842040776d 100755 --- a/po/lyx_pot.py +++ b/po/lyx_pot.py @@ -92,10 +92,14 @@ def layouts_l10n(input_files, output, base): EndI18nPreamble = re.compile(r'\s*End(Lang)|(Babel)Preamble\s*$') I18nString = re.compile(r'_\(([^\)]+)\)') 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: readingDescription = False readingI18nPreamble = False + readingCiteFormats = False descStartLine = -1 descLines = [] lineno = 0 @@ -179,6 +183,18 @@ def layouts_l10n(input_files, output, base): string = res.group(1) writeString(out, src, base, lineno, string) 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() diff --git a/src/BiblioInfo.cpp b/src/BiblioInfo.cpp index e7ff51e6d9..4ee075e596 100644 --- a/src/BiblioInfo.cpp +++ b/src/BiblioInfo.cpp @@ -395,17 +395,27 @@ namespace { 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 string key; bool scanning_key = false; bool scanning_rich = false; + int passes = 0; string fmt = format; // we'll remove characters from the front of fmt as we // deal with them while (fmt.size()) { + if (passes++ > max_passes) { + LYXERR0("Recursion limit reached while parsing `" + << format << "'."); + return _("ERROR!"); + } + char_type thischar = fmt[0]; if (thischar == '%') { // beginning or end of key @@ -413,14 +423,27 @@ docstring BibTeXInfo::expandFormat(string const & format, // end of key scanning_key = false; // so we replace the key with its value, which may be empty - docstring const val = getValueForKey(key, xref); - ret += val; - key.clear(); + if (key[0] == '!') { + // macro + 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 { // beginning of key + key.clear(); scanning_key = true; } - } + } else if (thischar == '{') { // beginning of option? if (scanning_key) { @@ -440,9 +463,9 @@ docstring BibTeXInfo::expandFormat(string const & format, fmt = newfmt; docstring const val = getValueForKey(optkey, xref); if (!val.empty()) - ret += expandFormat(ifpart, xref, richtext); + ret += expandFormat(ifpart, xref, buf, richtext); else if (!elsepart.empty()) - ret += expandFormat(elsepart, xref, richtext); + ret += expandFormat(elsepart, xref, buf, richtext); // fmt will have been shortened for us already continue; } @@ -453,7 +476,8 @@ docstring BibTeXInfo::expandFormat(string const & format, 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; } else if (scanning_rich && thischar == '!' @@ -497,7 +521,7 @@ docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref, DocumentClass const & dc = buf.params().documentClass(); string const & format = dc.getCiteFormat(to_utf8(entry_type_)); - info_ = expandFormat(format, xref, richtext); + info_ = expandFormat(format, xref, buf, richtext); if (!info_.empty()) info_ = convertLaTeXCommands(info_); diff --git a/src/BiblioInfo.h b/src/BiblioInfo.h index fffb81c639..05b61f64cb 100644 --- a/src/BiblioInfo.h +++ b/src/BiblioInfo.h @@ -117,8 +117,9 @@ private: /// material intended only for rich text (HTML) output should be /// wrapped in "{!" and "!}". it will be removed if richtext is /// false. - docstring expandFormat(std::string const & fmt, - BibTeXInfo const * const xref, bool richtext) const; + docstring expandFormat(std::string const & fmt, + BibTeXInfo const * const xref, + Buffer const & buf, bool richtext) const; /// true if from BibTeX; false if from bibliography environment bool is_bibtex_; /// the BibTeX key for this entry diff --git a/src/TextClass.cpp b/src/TextClass.cpp index ee43150547..6bc0bc0c8e 100644 --- a/src/TextClass.cpp +++ b/src/TextClass.cpp @@ -863,7 +863,13 @@ void TextClass::readCiteFormat(Lexer & lexrc) break; lexrc.eatLine(); 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::const_iterator it = cite_macros_.find(macro); + if (it != cite_macros_.end()) + return it->second; + return empty; +} + + ///////////////////////////////////////////////////////////////////////// // // PageSides diff --git a/src/TextClass.h b/src/TextClass.h index 52074751bd..04816c5b7f 100644 --- a/src/TextClass.h +++ b/src/TextClass.h @@ -306,6 +306,8 @@ protected: int max_toclevel_; /// Citation formatting information std::map cite_formats_; + /// Citation macros + std::map cite_macros_; private: /////////////////////////////////////////////////////////////////// // helper routines for reading layout files @@ -429,6 +431,8 @@ public: bool hasTocLevels() const; /// std::string const & getCiteFormat(std::string const & entry_type) const; + /// + std::string const & getCiteMacro(std::string const & macro) const; protected: /// Constructs a DocumentClass based upon a LayoutFile. DocumentClass(LayoutFile const & tc); -- 2.39.2