![数学模式下的 lstinline 具有正确的字体大小](https://linux22.com/image/456089/%E6%95%B0%E5%AD%A6%E6%A8%A1%E5%BC%8F%E4%B8%8B%E7%9A%84%20lstinline%20%E5%85%B7%E6%9C%89%E6%AD%A3%E7%A1%AE%E7%9A%84%E5%AD%97%E4%BD%93%E5%A4%A7%E5%B0%8F.png)
我经常排版有关计算机程序的数学公式(循环不变量等)。
我用打字机字体排版它们,在我的序言中说\lstset{basicstyle=\ttfamily}
。
我可以说
$\frac{\text{\lstinline£x£}}2$
但这很麻烦。我想输入
$\frac{\lstinline£x£}2$
因此,以类似的方式那个答案,我创建了一个数学模式版本\lstinline
并使用它\ifmmode
来选择适当的变体(请参阅末尾的 MWE):
\newcommand\lstinlinemm[1][]{%
\hbox\bgroup % the \hbox is new
\def\lst@boxpos{b}%
\lsthk@PreSet\lstset{flexiblecolumns,#1}%
\lsthk@TextStyle
\lstinline@}
但是,在排版时(例如分数),这不能适当地缩放字体大小。
\hbox
用amstext
(\text@
的数学模式版本)替换\text
会导致代码在数学模式而不是文本模式下排版,并且我不清楚其中的原因。这是一个问题,因为它会导致\ttfamily
与数学模式不可用相关的错误。
一个有趣的答案告诉我使用\mathchoice
比我想象的要复杂,因为每个尺寸版本都是排版的,因为 TeX 事先不知道是否需要常规或 scriptsize 变体。
所以这意味着移动逐字的代码片段,据我所知这不是一件小事。
看起来 Lua 可以与 LuaTeX 的输入处理进行交互。这个答案引用process_input_buffer
回调将逐字文本存储到 lua 变量中,然后使用它。但是,我理解它是逐行工作的,因此不适用于我的情况,因为我当然不想在公式中的 tex 源中换行。
答案中引用了 Paul Isambert 的文章还给出了一个使用回调的示例token_filter
。我认为这也可以用来将代码片段吞噬到 lua 变量中,然后将其提供给\text
。然而,token_filter
不复存在自 2016 年起。
MWE 如下:
\documentclass{standalone}
\usepackage{amsmath,listings}
\lstset{basicstyle=\ttfamily}
\makeatletter
\newcommand\lstinlinemm[1][]{%
\hbox\bgroup
\def\lst@boxpos{b}%
\lsthk@PreSet\lstset{flexiblecolumns,#1}%
\lsthk@TextStyle
\lstinline@}
% On renomme le lstinline d'origine
\let\lstinlinetm\lstinline %%
% On met en place la sélection de la bonne version selon le mode actif
\DeclareRobustCommand\lstinline{\ifmmode\let\nextlstinline\lstinlinemm\else\let\nextlstinline\lstinlinetm\fi\nextlstinline}
\newcommand\£{\lstinline£} %£
\begin{document}
$\frac{\£x£}2$ $\frac{\text{\£x£}}2$
\end{document}
答案1
首先,请注意命令参数中的“逐字”通常不会“真正”起作用,即使有时看起来有效。
引用文档
5.1 参数内的列表
如果您想在参数中使用 \lstinline 或列表环境,则需要考虑一些事项。由于 TeX 在执行“lst- 宏”之前读取参数,因此此包无法执行任何操作来保存输入:空格缩小为一个空格,制表符和行尾转换为空格,TeX 的注释字符不可打印,等等。因此,您必须多做一些工作。您必须在以下四个字符前面分别加上反斜杠:
\{}%
。此外,如果 (i) 两个或多个空格彼此相连,或 (ii) 空格是行中的第一个字符,则必须以相同的方式保护空格。这还不够:每行都必须以“换行符”^^J 结束。并且您无法在这样的列表中退出到 LaTeX!
其次,如果您知道 TeX 内部的工作原理,您就会发现,为了使文本大小在最低级别的数学模式下正确,需要对每个数学模式执行内容 4 次。
无论哪种方式,在这种情况下您都需要一些深层的lstinline
代码补丁。
代码lstinline
相当复杂,理论上最好的修补方法是
- 首先设置 catcode,
- 然后收集参数,
- 然后进行设置(例如包括
\ttfamily
在这种情况下) - 然后将所有内容排版。
我还没有弄清楚里面的代码是如何\lst@Init
工作以分离 set-catcode 部分和 font-init 等部分的,所以我只是这样做。
%! TEX program = lualatex
\documentclass{article}
\usepackage{amsmath}
\usepackage{listings}
\begin{document}
\makeatletter
\def\lstinline@#1{%
%\lst@Init\relax % originally this was included, we move it to later
\lst@IfNextCharActive{\lst@InlineM#1}{\lst@InlineJ#1}% original definition, we don't handle M case
%\lst@InlineJ#1%
}
\def\lst@InlineJ#1{%
\def\lst@temp##1#1{%
\text{% ← this is added around
\lst@Init\relax % the init is moved to here
\let\lst@arg\@empty \lst@InsideConvert{##1}%
\lst@arg
\lst@DeInit
}% ← we end up doing the init 4 times
\egroup}%
\lst@temp}
\makeatother
\lstset{basicstyle=\ttfamily}
Issue: this will disable the verbatim capturing mode e.g.
\lstinline+123 4 56+ does not preserve the double-space.
But otherwise it works.
\[
\lstinline+123+\frac{\lstinline+123+^{\lstinline+123+_{\lstinline+123+}}}{2}
\]
\end{document}
答案2
@user202729 的解决方案符合我的需要,但有两处修改:
- 我只会在数学模式下使用它,
\lstinline
在文本模式下保留原来的 - 为了使
%
正常\
工作并允许不平衡的{
结束}
,我将它们的 catcode 设置为 12。我们可以通过将 的 catcode也设置为 12 来避免连续空间的崩溃。然而,我并不知道这会带来什么意外的副作用。据推测这可能会干扰对
listings
这些字符的处理,但就我而言,我无论如何都不想让它对它们做任何事情,所以……
我也没有尝试去处理\lstinline{code}
,在我看来这是没用的。
\newcommand\lstinlinemm[1][]{%
\bgroup
\def\lst@boxpos{b}%
\lsthk@PreSet\lstset{flexiblecolumns,#1}%
\lsthk@TextStyle
\lstinline@math}
\def\lstinline@math#1{%
\begingroup
\catcode`\%=12
\catcode`\{=12
\catcode`\}=12
\catcode`\\=12
\def\lst@temp##1#1{%
\text{% ← this is added around
\lst@Init\relax % the init is moved to here
\let\lst@arg\@empty \lst@InsideConvert{##1}%
\lst@arg
\lst@DeInit
}% ← we end up doing the init 4 times
\endgroup\egroup}%
\lst@temp}
% On renomme le lstinline d'origine
\let\lstinlinetm\lstinline %%
% On met en place la sélection de la bonne version selon le mode actif
\DeclareRobustCommand\lstinline{\ifmmode\let\nextlstinline\lstinlinemm\else\let\nextlstinline\lstinlinetm\fi\nextlstinline}