我似乎从 中得到了一个虚假的空间\@ifmtarg
。下面的 MWE 产生了左侧的图像,其中在 的结尾之前有一个虚假的空间hyperref
(对于最后两种情况)。但是,如果我添加一个\unskip
hack,我就会在右侧获得所需的结果。
笔记:
- 一个简单的用例
\@ifmtarg
没有为我重现这个问题,所以也许这与我的使用方式有关。 - 下面的 MWE 会引发一些 WTF 问题,比如我为什么要使用,
\renewcommand
但这是我的实际用例的一个大大简化的版本,可能需要大量代码清理。但就目前而言,这是我拥有的结构。
参考:
代码:
\documentclass{article}
\usepackage{ifmtarg}
\usepackage{xcolor}
\usepackage{hyperref}
\makeatletter
\newcommand{\IfIsEmptyArg}[3]{\@ifmtarg{#1}{#2}{#3}}
\makeatother
\newcommand{\SetTitle}[1]{}
\newcommand{\ExtractAndSetTitle}[2]{%
% #1 = macro csname in which the result is stored
% #2 = text of title witout symbol
\renewcommand{\SetTitle}[1]{%
%\latexglobal\expandafter\renewcommand\csname #1\endcsname{%
% Simplify above for this MWE.
\expandafter\gdef\csname #1\endcsname{%
##1%
\IfIsEmptyArg{\Symbol}{}{~\Symbol}%
%\unskip% Hack!!!!
}%
}%
\SetTitle{#2}%
}%
\begin{document}
\def\Symbol{$\times$}% This works
\ExtractAndSetTitle{ExtractedTitle}{Times}%
\href{some.pdf}{\ExtractedTitle}%
\def\Symbol{\empty}% This requires \unskip HACK
\ExtractAndSetTitle{ExtractedTitle}{Times}%
\href{some.pdf}{\ExtractedTitle}%
\def\Symbol{}% This requires \unskip HACK
\ExtractAndSetTitle{ExtractedTitle}{Times}%
\href{some.pdf}{\ExtractedTitle}%
\end{document}
答案1
你是使用\@ifmtarg
不正确。下面是一个简短的示例,显示了您的错误用法:
\documentclass{article}
\usepackage{ifmtarg}% http://ctan.org/pkg/ifmtarg
\begin{document}
\makeatletter
Test 1: \@ifmtarg{}{YES}{NO} \par
Test 2: \@ifmtarg{ }{YES}{NO} \par
Test 3: \@ifmtarg{\empty}{YES}{NO} \par
Test 4: \@ifmtarg{\relax}{YES}{NO} \par
Test 5: \@ifmtarg{\@empty}{YES}{NO}
\end{document}
从上面的\empty
、\relax
和\@empty
可以看出, 都被认为不为空。当然,你也可以使用另一种方法,比如将其放在一个盒子里,然后测试它的宽度是否非零:
\documentclass{article}
\makeatletter
\newcommand{\@ifmtarg}[1]
{\setbox1=\hbox{\ignorespaces#1}\ifdim\wd1>\z@\expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi}
\makeatother
\begin{document}
\makeatletter
Test 1: \@ifmtarg{}{YES}{NO} \par
Test 2: \@ifmtarg{ }{YES}{NO} \par
Test 3: \@ifmtarg{\empty}{YES}{NO} \par
Test 4: \@ifmtarg{\relax}{YES}{NO} \par
Test 5: \@ifmtarg{\@empty}{YES}{NO}
\end{document}
我想这取决于您的用例。如果您没有任何特殊要求,只是想测试所提供的内容是否为空,那么上述方法应该有效。
答案2
\@ifmtarg
仅将由零个或多个空格组成的参数视为空。 在您的例子中,参数始终为\Symbol
,这肯定不是空的。
让我们看看\@ifmtarg{\Symbol}{E}{N}
会发生什么。这是的定义\@ifmtarg
:
\begingroup
\catcode`\Q=3
\long\gdef\@ifmtarg#1{\@xifmtarg#1QQ\@secondoftwo\@firstoftwo\@nil}
\long\gdef\@xifmtarg#1#2Q#3#4#5\@nil{#4}
\endgroup
第一个扩展
\@xifmtarg\SymbolQQ\@secondoftwo\@firstoftwo\@nil{E}{N}
因此,支持的论点\@xifmtarg
是:
#1
是\Symbol
(#1
未分隔)#2
是空的(#2
所有东西都到前Q
3 个#3
是Q
3#4
是\@secondoftwo
#5
是\@firstoftwo
(一切取决于\@nil
)。
因此下一个扩展是
\@secondoftwo{E}{N}
返回N
。如果 的参数\@ifmtarg
是任何空格序列,它们将被吞噬,因为 TeX 在寻找未分隔的参数时会忽略空格标记。因此,使用 ,\@ifmtarg{}{E}{N}
我们将得到
#1
是Q
3(第一个非空格标记)#2
是空的(#2
一切都取决于接下来的前Q
3#3
是\@secondoftwo
#4
是\@firstoftwo
#5
为空 (直到 为止的所有内容\@nil
)。
这样下一步就是\@firstoftwo{E}{N}
然后E
。
你可能想要
\makeatletter
\newcommand{\IfIsEmptyArg}[3]{%
\expandafter\@ifmtarg\expandafter{#1}{#2}{#3}
}
\makeatother
因此,您要查看 的扩展,\Symbol
而不是的扩展\Symbol
。当然,使用\def\Symbol{\empty}
,将遵循“非空”分支。
答案3
问题是,\@ifmtarg
评估结果\Symbol
不为空,可能是因为它没有扩展它。我不知道是否应该这样做。
下面的代码显示了正在发生的事情:
\documentclass{article}
\usepackage{ifmtarg}
\begin{document}
\def\Symbol{}
\makeatletter
\@ifmtarg{\Symbol}{\tt\string\Symbol{} is empty}{\tt\string\Symbol{} is not empty}%
\makeatother
\end{document}
结果是:
\符号不为空
从那里,您的代码输出~\Symbol
,导致由于而出现空白~
。
如果一次扩展\Symbol
就足够了(即\Symbol
直接扩展到其内容,而不是其他宏/命令,它们本身可能会扩展为空字符串),那么以下测试就可以\expandafter
起作用:
\expandafter\@ifmtarg\expandafter{\Symbol}{...}{...}%
处理更多扩展的一种可能方法是将其完全扩展\Symbol
(使用\edef
)为一个临时变量,比如说\SymbolExpanded
,然后对运行上述测试\SymbolExpanded
。