我想编写一个 LaTeX3 函数,它接受一个类型为 LaTeX3 字符串的\f
参数,并打印#1
你好,#1!
第一次尝试是
\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\cs_new:Nn \f:n {Hello, #1}
\cs_gset_eq:NN \f \f:n
\ExplSyntaxOff
\begin{document}
\f {world!}
\end{document}
此排版
你好世界!
请注意,逗号和后面的单词之间没有空格。这是因为宏\ExplSyntaxOn
更改了空格字符的类别代码,使其被忽略。(\ExplSyntaxOff
宏会撤消此效果。)
可以通过使用波浪符号 (~) 代替\ExplSyntaxOn
和之间的空格字符来轻松解决这个问题\ExplSyntaxOff
,因此:
...
\cs_new:Nn \f:n {Hello,~#1}
...
现在文档排版
你好世界!
如预期的。
这解决了这个简单、人为的案例中的问题。然而,当将此示例推广到创建参数化文本模板的问题时,解决方案就失效了,因为在长文本中用波浪号替换每个空格很不方便,此外,通过简单地复制粘贴来从文档正文中自然出现的文本创建模板也非常麻烦。
例如,我有一份文档,其中包含许多类似的数学概念定义,其中一个例子是
\begin{definition}[Doubling]
Let $S$ be a type.
We denote with \dbl the \emph{doubling} function $\dbl:S \rightarrow S\times S$,
which to every $s:S$, assigns $(s,s)$.
(Hacker's note: you can use the TeX macro named "dbl"
to generate this function's symbol.)
\end{definition}
我想通过参数化定义术语的名称(Doubling
在本例中)、用于排版表示定义术语的符号的宏(\dbl
在本例中)以及术语的定义公式((s,s)
在本例中)来根据此示例定义创建一个模板。换句话说,我希望能够通过以下方式排版上述定义:
\MyDef {Doubling} \dbl {(s,s)}
然后创建另一个类似的定义,方法是:
\MyDef {Starring} \star {s*}
那么,我是否应该将定义文本中的每个空格字符替换为波浪号?假设我这样做了。如果我以后想在文档正文中使用定义中的一个句子怎么办?我是否需要将复制的句子中的所有波浪号改回空格?
答案1
只需将代码分成两部分即可。另一方面,我认为这是产生枯燥文本的秘诀。
\documentclass{article}
\usepackage{xparse}
\usepackage{amsmath,amsthm}
\theoremstyle{definition}
\newtheorem{definition}{Definition}
% the text
\NewDocumentCommand{\definitiontext}{mmmm}{%
\begin{definition}[#1]
Let $S$ be a type.
We denote with $#2$ the \emph{\ExpLowercase{#1}} function
$#2\colon S\rightarrow #3$,
which to every $s:S$, assigns $#4$.
(Hacker's note: you can use the \TeX\ macro \texttt{\ExpString#2}
to generate this function's symbol.)
\end{definition}
}
\ExplSyntaxOn
\cs_set_eq:NN \ExpLowercase \tl_lower_case:n
\cs_set_eq:NN \ExpString \token_to_str:N
\NewDocumentCommand{\MyDef}{mmmm}
{
\cs_new:Npx #2
{
\exp_not:N\mathrm{\cs_to_str:N #2}
}
\definitiontext{#1}{#2}{#3}{#4}
}
\ExplSyntaxOff
\begin{document}
\MyDef{Doubling}{\dbl}{S\times S}{(s,s)}
\MyDef{Star}{\sstar}{S}{s^*}
\end{document}
(抱歉,我无法满足您对重新定义现有命令而不发出警告的要求。)
(图片稍后会添加,imgur 似乎拒绝了它们)
答案2
您可以使用~
,但如果有较长的文档级字符串,则表明该命令位于文档级界面中,而不是 expl3 代码层中,因此您可以在 expl3 代码约定块之外定义它,只要您确实公开了可以在该环境中调用的合适代码命令即可,例如
\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\cs_new:Nn \f:nn {#1#2}
\cs_gset_eq:NN \fnn \f:nn
\ExplSyntaxOff
\NewDocumentCommand\f{m}{\fnn{Hello }{#1}}
\begin{document}
\f {world!}
\end{document}
对于第二个例子,类似
\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\ExplSyntaxOff
\newtheorem{definition}{definition}
\def\dbl{\mathrm{DbL}}%?
\def\star{\mathrm{star}}%?
\NewDocumentCommand\mydef{mmm}{%
\begin{definition}[#1]
Let $S$ be a type.
We denote with \texttt{\string#2} the \emph{\lowercase{#1}} function $#2:S \rightarrow S\times S$,
which to every $s:S$, assigns $(s,s)$.
\end{definition}}
\begin{document}
\mydef {Doubling}\dbl{(s,s)}
\mydef {Starring} \star {s*}
\end{document}
答案3
基于egreg 的回答我创建了一个文件expl3x.tex
(文件名中的 extrax
代表“eX港口),其唯一目的是“出口”选择expl3
函数和变量,也就是说,以系统的方式重命名它们,以便它们可以在文档命令主体中使用。具体来说,重命名过程取消了下划线和冒号,这些符号经常用于数学写作(这是我最常使用 TeX 的写作类型),而是使用骆驼香烟盒与 & 符号串联。因此,例如, expl3 函数\cs_if_exist:NTF
被重命名为\CSIfExist@NTF
。
expl3x.tex
这是该文件的当前内容(根据需要进行了扩展):
\input expl3-generic
\ExplSyntaxOn
\makeatletter
\cs_new_eq:NN \CSIfExist@NTF \cs_if_exist:NTF
\cs_new_eq:NN \CSNewEq@NN \cs_new_eq:NN
\cs_new_eq:NN \CSSetEq@NN \cs_set_eq:NN
\cs_new_eq:NN \CSToStr@N \cs_to_str:N
\cs_new_eq:NN \GroupBegin@ \group_begin:
\cs_new_eq:NN \GroupEnd@ \group_end:
\cs_new_eq:NN \StrClearNew@N \str_clear_new:N
\cs_new_eq:NN \StrLowerCase@f \str_lower_case:f
\cs_new_eq:NN \StrSet@Nn \str_set:Nn
\cs_new_eq:NN \TLClearNew@N \tl_clear_new:N
\cs_new_eq:NN \TLSet@Nn \tl_set:Nn
\makeatother
\ExplSyntaxOff
然后我将其包含到我的主文档中,如下所示:
\documentclass{article}
\usepackage{xparse}
\input expl3x
\makeatletter
\NewDocumentCommand \MyCommand {m s}
{% I can use \CSIfExist@NTF, etc. here
}
\makeatother
\begin{document}
% I can use \MyCommand here
\end{document}
理想情况下,该文件expl3x.tex
应由 LaTeX3 项目提供,以便于使用和统一,并且列表始终是全面和最新的。它可以自动或半自动生成。
OP 的第二个例子现在可以进行如下编程。
\documentclass{article}
\usepackage{xparse}
\input expl3x
\makeatletter
\NewDocumentCommand \MyDef {m m m m}
{\begin{definition}[#1]
Let $S$ be a type.
We denote with #2 the \emph{\StrLowerCase@f{#1}} function $#2:S \rightarrow #4$,
which to every $s:S$, assigns $#3$.
(Hacker's note: you can use the TeX macro named "\CSToStr@N #2"
to generate this function's symbol.)
\end{definition}}
\makeatother
\NewDocumentCommand \Dbl {} {\ensuremath{\mathbf{D}}}
\NewDocumentCommand \Star {} {\ensuremath{\mathbf{S}}}
\newtheorem{definition}{Definition}
\begin{document}
\MyDef {Doubling} \Dbl {(s,s)} {S\times S}
\MyDef {Starring} \Star {(s,s,\dots)} {S^\aleph}
\end{document}
排版如下: