![执行 \def+asdf+{\texttt{#1}} 其中 + 可以使用宏设置](https://linux22.com/image/247692/%E6%89%A7%E8%A1%8C%20%5Cdef%2Basdf%2B%7B%5Ctexttt%7B%231%7D%7D%20%E5%85%B6%E4%B8%AD%20%2B%20%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E5%AE%8F%E8%AE%BE%E7%BD%AE.png)
这是我之前的问题。
在我之前的问题中,我学习了如何设置(比如说)+
一个“特殊字符”,以便我可以+asdf+
在我的文档中输入它并将其扩展为\texttt{asdf}
:
\documentclass{article}
\catcode`+=\active
\def+#1+{\texttt{#1}}
\begin{document}
+asdf+ % does \texttt{asdf}
\end{document}
我现在感兴趣的是定义一个命令\DefineShortTexttt{\+}
,将其设置+
为魔法字符。这就像\DefineShortVerb
在包中fancyvrb
或\MakeShortVerb
在包中一样shortvrb
。
本质上,我想要一个\DefineShortTexttt{SYMBOL}
能够实现 的东西\defSYMBOL#1SYMBOL{\texttt{#1}}
。
我刚刚了解了这个\lccode`~=`#1\lowercase{....}
技巧,因此我得到了一些类似这样的工作:
\documentclass{article}
\usepackage{xparse}
% make a command \ttt+asdf+ that does \texttt{asdf}, like \verb++ construct.
\NewDocumentCommand\ttt{v}{\texttt{#1}}
% make a command \DefineShortTexttt{<c>} such that <c>sometext<c
% is like typing \ttt<c>sometext<c>
\def\DefineShortTexttt#1{%
\begingroup%
\lccode`~=`#1%
\lowercase{%
\gdef~{\ttt~}
}%
\endgroup%
\catcode`#1=\active%
}
\begin{document}
\DefineShortTexttt{\|}
|asdf| % yay, it works!
\end{document}
现在,我大概明白了它的工作原理:我让~
为#1
,并基本上定义[DELIMITER]
为\ttt[DELIMITER]
。因此,当 tex 遇到 时,[DELIMITER]sometext[DELIMITER]
它会将第一个变成\ttt[DELIMITER]
,然后看起来像\ttt[DELIMITER]sometex[DELIMITER]
。真漂亮!
但请注意,我必须\ttt
在 的定义中使用 形式\DefineShortTexttt
?有什么方法可以代替吗\texttt{}
?
我尝试了一种变化,我将更\gdef~{\ttt~}
改为
\gdef~#1~{\texttt{#1}} % Use of [DELIMITER] doesn't match its definition
我认为这可能会起作用,因为我基本上想写\gdef~#1~{\texttt{#1}}
,其中~
包含当前分隔符,但它抱怨我对分隔符的使用与其定义不匹配。
我想我可能需要看看\expandafter
(???)但似乎无法使其工作 - 我可以得到任何指点吗?
(PS - 我知道这一切看起来有点琐碎 -\ttt+asdf+
写起来并不难,而且制作简写版本可能会导致其他问题,但这对我学习更高级的文本非常有用!另外,如果我可以开始\DefineShortTexttt
工作,我会在之后继续,但我想在问问题之前先好好尝试一下。到目前为止,\UndefineShortTexttt
我主要受到该包的来源的指导)。shortvrb
答案1
下面的操作应该可以工作。
\def\DefineShortTexttt#1{\begingroup\lccode`~=`#1\lowercase{\endgroup\def~##1~{\texttt{##1}}}\catcode`#1=\active}
它使用相同的小写技巧,请注意,在内部定义中,您需要将标记加倍#
。也就是说,\def\x#1#2{\def\y##1{##1#1}\y#2}
这是一种反转两个参数的愚蠢方法。它在内部创建一个\y
带有一个参数的宏。
\lowercase
关于and的用法\endgroup
以及它们出现的原因的一些附加解释。
首先,\endgroup
不能追踪 的使用~
,因为那会使 成为\def
本地的。但为什么会这样工作呢?为什么 的 不是本地\lccode
的~
,并且当 被发现时不再活跃\def
,这样它在组之外了,对吧?嗯,这是由于\lowercase
工作方式。\lowercase
所做的是将其参数列表中每个显式字符标记的字符代码替换为该字符标记的小写字符代码,同时保持该标记的类别代码不变(这对我们很重要,事实上,这也是我们使用这个技巧的原因)。它无需扩展即可完成此操作,也就是说,它\lowercase
是不可扩展的,并且在执行处理器中处理。这意味着 的字符代码~
被\def~##1~...
它的小写字符代码替换,我们将其设置为等于第一个参数的字符代码\DefineShortTexttt
(例如,假设该参数为+
)。但是字符的类别代码~
保持不变,因此它仍然处于活动状态(~
当然 是不可破坏的空间)。因此,在我们的定义中,我们最终得到了 的活动版本,+
并且当分组完成时, 的小写代码~
是否发生变化并不重要,因为该字符标记此时已被修改,并且 TeX 只会看到类别代码为 13(活动)的标记和 的字符代码+
,从而导致\def+#1#{\texttt{#1}}
。之后我们将 设置+
为活动,因为+
否则输入中的其他 不会具有类别代码 13。分组存在是因为否则 的小写代码~
将全局更改为 的字符代码+
,这是不可取的。