# Scaling inline code to the current font size

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
%    \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}

-

Package listings has too hooks TextStyle and DisplayStyle or a switch \lst@ifdisplaystyle, which can be used for your purpose to set a different font size in inline and displayed code listings, e.g.:

\documentclass{article}
\usepackage{color}
\usepackage{listings}

\makeatletter
\lstdefinestyle{mystyle}{
basicstyle=%
\ttfamily
\color{blue}%
\lst@ifdisplaystyle\scriptsize\fi
}
\makeatother

\lstset{style=mystyle}

\begin{document}
\Large
\noindent
Here is a very important keyword: \lstinline|foo|.
\begin{lstlisting}
Some code with foo.
\end{lstlisting}
\end{document}


-
Aaahh that's great! I've started playing with listings' hooks, but I had overlooked those two and the \lst@ifdisplaystyle` switch. The solution ends up being so simple with them! Great thanks! –  Jubobs Feb 20 at 21:45