我正在尝试定义一个简写命令,以便更快地编写一些引用。到目前为止,我能做的最好的事情是
\newcommand{\apologien}[2]{#1\textit{A} #2}
\newcommand{\apo}[1]{\apologien{1}{#1}}
\newcommand{\apoz}[1]{\apologien{2}{#1}}
例如,它很适合\apo{65.1}
。但是,如果要引用整个文本而不仅仅是特定的章节或诗句,我会使用例如\apo
。这会给我留下一个不必要的尾随空格。
除此以外,我还尝试了以下方法:
\usepackage{xparse}
\DeclareDocumentCommand{\apologien}{mo}
{%
#1\textit{A}\IfValueT{#2}{ {#2}}
}
或者
\usepackage{ifthen}
\newcommand{\apologien}[2]{#1\textit{A}\ifthenelse{\isundefined{#2}}{}{ #2}}
或者
\usepackage{ifthen}
\newcommand{\apologien}[2][]{#1\textit{A}\ifthenelse{\equal{#2}{}}{}{ #2}}
我终于让它为 \apo{} 工作了
\usepackage{trimspaces}
\makeatletter
\newcommand{\apologien}[2]{\trim@spaces{#1\textit{A} #2}}
\makeatother
不过,我真的很想知道为什么我的其他尝试没有成功。
示例文档:
%!TEX TS-program = xelatex
%!TEX encoding = UTF-8 Unicode
\documentclass[
fontsize=12pt,
paper=a4,
titlepage,
twoside,
]{scrartcl}
\usepackage{trimspaces}
\makeatletter
\newcommand{\apologien}[2]{\trim@spaces{#1\textit{A} #2}}
\makeatother
\newcommand{\apo}[1]{\apologien{1}{#1}}
\newcommand{\apoz}[1]{\apologien{2}{#1}}
\begin{document}
\begin{tabular}{ll}
\hline
Commmand & Wanted\\
\hline
\apologien{1}. & 1\textit{A}.\\
\apologien{1}{}. & 1\textit{A}.\\
\apologien{1}{65.1}. & 1\textit{A} 65.1.\\
\apo{65.1}. & 1\textit{A} 65.1.\\
\apo. & 1\textit{A}.\\
\apo{}. & 1\textit{A}.\\
\apoz{5.1}. & 2\textit{A} 5.1\\
\hline
\end{tabular}
\end{document}
答案1
我认为您的问题是,当您重写宏以便它们使用可选参数时,您并没有更改宏,因此它们使用了可选参数。
更明确地说,如果你定义
\usepackage{xparse}
\DeclareDocumentCommand{\apologien}{mo}
{%
#1\textit{A}\IfValueT{#2}{ {#2}}
}
那么您必须使用可选参数,以便和\apologien
的定义也必须更改为\apo
\apoz
\newcommand{\apo}[1]{\apologien{1}[#1}]}
\newcommand{\apoz}[1]{\apologien{2}[#1]}
实际上,您在“现在正在工作的” MWE 中也遇到了类似的问题,因为您使用了\apo.
和\apo{}
。其中第一个扩展为\apologien{1}{.}
,第二个扩展为\apologien{1}{}
,因此您可能偶然得到了想要的结果。如果您希望此语法起作用,那么\apo
和\apoz
还必须接受可选参数。
据我所知,你不需要使用修剪空间包并可以改用:
\documentclass[
fontsize=12pt,
paper=a4,
titlepage,
twoside,
]{scrartcl}
\usepackage{xparse}
\NewDocumentCommand\apologien{ mo }{#1\textit{A}\IfValueT{#2}{\space #2}}
\NewDocumentCommand{\apo}{o}{\IfValueTF{#1}{\apologien{1}[#1]}{\apologien{1}}}
\NewDocumentCommand{\apoz}{o}{\IfValueTF{#1}{\apologien{2}[#1]}{\apologien{1}}}
\begin{document}
\begin{tabular}{ll}
\hline
Commmand & Wanted\\
\hline
\apologien{1}. & 1\textit{A}.\\
\apologien{1}{}. & 1\textit{A}.\\
\apologien{1}[65.1]. & 1\textit{A} 65.1.\\
\apo[65.1]. & 1\textit{A} 65.1.\\
\apo. & 1\textit{A}.\\
\apo{}. & 1\textit{A}.\\
\apoz[5.1]. & 2\textit{A} 5.1\\
\hline
\end{tabular}
\end{document}
当然,这会产生您预期的输出:
但请注意,当需要可选参数时,您需要使用它们!
最后一条评论:LaTeX 中的通常做法是将可选参数放在首位。当然,你不需要这样做,但至少对我来说,这样写更自然:
\NewDocumentCommand\apologien{ om }{#2\textit{A}\IfValueT{#1}{\space #1}}
\NewDocumentCommand{\apo}{o}{\IfValueTF{#1}{\apologien[#1]{1}}{\apologien{1}}}
\NewDocumentCommand{\apoz}{o}{\IfValueTF{#1}{\apologien[#1]{2}}{\apologien{1}}}
答案2
你特别需要区分 和\apo{something}
,\apo
其中{
不 跟在后面。然后\futurelet
需要使用 TeX 原语:
\def\apo {1{\it A}\futurelet\next\apoA}
\def\apoz {2{\it A}\futurelet\next\apoA}
\def\apoA{\ifx\next\bgroup \space \fi}
Test:
\apo {65.1}, \apo.
\apoz {65.1}, \apoz.
\bye
答案3
分析
让我们考虑一下代码
\newcommand{\apologien}[2]{#1\textit{A} #2}
\newcommand{\apo}[1]{\apologien{1}{#1}}
\newcommand{\apoz}[1]{\apologien{2}{#1}}
如果你在示例中调用\apo.
或类似,则参数在前一种情况下是句点,在后一种情况下是空,从而导致\apo{}.
#1
\apologien{1}{.}
\apologien{1}{}.
在这两种情况下,你最终都会得到
1\textit{A} .
建议的解决方案
由于章节部分似乎是可选的,因此这样处理是有意义的:
\NewDocumentCommand{\apologien}{mo}{%
#1\textit{A}%
\IfValueT{#2}{~#2}%
}
\NewDocumentCommand{\apo}{}{\apologien{1}}
\NewDocumentCommand{\apoz}{}{\apologien{2}}
你应该调用如下命令
\apologien{1}.
\apologien{1}[65.1].
\apo[65.1].
\apo.
\apoz[5.1].
语法一致。即使你使用\apo{}
(可能是为了保护后面的空格),结果也会如指定的那样。
替代(但不推荐)解决方案
只是为了完整性,但这是一个我完全不推荐的方法,你可以做
\NewDocumentCommand{\apologien}{mg}{%
#1\textit{A}%
\IfValueT{#2}{~#2}%
}
\NewDocumentCommand{\apo}{}{\apologien{1}}
\NewDocumentCommand{\apoz}{}{\apologien{2}}
并将上述代码中[...]
的括号改为。然而,这仍然会导致不必要的空格,并且还需要做更多的工作{...}
\apo{}
\ExplSyntaxOn
\NewDocumentCommand{\apologien}{mg}
{
#1\textit{A}
\IfValueT { #2 } { \tl_if_blank:nF { #2 } { \nobreakspace #2 } }
}
\ExplSyntaxOff