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}
bjoseru
  • 133

1 Answers1

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

egreg
  • 1,121,712
  • 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