使用 \ifmtarg 会产生虚假空格

使用 \ifmtarg 会产生虚假空格

我似乎从 中得到了一个虚假的空间\@ifmtarg。下面的 MWE 产生了左侧的图像,其中在 的结尾之前有一个虚假的空间hyperref(对于最后两种情况)。但是,如果我添加一个\unskiphack,我就会在右侧获得所需的结果。

在此处输入图片描述 在此处输入图片描述

笔记:

  • 一个简单的用例\@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所有东西都到前Q3 个
  • #3Q3
  • #4\@secondoftwo
  • #5\@firstoftwo(一切取决于\@nil)。

因此下一个扩展是

\@secondoftwo{E}{N}

返回N。如果 的参数\@ifmtarg是任何空格序列,它们将被吞噬,因为 TeX 在寻找未分隔的参数时会忽略空格标记。因此,使用 ,\@ifmtarg{}{E}{N}我们将得到

  • #1Q3(第一个非空格标记)
  • #2是空的(#2一切都取决于接下来的前Q3
  • #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

相关内容