mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-23 18:24:48 +00:00
Improve info display for biblatex databases, part II
In addition to the classic crossref, biblatex introduces xdata references in order to source-out common data of entries. Entries that have "xdata = {somekey}" just inherit all fields from the respective @xdata entry, if the field is not already defined in the entry itself (just like crossref, with the exception that @xdata entries themselves are _never_ output on their own). @xdata entries can themselves inherit to other @xdata entries (ad infinitum). So you can, for instance, setup an xdata entry for a book series with series name that inherits an xdata entry with information of the publisher (publisher, address). Any book of that series would just need to refer to the series xdata and add the number. BiblioInfo now checks, in addition to crossrefs, for such xdata references and inherits missing fields. Nte that biblatex also introduces an "xref" field as an alternative to crossref. We must not care about that, since the point of xref is that it does not inherit fields from the target (just cites that one if a given number of refs to it exist)
This commit is contained in:
parent
e7e0472742
commit
a887eb6300
@ -352,14 +352,6 @@ docstring const BibTeXInfo::getYear() const
|
||||
}
|
||||
|
||||
|
||||
docstring const BibTeXInfo::getXRef() const
|
||||
{
|
||||
if (!is_bibtex_)
|
||||
return docstring();
|
||||
return operator[]("crossref");
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
docstring parseOptions(docstring const & format, string & optkey,
|
||||
@ -485,7 +477,7 @@ I can tell, but it still feels like a hack. Fixing this would require quite a
|
||||
bit of work, however.
|
||||
*/
|
||||
docstring BibTeXInfo::expandFormat(docstring const & format,
|
||||
BibTeXInfo const * const xref, int & counter, Buffer const & buf,
|
||||
BibTeXInfoList const xrefs, int & counter, Buffer const & buf,
|
||||
docstring before, docstring after, docstring dialog, bool next) const
|
||||
{
|
||||
// incorrect use of macros could put us in an infinite loop
|
||||
@ -534,7 +526,7 @@ docstring BibTeXInfo::expandFormat(docstring const & format,
|
||||
ret << trans;
|
||||
} else {
|
||||
docstring const val =
|
||||
getValueForKey(key, buf, before, after, dialog, xref, max_keysize);
|
||||
getValueForKey(key, buf, before, after, dialog, xrefs, max_keysize);
|
||||
if (!scanning_rich)
|
||||
ret << from_ascii("{!<span class=\"bib-" + key + "\">!}");
|
||||
ret << val;
|
||||
@ -565,16 +557,16 @@ docstring BibTeXInfo::expandFormat(docstring const & format,
|
||||
return _("ERROR!");
|
||||
fmt = newfmt;
|
||||
docstring const val =
|
||||
getValueForKey(optkey, buf, before, after, dialog, xref);
|
||||
getValueForKey(optkey, buf, before, after, dialog, xrefs);
|
||||
if (optkey == "next" && next)
|
||||
ret << ifpart; // without expansion
|
||||
else if (!val.empty()) {
|
||||
int newcounter = 0;
|
||||
ret << expandFormat(ifpart, xref, newcounter, buf,
|
||||
ret << expandFormat(ifpart, xrefs, newcounter, buf,
|
||||
before, after, dialog, next);
|
||||
} else if (!elsepart.empty()) {
|
||||
int newcounter = 0;
|
||||
ret << expandFormat(elsepart, xref, newcounter, buf,
|
||||
ret << expandFormat(elsepart, xrefs, newcounter, buf,
|
||||
before, after, dialog, next);
|
||||
}
|
||||
// fmt will have been shortened for us already
|
||||
@ -623,7 +615,7 @@ docstring BibTeXInfo::expandFormat(docstring const & format,
|
||||
}
|
||||
|
||||
|
||||
docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref,
|
||||
docstring const & BibTeXInfo::getInfo(BibTeXInfoList const xrefs,
|
||||
Buffer const & buf, bool richtext) const
|
||||
{
|
||||
if (!richtext && !info_.empty())
|
||||
@ -642,7 +634,7 @@ docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref,
|
||||
docstring const & format =
|
||||
from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_)));
|
||||
int counter = 0;
|
||||
info_ = expandFormat(format, xref, counter, buf,
|
||||
info_ = expandFormat(format, xrefs, counter, buf,
|
||||
docstring(), docstring(), docstring(), false);
|
||||
|
||||
if (info_.empty()) {
|
||||
@ -660,7 +652,7 @@ docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref,
|
||||
}
|
||||
|
||||
|
||||
docstring const BibTeXInfo::getLabel(BibTeXInfo const * const xref,
|
||||
docstring const BibTeXInfo::getLabel(BibTeXInfoList const xrefs,
|
||||
Buffer const & buf, docstring const & format, bool richtext,
|
||||
docstring const & before, docstring const & after,
|
||||
docstring const & dialog, bool next) const
|
||||
@ -668,7 +660,7 @@ docstring const BibTeXInfo::getLabel(BibTeXInfo const * const xref,
|
||||
docstring loclabel;
|
||||
|
||||
int counter = 0;
|
||||
loclabel = expandFormat(format, xref, counter, buf,
|
||||
loclabel = expandFormat(format, xrefs, counter, buf,
|
||||
before, after, dialog, next);
|
||||
|
||||
if (!loclabel.empty() && !next) {
|
||||
@ -698,7 +690,7 @@ docstring const & BibTeXInfo::operator[](string const & field) const
|
||||
|
||||
docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf,
|
||||
docstring const & before, docstring const & after, docstring const & dialog,
|
||||
BibTeXInfo const * const xref, size_t maxsize) const
|
||||
BibTeXInfoList const xrefs, size_t maxsize) const
|
||||
{
|
||||
// anything less is pointless
|
||||
LASSERT(maxsize >= 16, maxsize = 16);
|
||||
@ -710,8 +702,16 @@ docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf,
|
||||
}
|
||||
|
||||
docstring ret = operator[](key);
|
||||
if (ret.empty() && xref)
|
||||
ret = (*xref)[key];
|
||||
if (ret.empty() && !xrefs.empty()) {
|
||||
vector<BibTeXInfo const *>::const_iterator it = xrefs.begin();
|
||||
vector<BibTeXInfo const *>::const_iterator en = xrefs.end();
|
||||
for (; it != en; ++it) {
|
||||
if (*it && !(**it)[key].empty()) {
|
||||
ret = (**it)[key];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret.empty()) {
|
||||
// some special keys
|
||||
// FIXME: dialog, textbefore and textafter have nothing to do with this
|
||||
@ -751,7 +751,7 @@ docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf,
|
||||
docstring const & format =
|
||||
from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_)));
|
||||
int counter = 0;
|
||||
ret = expandFormat(format, xref, counter, buf,
|
||||
ret = expandFormat(format, xrefs, counter, buf,
|
||||
docstring(), docstring(), docstring(), false);
|
||||
} else if (key == "textbefore")
|
||||
ret = before;
|
||||
@ -790,6 +790,30 @@ public:
|
||||
} // namespace anon
|
||||
|
||||
|
||||
vector<docstring> const BiblioInfo::getXRefs(BibTeXInfo const & data, bool const nested) const
|
||||
{
|
||||
vector<docstring> result;
|
||||
if (!data.isBibTeX())
|
||||
return result;
|
||||
// Legacy crossref field. This is not nestable.
|
||||
if (!nested && !data["crossref"].empty())
|
||||
result.push_back(data["crossref"]);
|
||||
// Biblatex's xdata field. Infinitely nestable.
|
||||
docstring const xdatakey = data["xdata"];
|
||||
if (!xdatakey.empty()) {
|
||||
result.push_back(xdatakey);
|
||||
BiblioInfo::const_iterator it = find(xdatakey);
|
||||
if (it != end()) {
|
||||
BibTeXInfo const & xdata = it->second;
|
||||
vector<docstring> const nxdata = getXRefs(xdata, true);
|
||||
if (!nxdata.empty())
|
||||
result.insert(result.end(), nxdata.begin(), nxdata.end());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
vector<docstring> const BiblioInfo::getKeys() const
|
||||
{
|
||||
vector<docstring> bibkeys;
|
||||
@ -853,17 +877,23 @@ docstring const BiblioInfo::getYear(docstring const & key, bool use_modifier) co
|
||||
BibTeXInfo const & data = it->second;
|
||||
docstring year = data.getYear();
|
||||
if (year.empty()) {
|
||||
// let's try the crossref
|
||||
docstring const xref = data.getXRef();
|
||||
if (xref.empty())
|
||||
// let's try the crossrefs
|
||||
vector<docstring> const xrefs = getXRefs(data);
|
||||
if (xrefs.empty())
|
||||
// no luck
|
||||
return docstring();
|
||||
BiblioInfo::const_iterator const xrefit = find(xref);
|
||||
vector<docstring>::const_iterator it = xrefs.begin();
|
||||
vector<docstring>::const_iterator en = xrefs.end();
|
||||
for (; it != en; ++it) {
|
||||
BiblioInfo::const_iterator const xrefit = find(*it);
|
||||
if (xrefit == end())
|
||||
// no luck again
|
||||
return docstring();
|
||||
continue;
|
||||
BibTeXInfo const & xref_data = xrefit->second;
|
||||
year = xref_data.getYear();
|
||||
if (!year.empty())
|
||||
// success!
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (use_modifier && data.modifier() != 0)
|
||||
year += data.modifier();
|
||||
@ -887,14 +917,18 @@ docstring const BiblioInfo::getInfo(docstring const & key,
|
||||
if (it == end())
|
||||
return docstring(_("Bibliography entry not found!"));
|
||||
BibTeXInfo const & data = it->second;
|
||||
BibTeXInfo const * xrefptr = 0;
|
||||
docstring const xref = data.getXRef();
|
||||
if (!xref.empty()) {
|
||||
BiblioInfo::const_iterator const xrefit = find(xref);
|
||||
BibTeXInfoList xrefptrs;
|
||||
vector<docstring> const xrefs = getXRefs(data);
|
||||
if (!xrefs.empty()) {
|
||||
vector<docstring>::const_iterator it = xrefs.begin();
|
||||
vector<docstring>::const_iterator en = xrefs.end();
|
||||
for (; it != en; ++it) {
|
||||
BiblioInfo::const_iterator const xrefit = find(*it);
|
||||
if (xrefit != end())
|
||||
xrefptr = &(xrefit->second);
|
||||
xrefptrs.push_back(&(xrefit->second));
|
||||
}
|
||||
return data.getInfo(xrefptr, buf, richtext);
|
||||
}
|
||||
return data.getInfo(xrefptrs, buf, richtext);
|
||||
}
|
||||
|
||||
|
||||
@ -922,17 +956,21 @@ docstring const BiblioInfo::getLabel(vector<docstring> keys,
|
||||
BibTeXInfo empty_data;
|
||||
empty_data.key(*key);
|
||||
BibTeXInfo & data = empty_data;
|
||||
BibTeXInfo const * xrefptr = 0;
|
||||
vector<BibTeXInfo const *> xrefptrs;
|
||||
if (it != end()) {
|
||||
data = it->second;
|
||||
docstring const xref = data.getXRef();
|
||||
if (!xref.empty()) {
|
||||
BiblioInfo::const_iterator const xrefit = find(xref);
|
||||
vector<docstring> const xrefs = getXRefs(data);
|
||||
if (!xrefs.empty()) {
|
||||
vector<docstring>::const_iterator it = xrefs.begin();
|
||||
vector<docstring>::const_iterator en = xrefs.end();
|
||||
for (; it != en; ++it) {
|
||||
BiblioInfo::const_iterator const xrefit = find(*it);
|
||||
if (xrefit != end())
|
||||
xrefptr = &(xrefit->second);
|
||||
xrefptrs.push_back(&(xrefit->second));
|
||||
}
|
||||
}
|
||||
ret = data.getLabel(xrefptr, buf, ret, for_xhtml,
|
||||
}
|
||||
ret = data.getLabel(xrefptrs, buf, ret, for_xhtml,
|
||||
before, after, dialog, key + 1 != ken);
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,8 @@ public:
|
||||
/// and the values are the associated field values.
|
||||
typedef std::map<docstring, docstring>::const_iterator const_iterator;
|
||||
///
|
||||
typedef std::vector<BibTeXInfo const *> const BibTeXInfoList;
|
||||
///
|
||||
BibTeXInfo() : is_bibtex_(true), modifier_(0) {}
|
||||
/// argument sets isBibTeX_, so should be false only if it's coming
|
||||
/// from a bibliography environment
|
||||
@ -58,14 +60,12 @@ public:
|
||||
Buffer const * buf = 0, bool jurabib_style = false) const;
|
||||
///
|
||||
docstring const getYear() const;
|
||||
///
|
||||
docstring const getXRef() const;
|
||||
/// \return formatted BibTeX data suitable for framing.
|
||||
/// \param pointer to crossref information
|
||||
docstring const & getInfo(BibTeXInfo const * const xref,
|
||||
/// \param vector of pointers to crossref/xdata information
|
||||
docstring const & getInfo(BibTeXInfoList const xrefs,
|
||||
Buffer const & buf, bool richtext) const;
|
||||
/// \return formatted BibTeX data for a citation label
|
||||
docstring const getLabel(BibTeXInfo const * const xref,
|
||||
docstring const getLabel(BibTeXInfoList const xrefs,
|
||||
Buffer const & buf, docstring const & format, bool richtext,
|
||||
const docstring & before, const docstring & after,
|
||||
const docstring & dialog, bool next = false) const;
|
||||
@ -111,11 +111,11 @@ public:
|
||||
bool isBibTeX() const { return is_bibtex_; }
|
||||
private:
|
||||
/// like operator[], except, if the field is empty, it will attempt
|
||||
/// to get the data from xref BibTeXInfo object, which would normally
|
||||
/// be the one referenced in the crossref field.
|
||||
/// to get the data from xref BibTeXInfo objects, which would normally
|
||||
/// be the one referenced in the crossref or xdata field.
|
||||
docstring getValueForKey(std::string const & key, Buffer const & buf,
|
||||
docstring const & before, docstring const & after, docstring const & dialog,
|
||||
BibTeXInfo const * const xref, size_t maxsize = 4096) const;
|
||||
BibTeXInfoList const xrefs, size_t maxsize = 4096) const;
|
||||
/// replace %keys% in a format string with their values
|
||||
/// called from getInfo()
|
||||
/// format strings may contain:
|
||||
@ -133,7 +133,7 @@ private:
|
||||
/// moreover, keys that look like "%_key%" are treated as translatable
|
||||
/// so that things like "pp." and "vol." can be translated.
|
||||
docstring expandFormat(docstring const & fmt,
|
||||
BibTeXInfo const * const xref, int & counter,
|
||||
BibTeXInfoList const xrefs, int & counter,
|
||||
Buffer const & buf, docstring before = docstring(),
|
||||
docstring after = docstring(), docstring dialog = docstring(),
|
||||
bool next = false) const;
|
||||
@ -166,8 +166,13 @@ private:
|
||||
/// from BibTeX or from bibliography environments.
|
||||
class BiblioInfo {
|
||||
public:
|
||||
///
|
||||
typedef std::vector<BibTeXInfo const *> BibTeXInfoList;
|
||||
/// bibliography key --> data for that key
|
||||
typedef std::map<docstring, BibTeXInfo>::const_iterator const_iterator;
|
||||
/// Get a vector with all external data (crossref, xdata)
|
||||
std::vector<docstring> const getXRefs(BibTeXInfo const & data,
|
||||
bool const nested = false) const;
|
||||
/// \return a sorted vector of bibliography keys
|
||||
std::vector<docstring> const getKeys() const;
|
||||
/// \return a sorted vector of present BibTeX fields
|
||||
@ -179,15 +184,19 @@ public:
|
||||
/// \return the year from the bibtex data record for \param key
|
||||
/// if \param use_modifier is true, then we will also append any
|
||||
/// modifier for this entry (e.g., 1998b).
|
||||
/// Note that this will get the year from the crossref if it's
|
||||
/// not present in the record itself.
|
||||
/// If no legacy year field is present, check for date (common in
|
||||
/// biblatex) and extract the year from there.
|
||||
/// Note further that this will get the year from the crossref or xdata
|
||||
/// if it's not present in the record itself.
|
||||
docstring const getYear(docstring const & key,
|
||||
bool use_modifier = false) const;
|
||||
/// \return the year from the bibtex data record for \param key
|
||||
/// if \param use_modifier is true, then we will also append any
|
||||
/// modifier for this entry (e.g., 1998b).
|
||||
/// Note that this will get the year from the crossref if it's
|
||||
/// not present in the record itself.
|
||||
/// If no legacy year field is present, check for date (common in
|
||||
/// biblatex) and extract the year from there.
|
||||
/// Note further that this will get the year from the crossref or xdata
|
||||
/// if it's not present in the record itself.
|
||||
/// If no year is found, \return "No year" translated to the buffer
|
||||
/// language.
|
||||
docstring const getYear(docstring const & key, Buffer const & buf,
|
||||
@ -196,7 +205,7 @@ public:
|
||||
docstring const getCiteNumber(docstring const & key) const;
|
||||
/// \return formatted BibTeX data associated with a given key.
|
||||
/// 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 or xdata as needed.
|
||||
/// If \param richtext is true, then it will output any richtext tags
|
||||
/// marked in the citation format and escape < and > elsewhere.
|
||||
docstring const getInfo(docstring const & key, Buffer const & buf,
|
||||
|
Loading…
Reference in New Issue
Block a user