在以下 MWE 中(它很小,因此不是原始问题)。您可以检查,两边都有一个空格\mycommand
。当我将宏设置为“虚拟”以用于特定用途时:如果剩下两个空格,我可以删除其中一个空格吗?
\documentclass{article}
\DeclareRobustCommand\mycommand[1]{%
\textbf{#1}%
}
\makeatletter
\newcommand\nobf[1]{%
{\def\mycommand##1{}#1}}
\makeatother
\begin{document}
\def\abc{X \mycommand{Y} Z \mycommand{!}}
\abc
\nobf{\abc}
X Z
\abc
\end{document}
第一个对之间有两个空格X
Z
:
答案1
空格的原因来自于宏定义中的虚假空格:换行符没有 %
作用类似于空格。有关此讨论的更多信息,请参阅百分号 (%
行末。
一个更简短的定义\nobf
是
\newcommand\nobf[1]{{\renewcommand{\mycommand}[1]{\leavevmode\unskip\ignorespaces}#1}}
请注意,没有换行符,因此宏不会在输出中引入任何虚假空格。此外,重新定义\mycommand
是在组内完成的,因此无需保存和恢复宏。重新定义会删除它之前的任何跳过(via \unskip
)并忽略任何后续的跳过(via \ignorespaces
)。
\documentclass{article}
\DeclareRobustCommand\mycommand[1]{\textbf{#1}}
\makeatletter
\newcommand\nobf[1]{{\renewcommand{\mycommand}[1]{\leavevmode\unskip\ignorespaces}#1}}
\makeatother
\begin{document}
\def\abc{X \mycommand{Y} Z \mycommand{!}}
\abc
\nobf{\abc}
X Z
\abc
\end{document}
答案2
在 latex 内部代码中,任何可以在段落中使用但不提供可见文本的命令都使用两个内部命令:\@bsphack
和@esphack
。第一个命令尝试检测其前面是否有空格,并将该信息传递给第二个命令。如果存在空格,则会发出\@esphack
。\ignorespaces
因此:
\documentclass{article}
\DeclareRobustCommand\mycommand[1]{%
\textbf{#1}}
\makeatletter
\newcommand\nobf[1]{% Use the "space hack"
{\def\mycommand##1{\@bsphack\@esphack}#1}}
\makeatother
\begin{document}
\def\abc{X \mycommand{Y} Z}
\abc
\nobf{\abc}
\def\abc{X\mycommand{Y} Z}
\abc
\nobf{\abc}
\def\abc{X \mycommand{Y}Z}
\abc
\nobf{\abc}
\end{document}
实际上,在这个受限的应用程序中,不需要任何内部命令。 \def\mycommand##1{\@bsphack\@esphack}
可以使用
\def\mycommand##1{\ifdim\lastskip>0pt \ignorespaces\fi}