使用 \csname 创建大写宏标记

使用 \csname 创建大写宏标记

有两件事我理解,有一件事我不理解:

我经常使用它\csname来创建用户定义的标记。例如,以下代码用于\expandafter扩展结果之间\csname\endcsname之前的所有内容:\gdef

\newcommand{\mycommand}[1]{%
  \expandafter\gdef\csname #1\endcsname{Here is #1 printed.}%
}

\begin{document}
\mycommand{abc} % Creates a macro \abc
Demonstration: \abc % Prints Demonstration: Here is abc printed.
\end{document}

我想通过使用\mycommand{abc}创建宏\Abc(注意大写字母)来做类似的事情。不幸的是,\uppercase不能在里面使用\csname。(我猜有些部分会扩展为 TeX 基元?)但我从 Heiko Oberdiek 那里找到了一个有点相关的答案(http://newsgroups.derkeiler.com/Archive/Comp/comp.text.tex/2006-02/msg01220.html) 并创建了以下内容,我不完全理解。

它应该创建一个新的大写标记,并且我认为它正在起作用,因为我可以将\let它转换为另一个宏并且不会出错。

\newcommand{\mycommand}[1]{% 
  \uppercase\expandafter{\expandafter\csname #1}\endcsname% Creates token 
}%
\def\temp{if it worked}
\let\Abc\temp% Now \Abc expands to something other than \relax

\begin{document}
\mycommand{abc}% Creates \Abc
This lets you see \Abc.% Prints This lets you see if it worked.
\end{document}

所以我的问题是:如何创建大写标记并定义扩展同时?(基本上,我想结合上述两种方法。)以下是我尝试过的两种方法(均返回错误:额外的 \endcsname)。

\newcommand{\mycommand}[1]{% 
  \expandafter\gdef%   I think this tries to do \gdef\uppercase = bad 
  \uppercase\expandafter{\expandafter\csname #1}\endcsname{the macro #1 expanded}%  
}%
\mycommand{abc}
Use \Abc. % Should print Use the macro abc expanded.

或者

\newcommand{\mycommand}[1]{% 
  \expandafter\gdef\expandafter{% 
  \uppercase\expandafter{\expandafter\csname #1}\endcsname}{the macro #1 expanded}% 
}%
\mycommand{abc}
Use \Abc. % Should print Use the macro abc expanded.

答案1

您必须将第一个标记#1与其余标记隔离开来,并将其大写;事实上,它\uppercase不会扩展任何内容,并在操作后将标记列表放回到输入流中,这一点可以通过以下方式利用:

\newcommand{\mycommand}[1]{\mycommandaux#1\relax}
\def\mycommandaux#1#2\relax{%
  \uppercase{\expandafter\gdef\csname #1}#2\endcsname{the macro #1#2 expanded}%
}
\mycommand{abc}
\show\Abc

当然,空参数将\mycommand导致错误。

如果你想给出一个定义,可以说

\mycommand{abc}{Something else}

相当于\def\Abc{Something else},只需省略后面的标记\endcsname

\newcommand{\mycommand}[1]{\mycommandaux#1\relax}
\def\mycommandaux#1#2\relax{%
  \uppercase{\expandafter\gdef\csname #1}#2\endcsname
}
\mycommand{abc}{Something else}
\show\Abc

该命令\uppercase比其他 TeX 基元命令更奇怪。事实上,它<general text>要求作为参数的 先在 TeX 的胃中移动,在每个字符标记使用向量转换后进行“反刍” \uccode:如果一个字符具有正\uccode,TeX 会将其转换为该字符(类别代码不变)。因此,例如,TeX 设置为 ,\uccode`a=`A因此反刍后a变成A。非字符标记保持不变,进行扩展。

这是慢动作的工作(第一版)。

  1. \mycommand{abc}
    #1abc

  2. \mycommandaux abc\relax
    这里#1a#2bc(参数#2由分隔\relax,而#1不受分隔,因此仅抓取第一个标记)

  3. \uppercase{\expandafter\gdef\csname a}bc\endcsname {the macro abc expanded}
    特克斯执行\uppercase放回

    \expandafter\gdef\csname A
    

    在输入流中。

  4. \expandafter\gdef\csname Abc\endcsname{the macro abc expanded}

  5. \gdef\Abc{the macro abc expanded}

瞧!


\newcommand使用而不是 的变体\gdef,可以轻松定义带有参数的宏:

\newcommand{\mycommand}[1]{\mycommandaux#1\relax}
\def\mycommandaux#1#2\relax{%
  \uppercase{\expandafter\newcommand\csname #1}#2\endcsname
}
\mycommand{abc}{Something else}
\show\Abc

\mycommand{uvw}[1]{Something else with #1}
\show\Uvw

应与\gdef标准参数文本一起使用。

\newcommand{\mycommand}[1]{\mycommandaux#1\relax}
\def\mycommandaux#1#2\relax{%
  \uppercase{\expandafter\gdef\csname #1}#2\endcsname
}
\mycommand{abc}{Something else}
\show\Abc

\mycommand{uvw}#1{Something else with #1}
\show\Uvw

答案2

问题是\uppercase不可扩展。您不能将它与 一起使用\expandafter。我会首先扩展参数,作为一种很好的措施,然后使用第二个内部宏读取第一个字母,然后使用它\uppercase来更改该字母。最后,第二个内部宏读取新的大写字母和名称的其余部分并进行定义。如果需要,原始名称也可以作为第三个参数传递:

\makeatletter
\newcommand{\mycommand}[1]{% 
    \begingroup
    \edef\@tempa{#1}%
    \expandafter\endgroup\expandafter\@mycommand\@tempa\@nnil{#1}%
}
\def\@mycommand#1{%
    \uppercase{\@@mycommand{#1}}%
}
\def\@@mycommand#1#2\@nnil#3{%
    \global\@namedef{#1#2}{the macro #3 expanded}%%
}
\makeatother
\mycommand{abc}
\show\Abc

答案3

这是 LuaTeX 为何有用的一个很好的例子。

\def\defineuppercase#1%
    {\ctxcommand{defineuppercase("#1")}}

\startluacode
  function commands.defineuppercase(s)
      local upper = string.gsub(s, "^%l", string.upper)
      context.setgvalue(upper)
  end
\stopluacode

\defineuppercase{one}{Something}

\show\One
\end

我正在使用 ConTeXt MkIV,但代码也可以轻松地转换为 LaTeX。

答案4

您还可以使用包裹xstring。因此,在定义\mycommand{abc}、 和之后\mycommand{dbc},您可以使用\Abc、 和\Def来获得:

在此处输入图片描述

笔记:

  • 下面的代码并不完整,因为它只转换字母a,...,fA,...,F,但扩展它应该不是太困难了。

代码:

\documentclass{article}
\usepackage{xstring}

\newcommand{\mycommand}[1]{%
    \IfBeginWith{#1}{a}{\StrSubstitute{#1}{a}{A}[\newMacroName]}{}%
    \IfBeginWith{#1}{b}{\StrSubstitute{#1}{b}{B}[\newMacroName]}{}%
    \IfBeginWith{#1}{c}{\StrSubstitute{#1}{c}{C}[\newMacroName]}{}%
    \IfBeginWith{#1}{d}{\StrSubstitute{#1}{d}{D}[\newMacroName]}{}%
    \IfBeginWith{#1}{e}{\StrSubstitute{#1}{e}{E}[\newMacroName]}{}%
    \IfBeginWith{#1}{f}{\StrSubstitute{#1}{f}{F}[\newMacroName]}{}%
    % ... complete this ...
    \expandafter\gdef\csname \newMacroName\endcsname{Here is #1 printed.}%
}%

\begin{document}
\mycommand{abc} % Creates a macro \Abc
Demonstration: \Abc % Prints Demonstration: Here is abc printed.


\mycommand{dbc} % Creates a macro \Dbc
Demonstration: \Dbc % Prints Demonstration: Here is abc printed.
\end{document}

相关内容