Edit: Don't even bother reading the question. Just jump straight to Heiko Oberdiek's answer :)
With the listings
package, typesetting listings in some absolute font size is very easy; all you have to do, when you define your style, is to pass, possibly along with other macros, a font-size declaration to listings
' basicstyle
key. For instance:
\lstdefinestyle{mystyle}{basicstyle=\ttfamily\color{blue}\scriptsize}
That's fine with displayed code (lstlisting
environments) and standalone files (\lstinputlisting
). However, you rarely want inline code (\lstinline
) to be typeset in that absolute font size. For instance, what happens in the following case is probably not what you want:
\documentclass{article}
\usepackage{xcolor}
\usepackage{listings}
\lstset{basicstyle=\ttfamily\color{blue}\scriptsize}
\begin{document}
\Large
Here is a very important keyword: \lstinline|foo|.
\end{document}
Oops... "foo" is typeset in \scriptsize
, unlike the surrounding text, which is typeset in \Large
. Although you want to retain most of the style (typewriter font and blue colour, here), you probably want the inline code to override the font-size specification and be typeset in the current font size, right?
Now, if you simply try to pass \fontsize{\f@size}{\f@baselineskip}
to basicstyle
, you're in for disappointment:
\documentclass{article}
\usepackage{xcolor}
\usepackage{listings}
\lstset{basicstyle=\ttfamily\color{blue}\scriptsize}
\begin{document}
\Large
Here is a very important keyword: \lstinline|foo|.
\makeatletter
Here is a very important keyword:
\lstinline[basicstyle=\fontsize{\f@size}{\f@baselineskip}\selectfont]|foo|.
\makeatother
\end{document}
You can whip out your handkerchief: you've just overwritten the current basic style, and as a result, you've lost typewriter font and colour specifications! You could of course write
\lstinline%
[basicstyle=\ttfamily\color{blue}\fontsize{\f@size}{\f@baselineskip}\selectfont]%
|foo|
but this approach assumes you know the original definition of basicstyle
(which may be buried deep inside a package, way too deep for mere mortals) and is a typical example of code duplication that you'd rather avoid.
So I came up with the following workaround, which works fine:
\documentclass{article}
\usepackage{xcolor}
\usepackage{listings}
\makeatletter
\newcommand\applyCurrentFontsize
{%
% we first save the current fontsize, baseline-skip,
% and listings' basicstyle
\let\f@sizeS@ved\f@size%
\let\f@baselineskipS@ved\f@baselineskip%
\let\basicstyleS@ved\lst@basicstyle%
% we now change the fontsize of listings' basicstyle
\renewcommand\lst@basicstyle%
{%
\basicstyleS@ved%
\fontsize{\f@sizeS@ved}{\f@baselineskipS@ved}%
\selectfont%
}%
}
\makeatother
\newcommand\scaledlstinline[2][]
{%
\bgroup%
\lstset{#1}%
\applyCurrentFontsize%
% ... possibly other macros whose effects should remain local ...
\lstinline|#2|%
\egroup%
}
\lstset{basicstyle=\ttfamily\color{blue}\scriptsize}
\begin{document}
\Large
Here is a very important keyword: \lstinline[]|foo|.
Here is a very important keyword: \scaledlstinline{foo}.
\end{document}
So far, so good... However, I run into trouble when I try to adapt this tactic to \lstMakeShortInline
, a listings
macro that allows you to define a one-character delimiter for inline code (I've post the relevant lines from listings.dtx
below). More specifically, because of the peculiar way \lstMakeShortInline@
uses \lst@shortinlinedef
, I can't figure out where I should put my grouping commands.
Any guidance would be appreciated.
\newcommand\lstMakeShortInline[1][]{%
\def\lst@shortinlinedef{\lstinline[#1]}%
\lstMakeShortInline@}%
\def\lstMakeShortInline@#1{%
\expandafter\ifx\csname lst@ShortInlineOldCatcode\string#1\endcsname\relax
\lst@shortlstinlineinfo{Made }{#1}%
\lst@add@special{#1}%
% \end{macrocode}
% The character's current catcode is stored in
% |\lst@ShortInlineOldCatcode\|\meta{c}.
% \begin{macrocode}
\expandafter
\xdef\csname lst@ShortInlineOldCatcode\string#1\endcsname{\the\catcode`#1}%
% \end{macrocode}
% The character is spliced into the definition using the same trick as
% used in |\verb| (for instance), having activated |~| in a group.
% \begin{macrocode}
\begingroup
\catcode`\~\active \lccode`\~`#1%
\lowercase{%
% \end{macrocode}
% The character's old meaning is recorded
% in |\lst@ShortInlineOldMeaning\|\meta{c} prior to assigning it a new one.
% \begin{macrocode}
\global\expandafter\let
\csname lst@ShortInlineOldMeaning\string#1\endcsname~%
\expandafter\gdef\expandafter~\expandafter{\lst@shortinlinedef#1}}%
\endgroup
% \end{macrocode}
% Finally the character is made active.
% \begin{macrocode}
\global\catcode`#1\active
% \end{macrocode}
% If we suspect that \meta{c} is already a short reference, we tell
% the user. Now he or she is responsible if anything goes wrong\,\dots
% (Change in \packagename{listings}: We give a proper error here.)
% \begin{macrocode}
\else
\PackageError{Listings}%
{\string\lstMakeShorterInline\ definitions cannot be nested}%
{Use \string\lstDeleteShortInline first.}%
{}%
\fi}