为什么下面的操作根本不起作用?
\documentclass{article}
\makeatletter
\newcommand{\foo}[1]{\@ifstar{\textbf{#1}}{\textit{#1}}}
\makeatother
\begin{document}
\foo{test}
\foo*{test}
\end{document}
输出似乎是“test”,对于非星号变体正确地以斜体形式书写,而对于星号变体则写为“*test”(“test”正常书写,没有粗体,“*”以斜体形式书写)。
答案1
原因是 with\foo*{test}
*
是 的参数\foo
,而{test}
只是组中的单词文本。\foo
必须是一个没有参数的宏,它调用另一个有参数的宏
\documentclass{article}
\makeatletter
\newcommand{\foo}{\@ifstar{\@foob}{\@fooi}}
\newcommand{\@foob}[1]{\textbf{#1}}
\newcommand{\@fooi}[1]{\textit{#1}}
\makeatother
\begin{document}
\foo{test}
\foo*{test}
\end{document}
答案2
宏\foo
定义时只有一个参数。如果以 来调用\foo*{test}
,则星号将成为参数 ( #1
);然后 \foo
被展开并被\@ifstar
调用。但后面的标记{
不是星号。然后,参数星号被设置为\textit{*}
。的处理\foo
已完成,{test}
并被解释为包含单词test
inside 的组。
该示例可以通过以下方式修复:
\documentclass{article}
\makeatletter
\newcommand*{\foo}{\@ifstar\textbf\textit}
\makeatother
\begin{document}
\foo{test}
\foo*{test}
\end{document}
宏\foo
定义时不带参数,因此\@ifstar
可以查找后面的星号。然后代码中的“带星号”和“不带星号”的参数都会\@ifstar
读取后面的参数。
如果论证中的代码\@ifstar
更复杂,那么更一般的回答迈克的帮助。
答案3
在您的定义中,在 \@ifstar 出现之前,参数已经被读取。因此,您必须将星号放在参数后面(请注意,它会占用一个空格::
\documentclass{article}
\makeatletter
\newcommand{\foo}[1]{\@ifstar{\textbf{#1}}{\textit{#1}}}
\makeatother
\begin{document}
\foo{test}
\foo{test}*
\end{document}
但你想要的可能是这样的:
\documentclass{article}
\makeatletter
\newcommand{\foo}{\@ifstar\textbf\textit}
\makeatother
\begin{document}
\foo{test}
\foo*{test}
\end{document}
答案4
其内容如下xparse
:
\usepackage{xparse}
\NewDocumentCommand\foo{sm}{\IfBooleanTF{#1}{\textbf{#2}}{\textit{#2}}}