Feature request: Display all inherited values, including fields not displayed by default
Closed this issue ยท 5 comments
I have recently started using origyear
, origpublisher
and so on in my bib files, to indicate the initial publication of a work. I was working with a paper, first published in a collection in 1912, though the copy I had was pubhlised in 1970. So, I made a Collection
with origyear = 1912
, and year = 1970
. I crossreferenced the Collection
entry in an InCollection
entry, with only the details of the particular paper (file, author, title). In biblatex itself (as in, when I compiled a pdf of my essay, in the printed bibliography), the origyear
(and origpublisher
) of the Collection
were inherited by the InCollection
entry.
This doesn't show up in ebib. orig{year,publisher,etc.}
fields are not very common, and so are only displayed by default. Of course, they are displayed if they have a value (so the Collection
displays correctly). But ebib doesn't account for the fact that a value might inherited: only fields which are always displayed, or have an explicit (non-inherited) value are displayed. This misses the inherited value of origyear
in the InCollection
.
(Note that ebib does understand that the value has been inherited. If I add the field origyear
to the InCollection
entry and input nothing, then it displays with the inherited value, in the crossref face, just as it should. This just doesn't happen by default.)
So, my request: I don't know which part of the code deals with this, but I would like it if the existence of inherited values were accounted for in deciding which fields to display.
There is a workaround which works for now: adding fields like origyear
to ebib-extra-fields
. But this has two problems:
- It displays these fields all the time, for every entry, which is annoying. There is a reason they're not displayed by default!
- This problem exists for
origyear
for me, but might exist for other fields for other people. A general version of this workaround to fulfil all needs would amount to always displaying every possible field, which is hardly practical!
Yes, that's a bug, thanks for reporting it. The tl;dr of it is that I'm hoping to post a fix soon.
If you're interested in the whole story: It's actually two bugs, the one you noticed and one very similar. Luckily, they only need one joint fix.
Ebib distinguishes between fields that are predefined and fields that are not. The former can either be defined for a specific entry type, or they can be defined as "extra fields", meaning they apply to all entry types.
For predefined fields, Ebib also distinguishes between fields that are hidden by default and those that are not. Those that are hidden are only shown if they have a value. But they are only shown if they have a value themselves, not if they inherit a value from their cross-referenced entry.
Does that sound like your bug? Well, it isn't. ๐ Though from a user PoV, I admit it looks exactly the same.
That's because undefined fields (like the fields you are talking about) behave the same, but for a different reason.
This is also why adding your fields to ebib-extra-fields
makes them visible: they are now defined, and since they are not in ebib-hidden-fields
, their (inherited) values are shown. As an alternative, you could also define them in bibtex-biblatex-entry-alist
for only those entries for which you need them.
But I agree that's not really the right solution, because you'd run into this problem with any field that is not defined. Both hidden fields and undefined fields that inherit a value should be shown.
So how can this be solved? Well, the relevant code is in ebib.el
, lines 436-468:
Lines 436 to 468 in f9d2b15
The mapc
in line 453 goes through the various types of predefined fields plus all the undefined fields in the relevant entry (see line 468).
Each set of fields is formatted into the current buffer by the inner mapc
(line 456). However, fields that are not actually in the current entry (line 457) and that are in ebib-hidden-fields
(line 458) are skipped. This filters out hidden fields because they are not in the current entry, even if they do have an inherited value.
In addition, undefined fields with an inherited value are also skipped. In line 442, only those undefined fields that are actually present in the relevant entry's alist are collected in undef-fields
, so undefined fields that inherit their value don't even make it to the mapc
starting in line 453.
That's the diagnosis. A solution is conceptually simple: in line 437, where the variable entry
gets its value, instead of just getting the alist for the relevant entry, we need to get this alist plus the relevant fields from the cross-referenced entry.
Luckily, there's a function in parsebib.el
that can do this: parsebib--get-xref-fields
. So the procedure would be:
- check if
entry
has acrossref
field; if yes:- get the cross-referenced entry's alist
- pass both alists to
parsebib--get-xref-fields
- use the return value in the rest of the function.
A few caveats: First, parsebib--get-xref-fields
modifies its first argument, so you need to pass a copy of the alist.
Second, parsebib--get-xref-fields
requires a third argument, the inheritance schema. For BibTeX, this can simply be the symbol BibTeX
, but for biblatex, it should be a complete inheritance schema. parsebib.el
defines an inheritance schema for biblatex, but you should not use that one, because Ebib has its own schema, which the user may have customised. (Not very likely, but theoretically possible.)
Now, for some silly reason that I don't remember, Ebib and parsebib use the exact same inheritance schema, save for one little detail: where the Ebib version has the symbol none
, the parsebib version has the keyword :none
. (Sigh... Why did I do that!? ๐ฉ )
The most sensible way to remedy this, I think, would be to change parsebib. We could either be bold and use none
in parsebib--biblatex-inheritances
as well. The user base of parsebib.el
is much larger than that of Ebib, but I still suspect few people, if any, will have customised parsebib--biblatex-inheritances
. Alternatively, more cautious but safer, test for both :none
and none
in parsebib--get-target-field
. Either way, you can then simply pass ebib-biblatex-inheritances
to parsebib--get-xref-fields
and have it work.
This shouldn't take too long to implement, (probably less than it took me to research all this... ๐ ), so I'll have a go at it in the next few days. Or, feel free to post a PR. ๐
You have certainly done the research! You clearly know much more about this bug than I possibly could, so I think I'll leave this one to you.
The most sensible way to remedy this, I think, would be to change parsebib. We could either be bold and use none in parsebib--biblatex-inheritances as well. The user base of parsebib.el is much larger than that of Ebib, but I still suspect few people, if any, will have customised parsebib--biblatex-inheritances.
FWIW though, I reckon this is a bug, not an accidental difference in two pieces of software, and so I don't think there's much of a reason to support non-uniform ways of doing things. Checking for both none
and :none
in parsebib would also lead to different pieces of software using different strategies, creating downstream bugs, which would require yet more code to defend against (which would just amount to a load of PRs on every repo using parsebib to replace :none
with (or 'none :none)
. None of this is desirable. I think bold is the best approach: only check for none
in parsebib.
You have certainly done the research! You clearly know much more about this bug than I possibly could, so I think I'll leave this one to you.
๐
[...]
FWIW though, I reckon this is a bug, not an accidental difference in two pieces of software, and so I don't think there's much of a reason to support non-uniform ways of doing things. Checking for both
none
and:none
in parsebib would also lead to different pieces of software using different strategies, creating downstream bugs, which would require yet more code to defend against (which would just amount to a load of PRs on every repo using parsebib to replace:none
with(or 'none :none)
. None of this is desirable. I think bold is the best approach: only check fornone
in parsebib.
Done.
I still think the practical impact of either solution would be minimal to non-existent, but I agree using just none
is the better solution.
This should be fixed now. Please let me know if you see any problems.
Just checked, and it works at my end. Thank you!