有两件事我理解,有一件事我不理解:
我经常使用它\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
。非字符标记保持不变,不进行扩展。
这是慢动作的工作(第一版)。
\mycommand{abc}
这#1
是abc
\mycommandaux abc\relax
这里#1
是a
和#2
是bc
(参数#2
由分隔\relax
,而#1
不受分隔,因此仅抓取第一个标记)\uppercase{\expandafter\gdef\csname a}bc\endcsname {the macro abc expanded}
特克斯执行并\uppercase
放回\expandafter\gdef\csname A
在输入流中。
\expandafter\gdef\csname Abc\endcsname{the macro abc expanded}
\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,...,f
为A,...,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}