在 \newcommand 的输出中使用 \MakeUppercase

在 \newcommand 的输出中使用 \MakeUppercase

考虑这个例子:

\documentclass{article}
\usepackage{ifthen}
\newcommand{\deftitle}[1]{%                                                                                                                                                                                 
\ifthenelse{\equal{#1}{Aa}}{aaa}{}%                                                                                                                                                                         
\ifthenelse{\equal{#1}{Bb}}{bbb}{}%                                                                                                                                                                         
}%                                                                                                                                                                                                          

\begin{document}
\MakeUppercase sffdfd

\MakeUppercase \deftitle{Aa}
\end{document}

虽然\MakeUppercase sffdfd运行完美,但\MakeUppercase \deftitle{Aa}结果却出错。如何应用于\MakeUppercase的输出\newcommand

答案1

您的设置失败,因为\MakeUppercase将抓取一个参数,如果您不使用括号,这将是它看到的第一个标记。代码中的第一个标记是\deftitle。下一步\MakeUppercase尝试尽可能扩展其参数,但由于它是在没有参数的情况下被抓取的,因此\deftitle这将失败!正确的方法是先\deftitle用其参数进行扩展,然后应用于\MakeUppercase由此产生的第一个字符。如果不更改您的设置,则无法完成此操作。

以下假设您\deftitle实际上可以完全扩展工作(这对于您的 MWE 来说是正确的)。


此处的代码可能非常不稳定,具体取决于输入(非常适合\deftitle生成 ASCII 输出)。请参阅下文以了解更好的方法。

由于\ifthenelse不可扩展,您无法直接使用它来产生所需的结果。因此,下面定义了两个测试(这样做而不是加载定义所有测试的包,仅用于教育目的)。

第一个测试是针对空参数 ( ) 的测试\myifempty。它的工作原理是首先将参数转换为字符串,然后\relax使用进行比较\if。如果参数不为空,\relax将与 other 类别的字符进行比较,因此结果为 false。如果它为空,\relax将与第二个进行比较\relax,结果为 true。

第二个测试比较两个字符串(\myifeq),如果它们确实相同,则结果为 true。为此,我使用该包在未内置宏的引擎中pdftexcmds获取宏。\pdf@strcmp

接下来我们需要一个宏,它在将输入交给之前将其完全展开\MakeUppercase。为此,我使用\edef扩展并使用检查结果是否为空\ifx\mytmp\@empty。之后\MakeUppercase获取完全展开的第一个标记\mytmp作为其参数。

\documentclass[]{article}

\usepackage{pdftexcmds}

\makeatletter
\newcommand\myifempty[1]
  {%
    \if\relax\detokenize{#1}\relax
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
  }
\newcommand\myifeq[2]
  {%
    \ifnum\pdf@strcmp{\detokenize{#1}}{\detokenize{#2}}=0
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
  }
\newcommand\ExpandAndUppercaseFirst[1]
  {%
    \begingroup
      \edef\mytmp{#1}%
      \unless\ifx\mytmp\@empty
        \expandafter\MakeUppercase\mytmp
      \fi
    \endgroup
  }
\makeatletter

\newcommand\deftitle[1]
  {%
    \myifeq{#1}{Aa}{aaa}{}%
    \myifeq{#1}{Bb}{bbb}{}%
  }

\begin{document}
\ExpandAndUppercaseFirst{\deftitle{Aa}}
\end{document}

使用编程层,相同的宏,但更加稳定expl3

\documentclass[]{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand \ExpandAndUppercaseFirst { m }
  {
    \text_titlecase_first:n { #1 }
  }

\NewExpandableDocumentCommand \deftitle { m }
  {%
    \str_if_eq:nnT { #1 } { Aa } { aaa }
    \str_if_eq:nnT { #1 } { Bb } { bbb }
  }
\ExplSyntaxOff

\begin{document}
\ExpandAndUppercaseFirst{\deftitle{Aa}}
\end{document}

相关内容