22

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}

enter image description here

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}

enter image description here

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}

enter image description here

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}
29

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}

Result

  • 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! – jub0bs Feb 20 '14 at 21:45
  • 1
    It's great, but it's the answer to the wrong question. What is needed is simply for lstlisting to adopt the current font size, period. Always. – Peter Flynn Jan 26 '17 at 15:59
  • @HeikoOberdiek, I posted as an answer a fleshed out example showing that the power of your answer goes beyond your claim and your example, just to clarify this point for other readers. (You only have one non-display sample, so it's not clear that the font size would adjust to other context, such as a title, section heading, or text of a different arbitrary size.) – Jim Ratliff Aug 30 '18 at 22:11
0

@HeikoOberdiek's explanation to his answer above undersells its power and indeed, based solely on his explanation, you wouldn't think that his answer fully solved the OP's problem (as one commenter objected).

Heiko's claim is only that he provided a method to "to set a different font size in inline and displayed code listings." But what the OP wanted was that \lstinline would inherit the font size of the surrounding text. Heiko's solution does do that, though it won't be clear to readers that it does.

For that reason, I just want to provide an example showing that indeed, with Heiko's solution, the \lstinline font size does grow and shrink to adjust to the surrounding text. (If Heiko would like to add a similar example to his answer, I'd gladly delete this one.)

I add a \texttt{foo} directly after each \lstinline|foo| just to facilitate a comparison of the heights of the two foos.

enter image description here

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

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

\lstset{style=mystyle}

\begin{document}
\title{Here is a title with \lstinline|foo| \texttt{foo}.}
\date{}
\maketitle
\section{Here is a section heading with \lstinline|foo| \texttt{foo}.}
\Large
Here is: \lstinline|foo| \texttt{foo}.\\
\Huge
Here is: \lstinline|foo| \texttt{foo}.\\
\begin{lstlisting}
Some code with foo.
\end{lstlisting}
\end{document}

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.