Масштабирование встроенного кода под текущий размер шрифта

Масштабирование встроенного кода под текущий размер шрифта

Редактировать: Даже не пытайтесь читать вопрос. Просто переходите сразу кОтвет Хайко Обердика :)

С listingsпакетом, набор листингов в некоторыхабсолютныйразмер шрифта очень прост; все, что вам нужно сделать, когда вы определяете свой стиль, это передать, возможно, вместе с другими макросами, объявление размера шрифта в ключ listings' basicstyle. Например:

\lstdefinestyle{mystyle}{basicstyle=\ttfamily\color{blue}\scriptsize}

Это нормально для отображаемого кода ( lstlistingокружения) и отдельных файлов ( \lstinputlisting). Однако вам редко захочетсявстроенный код( \lstinline) быть набранным в томабсолютныйразмер шрифта. Например, то, что происходит в следующем случае, вероятно, не то, что вам нужно:

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

введите описание изображения здесь

Упс... "foo" набрано в \scriptsize, в отличие от окружающего текста, который набран в \Large. Хотя вы хотите сохранить большую часть стиля (шрифт пишущей машинки и синий цвет, здесь), вы, вероятно, захотите, чтобы встроенный код переопределил спецификацию размера шрифта и был набран втекущий размер шрифта, верно?

Теперь, если вы просто попытаетесь передать \fontsize{\f@size}{\f@baselineskip}, basicstyleвас ждет разочарование:

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

введите описание изображения здесь

Можете достать носовой платок: вы только что перезаписали текущий базовый стиль, и в результате вы потеряли шрифт и цветовые характеристики пишущей машинки! Конечно, вы могли бы написать

\lstinline%
[basicstyle=\ttfamily\color{blue}\fontsize{\f@size}{\f@baselineskip}\selectfont]%
|foo|

Однако этот подход предполагает, что вы знаете исходное определение basicstyle(которое может быть спрятано глубоко внутри пакета, слишком глубоко для простых смертных), и является типичным примером дублирования кода, которого вы бы предпочли избежать.

Поэтому я придумал следующее решение, которое отлично работает:

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

введите описание изображения здесь

Пока все хорошо... Однако я столкнулся с проблемой, когда попытался адаптировать эту тактику к \lstMakeShortInline, listingsмакросу, который позволяет определить односимвольный разделитель для встроенного кода (я разместил соответствующие строки listings.dtxниже). А именно, из-за своеобразного способа \lstMakeShortInline@использования \lst@shortinlinedef, я не могу понять, где мне следует размещать команды группировки.

Будем признательны за любые рекомендации.

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

решение1

Пакет listingsимеет также хуки TextStyleи DisplayStyle/или переключатель \lst@ifdisplaystyle, которые можно использовать для установки разного размера шрифта во встроенных и отображаемых листингах кода, например:

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

Результат

решение2

Объяснение @HeikoOberdiekего ответвыше недооценивает его силу, и действительно, основываясь исключительно на его объяснении, вы не подумаете, что его ответ полностью решил проблему автора поста (как возразил один комментатор).

Heiko утверждает только то, что он предоставил метод для «установки другого размера шрифта в встроенных и отображаемых листингах кода». Но автор хотел, чтобы OP \lstinlineнаследовал размер шрифта окружающего текста. Решение Heiko делает это, хотя читателям это и не будет ясно.

По этой причине я просто хочу привести пример, показывающий, что, действительно, с решением Хайко \lstinlineразмер шрифта увеличивается и уменьшается, подстраиваясь под окружающий текст. (Если Хайко захочет добавить аналогичный пример к своему ответу, я с радостью удалю этот.)

Я добавляю a \texttt{foo}сразу после каждой \lstinline|foo|буквы, чтобы облегчить сравнение высоты двух fooбукв s.

введите описание изображения здесь

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

Связанный контент