1

In working on improved documentation for a Biblatex style, I'd like to print nicely styled verbatim .bib entries beside the output for each, thereby juxtaposing cause and effect. This could be done by hand for each entry, but I hoped it might be easier to define a custom Biblatex citation command for typesetting .bib entries exactly as they appear in the file. A custom citation command would not only save tedium, but it would also help with automating documentation.

Unfortunately, I'm unsure how to access the literal data in a field, if this is even possible. I'd imagine Biber's already processing and parsing the data before Biblatex even sees it, and my use case is probably complicated by wanting to juxtapose unprocessed .bib data with stylized, processed Biblatex output. Here's a simplified version of what I have so far, along with the output for two entries:

\documentclass[a4paper]{article}
\usepackage[american]{babel}
\usepackage{csquotes}
\usepackage{xcolor}
\usepackage[style=mla,backend=biber]{biblatex}

\usepackage{filecontents}

\begin{filecontents}{documentation.bib} @article{Tibullus:2002ub, author = {Tibullus}, date = {2002/2003}, journal = {Chicago Review}, number = {4}, pages = {102--106}, title = {How to Be Tibullus}, translator = {Wray, David}, volume = {48}}

@article{Evacuation:wj, date = {2016-07-15}, entrysubtype = {newspaper}, journal = {The Boston Globe}, title = {Evacuation Order Lifted at Nice Airport}, url = {www.bostonglobe.com/news/world/2016/07/15/evacuation-progress-nice-airport/KO4BytWK4wFUOxjEkSpKTN/story.html}} \end{filecontents}

\addbibresource{documentation.bib}

\DeclareCiteCommand{\samplebib}[\texttt] {}% {\usebibmacro{citeindex}% \renewcommand{\newunitpunct}{\addcomma\newline}% \renewcommand{\multinamedelim}{\addspace{}and\addspace{}}% \usebibmacro{cite:mla:bib}} {}% {}

\newcommand{\entrycolor}{\color{teal}} \newcommand{\fieldcolor}[1]{{\color{purple}#1}} \newcommand{\fieldindent}{{\color{white} ~~~}}

\newcommand{\fieldcite}[1]{ \iffieldundef{#1}% {}% {\printtext{\fieldindent\fieldcolor{#1} = {\printfield[noformat]{#1}}}}% \ifnameundef{#1}% {}% {\printtext{\fieldindent\fieldcolor{#1} = {\printnames[family-given][-\value{listtotal}]{#1}}}}% \iflistundef{#1}% {}% {\printtext{\fieldindent\fieldcolor{#1} = {\printlist{#1}}}}% }

\makeatletter \newbibmacro*{cite:mla:bib}{% {\entrycolor\printtext{@}\printfield{entrytype}}{\printfield{entrykey}% \newunit% \fieldcite{author}% \newunit% \fieldcite{date}% \newunit% \fieldcite{day}% \newunit% \fieldcite{entrysubtype}% \newunit% \fieldcite{institution}% \newunit% \fieldcite{journaltitle}% \newunit% \fieldcite{journal}% \newunit% \fieldcite{month}% \newunit% \fieldcite{number}% \newunit% \fieldcite{options}% \newunit% \fieldcite{pages}% \newunit% \fieldcite{title} \newunit% \fieldcite{translator} \newunit% \fieldcite{url} \newunit% \fieldcite{volume} \newunit% \fieldcite{year}% \newline% } } \makeatother

\begin{document}

\begin{refsection} \noindent\samplebib{Tibullus:2002ub} \printbibliography[heading=none] \end{refsection}

\begin{refsection} \noindent\samplebib{Evacuation:wj} \printbibliography[heading=none] \end{refsection}

\end{document}

output of bibtex documentation

The output shows that the date entry is now gone, replaced by year, month, and day as needed, without any range. Likewise the journal field is converted with journaltitle--though this kind of conversion is less of a problem. Other entries will have similar substitutions, too, but they boil down to the same problem. (I understand why this is the default and have no complaints!) Is it possible to insist that Biblatex should show the literal .bib input for every field, or are these values out of reach? Perhaps more importantly, have I overlooked a better way to programmatically typeset Bibtex data from an existing .bib file for documentation?

jmclawson
  • 890
  • I've been working on this for awhile now and had my hopes raised this morning when I saw this question: https://tex.stackexchange.com/questions/601342/how-can-i-programatically-write-a-biblatex-file-containing-all-and-only-the-ref (Unfortunately, we weren't after the same goal.) – jmclawson Jun 15 '21 at 16:09
  • why don't you simply input the bib (or a part by line number or with some markers) with the listings package? – Ulrike Fischer Jun 15 '21 at 18:08
  • The listing package was one of the first ways I tried. As I understood it, it still required the (tedious) reproduction of .bib entries each time I wanted to show an entry's metadata. While my example above has been minimized to show only two citations, my documentation, when finished, will probably print a couple hundred sources, recreating examples from a handbook. – jmclawson Jun 15 '21 at 18:55
  • sorry I don't understand what you mean with "reproduction". – Ulrike Fischer Jun 15 '21 at 18:58
  • It may be that I misunderstand the capabilities of the listings package. If I have ~200 entries in an external .bib file, will the listings package allow me to call up the data from one of them by, e.g., the cite key? I think the package requires me either to copy and paste each entry ("reproducing" it) into my .tex file or to reference the specific line numbers I'd like to show—but these will shift when a bib file has changes and additions. (Or can I programmatically indicate these line numbers?) – jmclawson Jun 15 '21 at 19:16
  • 2
    you could use line range markers, see 5.7 Arbitrary linerange markers in the listings docu. – Ulrike Fischer Jun 15 '21 at 19:26
  • Ah! This looks viable. I can pre-process the .bib file to name line range markers with cite keys, which should make it easy to drop listings in programmatically. I'll give it a try in the next day. Thank you for pointing me in this direction! – jmclawson Jun 15 '21 at 19:36
  • For my biblatex-ext documentation I use \newtcbinputlisting with line numbers, but of course that requires manual adjustments when the .bib file changes. You could avoid this by using .dtx files to create the duplicate data (for .bib file and .tex file) from a single source without duplication. See for example the documentation of biblatex-oxref: https://github.com/alex-ball/biblatex-oxref/blob/master/oxref.dtx – moewe Jun 15 '21 at 21:02
  • 2
    It is very tricky to reconstruct the .bib data on the LaTeX side because you'd have to undo all of Biber's pre-processing steps (most prominently date parsing, but also field aliasing [journal -> journaltitle] and much more for crossref etc.) That might be possible for simple examples, but becomes less and less viable the more advanced features of biblatex you want to use. – moewe Jun 15 '21 at 21:09
  • 1
    In my last comment I should have probably made clearer that once on the LaTeX side of things you absolutely cannot distinguish whether input used journal or journaltitle (that is the point of the sourcemapping by Biber). Of course Biber would have the info available, but it's not exposed to the LaTeX side of things. For most simple dates it should be possible to reconstruct the date value, but it would get fairly messy for complex dates. – moewe Jun 16 '21 at 06:03
  • @UlrikeFischer your suggestion worked perfectly. Thank you! If you'd like to make it an answer, I will mark it. – jmclawson Jun 16 '21 at 12:29
  • @moewe thank you for pointing me to some other good options. Your documentation in biblatex-ext is very user friendly! And what you say about the options left available by Biber's sourcemapping makes good sense to me. The tradeoff of losing literal specificity is very much worth it to gain an easier data workflow with Biblatex. – jmclawson Jun 16 '21 at 12:32

2 Answers2

1

Reconstructing the bib-file from the bbl is not really possible as biber does a number of preprocessing you can't revert on the LaTeX side.

So I would use the listings package to include the bib-file verbatim.

A part of the file can be selected either by line numbers or --- if the line numbers are not stable enough --- you can use range markers as described in the listings documentation, 5.7 Arbitrary linerange markers.

Ulrike Fischer
  • 327,261
  • Thank you! This worked well. I pre-process my bib files in R (because it's what I know), and then use the listings package to include that data in my Latex documentation. Here's a gist to my R code to prepare a bibfile: https://gist.github.com/jmclawson/882c7ff79e5e9fdf37973a38ca52571a Here's the gist to Latex code for creating a \bibcitem command for use in documentation: https://gist.github.com/jmclawson/6b04d45ca5f5e05d021586b4da508760 – jmclawson Jun 16 '21 at 13:58
1

Instead of preprocessing the files yourself you can also use Bibtool, which allows to extract single entries from a .bib file (among many other things).

You can call Bibtool from within LaTeX using \write18 to save an entry to a temporary file and then use \lstinputlisting on that file. Note that this requires compiling with -shell-escape.

Bibtool does some processing on the file, such as adding a newline at the startof the file, and converting cite keys to lower case. You can switch that off.

MWE, based on your gist:

\documentclass[a4paper]{article}
\usepackage[american]{babel}
\usepackage{csquotes}
\usepackage{xcolor}
\usepackage[style=mla,backend=biber]{biblatex}
\usepackage{listings}

\lstdefinelanguage{BibTeX}{% % keywordsprefix={@}% keywords={% @book,@article,@incollection,@suppbook,@mvbook,@collection,@review,@misc,% @thesis,@mvreference,@inreference,@mvlexicon,@inlexicon,@unpublished,% @commentary,@inbook,@incommentary,@mvcommentary,@seminarpaper,@lexicon,% @reference,@mvcollection,@bookinbook,@ancienttext,@classictext,@online,% @manual,@conferencepaper,@series% }, emph={% author,title,location,publisher,date,shorttitle,translator,edition,preface,% related,relatedtype,editor,series,shortseries,number,journal,journaltitle,% shortjournal,volume,pages,type,booktitle,bookauthor,origlocation,% origpublisher,origdate,pubstate,origlanguage,maintitle,maineditor,part,% bookeditor,seriesseries,maintranslator,eprint,eprinttype,doi,url,% revdauthor,revdtitle,revdeditor,institution,type,shorthand,xref,% note,eprintdate,volumes,shortmaintitle,options,eprintclass,relatedoptions,% editortype,crossref,editora,editorb,editorc,editoratype,editorbtyle,% editorctype,entrysubtype,sorttitle,titleaddon,witheditor,witheditortype,% withtranslator,withtranslatortype,eventtitle,venue,eventdate,shortauthor% }, sensitive=false, breaklines=true, %breakatwhitespace=true, morecomment=[l][basicstyle]{=\ {} }

\lstset{% language=BibTeX, backgroundcolor=\color{gray!5}, basicstyle=\ttfamily\small, keywordstyle=\color{teal}, emphstyle=\color{purple} }

\lstset{rangeprefix=%[[\ ,% percent + double left square brace + space rangesuffix=\ ]]}% space + double right square bracket

\addbibresource{documentation.bib}

\newcommand{\sidebyside}[1]{% \begin{refsection}% \nocite{#1}% \immediate\write18{bibtool -- suppress.initial.newline=true -- preserve.key.case=on -X "^#1$" documentation.bib -o tmpsingle.bib}% \lstinputlisting{tmpsingle.bib}% \printbibliography[heading=none] \end{refsection} }

\begin{document} \sidebyside{Tibullus:2002ub}

\sidebyside{Evacuation:wj} \end{document}

Result:

enter image description here

Remark: tested on Linux only, I'm not sure the command line call will work as given on Windows or Mac - but if it doesn't then probably it can be adjusted easily.

Marijn
  • 37,699
  • I'd seen Bibtool mentioned in some other answers to other questions, but I wasn't aware it was able to do the kinds of things you show here. This looks like a great addition to the workflow. Thank you for suggesting it! – jmclawson Jun 16 '21 at 16:10