5

I want to use an alphabetically numbered bibliography in a letter class that does not provide bibliographies (scrlttr in my case, but the example provided below works with letter, too). Based on this answer I came up with a short piece of code that works very satisfyingly — until I load the babel package, which I also need.

My investigations show that babel seems to provide its own definition of \@citex, and it is substantially different from plain LaTeX. Specifically, \org@@citex seems to be the place where I would have to turn a number stored in the macro \csname b@\@citeb \endcsname into an alphabetic digit using \@Alph:

> \@citex=macro:
[#1]#2->\@safe@activestrue 
        \edef \@tempa {#2}\@safe@activesfalse \org@@citex [#1]{\@tempa }.

and

> \org@@citex=macro:
[#1]#2->\leavevmode \let \@citea \@empty 
        \@cite {\@for \@citeb :=#2\do {%
        \@citea \def \@citea {,\penalty \@m \ }%
        \edef \@citeb {\expandafter \@firstofone \@citeb \@empty }%
        \if@filesw \immediate \write \@auxout {\string \citation {\@citeb }}\fi
        \@ifundefined {b@\@citeb }%
          {\hbox {\reset@font \bfseries ?}\G@refundefinedtrue \@latex@warning {Citation `\@citeb ' on page \thepage \space undefined}}%
          {\@cite@ofmt {\csname b@\@citeb \endcsname }}%  <--- this is what I would like to modify, I think
        }}{#1}.

However, in contrast to plain LaTeX in the babel version this command does not just store a number, but it is preceeded by \@safe@activesfalse and I do not understand how to get rid of that. For example, \csname b@test1 \endcsname contains:

> \b@test1=macro:
->\@safe@activesfalse 1.

For my purposes it should only contain 1.

I would like to know how to fix this, but also I'd appreciate input on how to make such a code more robust against the many things that other packages could do to it.

A minimal example is available through this gist and here:

\documentclass{scrlttr2}

%% These two lines will break everything:
% \usepackage[english,german]{babel}
% \selectlanguage{english}

%% Some of the following taken from
%% https://tex.stackexchange.com/questions/18033/using-bibtex-with-letter-class
\makeatletter
\newenvironment{thebibliography}[1]
{\list{\@biblabel{\@Alph\c@enumiv}}%  LATIN LETTERS AS REFERENCES
  {\settowidth\labelwidth{\@biblabel{#1}}%
    \leftmargin\labelwidth
    \advance\leftmargin\labelsep
    \usecounter{enumiv}%
    \let\p@enumiv\@empty
    \renewcommand\theenumiv{\@Alph\c@enumiv}}% SAME HERE
  \sloppy
  \clubpenalty4000
  \@clubpenalty \clubpenalty
  \widowpenalty4000%
  \sfcode`\.\@m}
{\def\@noitemerr
  {\@latex@warning{Empty `thebibliography' environment}}%
  \endlist}
\newcommand\newblock{\hskip .11em\@plus.33em\@minus.07em}
\let\bibsection\relax
\def\section*#1{\relax}
\def\@citex[#1]#2{\leavevmode 
  \let \@citea \@empty \@cite {%
    \@for \@citeb :=#2\do {%
      \@citea \def \@citea {,\penalty \@m \ }%
      \edef \@citeb {\expandafter \@firstofone \@citeb \@empty }%
      \if@filesw \immediate \write \@auxout {\string \citation {\@citeb }}\fi%
      \@ifundefined {b@\@citeb }%
      {\hbox {\reset@font \bfseries ?}\G@refundefinedtrue \@latex@warning {Citation `\@citeb ' on page \thepage \space undefined}}%
      {\@cite@ofmt {\expandafter\@Alph\csname b@\@citeb \endcsname }}%
    }%
  }%
  {#1}%
}
\makeatother

\bibliographystyle{unsrt}
\begin{document}
\begin{letter}{TeX.SE}

  \opening{Hello,}

  When writing scientific reports I like to refer to the references in
  the main document using the citation style that has been used
  there. Sometimes I need to mention additional references, and for
  those I like to use capital latin characters to number them. Of
  course I rely on Bib\TeX\ when writing reports. 

  Thus, I like to cite \cite{test1} and \cite{test2} separately, but
  also \cite{test1,test2}. This all works just fine, as long as I do
  not include the babel package.

  How can I make commands defined above more robust?

  \vspace{2cm}
  \noindent References:

  \begin{thebibliography}{A}
  \bibitem{test1} First reference.
  \bibitem{test2} Second reference.
  \end{thebibliography}

\end{letter}
\end{document}
5

The definition of \@citex is useless, because it's the same as the kernel's. You don't need to define \bibsection because you're not using natbib, nor you need to do \def\section*#1{}.

The problem is, instead, in the fact that \@bibitem always writes numbers and you want a letter.

Don't issue \selectlanguage in the preamble. Specify last the main language (or use main=<languagename>).

\documentclass{scrlttr2}

\usepackage[ngerman,english]{babel} % english is the default

\makeatletter
% redefine \@bibitem to write out the counter and not a number
\def\@bibitem#1{%
  \item
  \if@filesw
    \immediate\write\@auxout{\string\bibcite{#1}{\csname the\@listctr\endcsname}}%
  \fi\ignorespaces
}
\newenvironment{thebibliography}[1]
  {\list{\@biblabel{\Alph{enumiv}}}%  LATIN LETTERS AS REFERENCES
    {\settowidth\labelwidth{\@biblabel{#1}}%
     \leftmargin\labelwidth
     \advance\leftmargin\labelsep
     \usecounter{enumiv}}%
   \let\p@enumiv\@empty
   \renewcommand\theenumiv{\Alph{enumiv}}% SAME HERE
   \sloppy
   \clubpenalty4000
   \@clubpenalty \clubpenalty
   \widowpenalty4000
   \sfcode`\.\@m}
  {\def\@noitemerr{\@latex@warning{Empty `thebibliography' environment}}%
   \endlist}
\newcommand\newblock{\hskip .11em\@plus.33em\@minus.07em}
\makeatother

\bibliographystyle{unsrt}

\begin{document}
\begin{letter}{TeX.SE}

  \opening{Hello,}

  When writing scientific reports I like to refer to the references in
  the main document using the citation style that has been used
  there. Sometimes I need to mention additional references, and for
  those I like to use capital latin characters to number them. Of
  course I rely on Bib\TeX\ when writing reports. 

  Thus, I like to cite \cite{test1} and \cite{test2} separately, but
  also \cite{test1,test2}. This all works just fine, as long as I do
  not include the babel package.

  How can I make commands defined above more robust?

  \vspace{2cm}
  \noindent References:

  \begin{thebibliography}{A}
  \bibitem{test1} First reference.
  \bibitem{test2} Second reference.
  \end{thebibliography}

\end{letter}
\end{document}

enter image description here

  • Thanks for those pointers. I realize that I might have tackled the problem from the other end, redefining @bibitem. Maybe that would work smoother. – bjoseru Nov 22 '14 at 23:20
  • @user805600 Your code redefines \@citex after babel has adapted it for its purposes, so undoing that change. But, as I said, it's not necessary to have a definition of \@citex, which is already provided in the kernel. – egreg Nov 22 '14 at 23:24
  • After more contemplation I came to realise that there is a wrapper in the original definition around the output. This wrapper is the same regardless of the presence of babel. So, instead of redefining \@citex, I redefine the wrapper: \def\@cite@ofmt#1{\def\@safe@activesfalse{}\hbox{\@Alph{#1}}} and suddenly everything works. I am not sure, however, that this won't break something else that I just haven't noticed yet. Where are these macros documented, anyways? – bjoseru Nov 24 '14 at 10:39
  • One more thing: The intention with the (re)definition of \section* and \bibsection was to prevent compile errors when the above code is used with other packages like natbib or babel. I wanted to put the above code into an LCO file for as generic a use as possible and have updated the gist with a working version of such an LCO file. The redefinitions are left in place for use with natbib. – bjoseru Nov 24 '14 at 11:31
  • @user805600 You need to look at the LaTeX kernel, babel and natbib (but also hyperref): not really easy. I'd be wary of doing \def\section*#1{} which is not relevant if already \bibsection is defined to do nothing. – egreg Nov 24 '14 at 12:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.