3

General situation

In a document I have to mention bibliographic line and corresponding BibTeX blockcode of the document itself.

Then, some fields of the BibTeX code, like title author date, should not be hard-coded but should depend of the corresponding LaTeX command definitions.

What I did

In order to get this behavior, I made the following BibTeX block code definition:

\makeatletter
\newcommand\bibtexselfentry{
 @book{fauve2023TheSuperBook,
    title  = {\@title},
    author = {\@author},
    publisher = {MadPublisher},
    year = {\@date}
 }
}
\makeatother

As you see, the title author year’s value are given by the \@title \@author \@year commands inside a \makeatletter-\makeatother context.

Where the problem is set

The problem start just next when I put this command in a filecontents environment:

\begin{filecontents*}{jobname.bib}
\bibtexselfentry
\end{filecontents*}

Because the file created by filecontents do not contain the bib block as expected but literally the following content:

\bibtexselfentry

So, the consequences is BibTeX can’t find fauve2023TheSuperBook and act like if it doesn’t exist (in fact it doesn’t exist in the bib file).

Some explanations

The filecontents environment put in jobname.bib the literal content I give him. Hi doesn’t interpret it.

The question

Is it possible to give to filecontents the output of some commands to make him don’t print the literal command name?

Alternatively, is their any other way to give a bibfile some values depending of a command output instead of hard coding the values?


Appendix

MWE

\documentclass{article}
\usepackage{filecontents}


\title{The Super Book}
\author{Fauve}
\date{3 June 2023}


\makeatletter
\newcommand\bibtexselfentry{
 @book{fauve2023TheSuperBook,
    title  = {\@title},
    author = {\@author},
    publisher = {MadPublisher},
    year = {\@date}
 }
}
\makeatother


\begin{filecontents*}{jobname.bib}
\bibtexselfentry
\end{filecontents*}

\RequirePackage[backend=bibtex]{biblatex}

\addbibresource{jobname.bib}


\begin{document}
You can cite this work with:

\fullcite{fauve2023TheSuperBook}
\vspace{1cm}

Using the following Bib\TeX block:

\texttt
\bibtexselfentry



\end{document}

Expected rendering

Expected rendering

Obtained rendering

Obtained rendering

1
  • 1
    BTW: Package filecontents is obsolete and should result in a corresponding warning message, when using an up-to-date LaTeX. See LaTeX News Issue 30.
    – cabohah
    Commented Jun 14, 2023 at 5:35

1 Answer 1

5

There are several issues with you approach. First of all, filecontents has not been made to expand anything while writing. It has been made to write the contents of the environment verbatim, which means without any expansion.

Also, writing the definition of \bibtexselfentry to the file, would not help, because it would generate the content:

@book{fauve2023TheSuperBook, title  = {\@title},    author = {\@author}, publisher = {MadPublisher},     year = {\@date} }

But with class article, \@title, \@author and \@date are not longer valid after \maketitle. \maketitle redefines them empty. Just add \maketitle after \begin{document} to see it.

So you need a real expansion like here:

\documentclass{article}

\title{The Super Book}
\author{Fauve}
\date{3 June 2023}

\makeatletter
\newcommand\bibtexselfentry{
 @book{fauve2023TheSuperBook,
    title  = {\@title},
    author = {\@author},
    publisher = {MadPublisher},
    year = {\@date}
 }
}
\makeatother

\newwrite\mybibfile
\immediate\openout\mybibfile \jobname.bib
\immediate\write\mybibfile{\bibtexselfentry}
\immediate\closeout\mybibfile

\RequirePackage[backend=bibtex]{biblatex}

\addbibresource{\jobname.bib}

\begin{document}

You can cite this work with:

\fullcite{fauve2023TheSuperBook}
\vspace{1cm}

Using the following Bib\TeX block:

\texttt
\bibtexselfentry

\end{document}

which produces a bib file:

@book{fauve2023TheSuperBook, title = {The Super Book}, author = {Fauve}, publisher = {MadPublisher}, year = {3 June 2023} }

I've also removed package filecontents, which is obsolete for years and also not needed in your example. With an up-to-date LaTeX the package shows the warning:

Package filecontents Warning: This package is obsolete. Disabling it and
(filecontents)                passing control to the filecontents environment
(filecontents)                defined by the LaTeX kernel.

And I've replaces jobname.bib by \jobname.bib, because I do not think, that you want to write a file jobname.bib but a bib file with the basename of the current TeX job.

The shown example can be improved, by writing end-of-line characters to the bib file, e.g. using

\newcommand\bibtexselfentry{%
 @book{fauve2023TheSuperBook,^^J%
    title  = {\@title},^^J%
    author = {\@author},^^J%
    publisher = {MadPublisher},^^J%
    year = {\@date}^^J%
 }%
}

to write:

@book{fauve2023TheSuperBook,
title = {The Super Book},
author = {Fauve},
publisher = {MadPublisher},
year = {3 June 2023}
}

Maybe using \protected@write resp. an immediate version of it would also be a good idea:

\documentclass{article}
\usepackage{scrlfile}% provides \protected@immediate@write
\usepackage{listings}
\title{The Super Book}
\author{Fauve\and \textsc{Me}}
\date{3 June 2023}

\makeatletter
\newcommand\bibtexselfentry{%
 @book{fauve2023TheSuperBook,^^J%
    title  = {\@title},^^J%
    author = {\@author},^^J%
    publisher = {MadPublisher},^^J%
    year = {\@date}^^J%
 }%
}

\newwrite\mybibfile
\immediate\openout\mybibfile \jobname.bib
\begingroup
\def\and{\string\and\space}
\protected@immediate@write\mybibfile{}{\bibtexselfentry}
\immediate\closeout\mybibfile
\makeatother

\RequirePackage[backend=bibtex]{biblatex}

\addbibresource{\jobname.bib}

\begin{document}

You can cite this work with:

\fullcite{fauve2023TheSuperBook}
\vspace{1cm}

Using the following Bib\TeX block:

\lstinputlisting{\jobname.bib}

\end{document}

Note: If you want to do some indent of some codes, you can also use

\newcommand\bibtexselfentry{%
  @book{fauve2023TheSuperBook,^^J
  \space title  = {\@title},^^J
  \space author = {\@author},^^J
  \space publisher = {MadPublisher},^^J
  \space year = {\@date}^^J%
  }%
}

which would result in:

@book{fauve2023TheSuperBook,
  title = {The Super Book},
  author = {Fauve\and \protect \textsc  {Me}},
  publisher = {MadPublisher},
  year = {3 June 2023}
}

resp. (without my changes of \author in the last example):

@book{fauve2023TheSuperBook,
  title = {The Super Book},
  author = {Fauve},
  publisher = {MadPublisher},
  year = {3 June 2023}
}

The first space to indent the lines is from the end of line character after the ^^J, the second one from the \space command.

I would also recommend to use backend=biber. The legacy interface using backend=bibtex has a reduced functionality and is not supported by all third-party styles.

2
  • Useful answer. Just need one little improvement: is it an equivalent to “^^J” but for making tabulation?
    – fauve
    Commented Jun 14, 2023 at 6:23
  • @fauve You can, e.g., use \space to add spaces to the output. Or just remove the % after the ^^J to have one space.
    – cabohah
    Commented Jun 14, 2023 at 6:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .