抱歉,这可能是一个非常简单的问题,我正在尝试清理样式文件,并想编写一个基本上运行以下代码的命令:
\newlength{<name>}\setlength{<name>}{<value>}
基于运行的另一个命令\def
,我认为我可以轻松使用expandafter
;csname
以下是我尝试过的:
\newcommand{\deflen}[2]{%
\expandafter\newlength{%
\csname #1\endcsname}\setlength{%
\csname #1\endcsname}{#2}
}
不幸的是,这似乎会产生与已定义相关的错误csname
。我认为这意味着我不能csname
在同一个扩展中使用两次,但我不知道如何先定义名称,然后使用它两次......帮忙?:)
答案1
您需要在用 定义之前\newcommand
和使用之前组装控制序列名称。这可以使用\expandafter
两次来实现。
\newcommand{\deflen}[2]{%
\expandafter\newlength\csname #1\endcsname
\expandafter\setlength\csname #1\endcsname{#2}%
}
\deflen{mylength}{12pt}
\showthe\mylength
答案2
Ian Thompson 的代码很好,但你可以添加检查能首先定义一个新的长度;例如,
\deflen{textwidth}{6pt}
会在 处发出错误消息\newlength
,但它\textwidth
仍然会设置。由于您处于样式文件中,因此您不需要\makeatletter
命令@
,因此您可以执行
\newcommand{\deflen}[2]{%
\expandafter\@ifdefinable\csname #1\endcsname{\prefix@deflen{#1}{#2}}%
}
\newcommand{\prefix@deflen}[2]{%
\expandafter\newlength\csname #1\endcsname
\expandafter\setlength\csname #1\endcsname{#2}%
}
仅当第一个参数给出的控制序列未定义时,才会执行作为第二个参数给出的代码\@ifdefinable
;否则会引发错误并忽略代码。
请注意,prefix
代表样式文件中使用的前缀,用于不破坏其他包的宏。
LaTeX3 版本可能
\RequirePackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\deflen}{ s m m }
{
\IfBooleanTF { #1 }
{ \prefix_deflen:nnn { dim } { #2 } { #3 } }
{ \prefix_deflen:nnn { skip } { #2 } { #3 } }
}
\cs_new_protected:Npn \prefix_deflen:nnn #1 #2 #3
{
\cs_if_exist:cTF { #2 }
{
\msg_error:nnn { package } { already~defined } { #2 }
}
{
\__prefix_deflen:nnn { #1 } { #2 } { #3 }
}
}
\cs_new_protected:Npn \__prefix_deflen:nnn #1 #2 #3
{
\use:c { #1_new:c } { l_prefix_#2_#1 }
\use:c { #1_set:cn } { l_prefix_#2_#1 } { #3 }
\cs_set_eq:cc { #2 } { l_prefix_#2_#1 } % user level name
}
\msg_new:nnnn { package } { already~defined }
{
Control~sequence~\exp_not:c { #1 } already~defined.
}
{
The~control~sequence~\exp_not:c { #1 } already~exists.~
Please~use~a~new~name;~the~command~will~not~be~executed.
}
\ExplSyntaxOff
请注意,\deflen{foo}{6pt}
将定义\l_prefix_foo_skip
为寄存器的内部名称,但也在\foo
用户级别。 *-version 将分配一个固定长度的寄存器(\dimen
在 TeXspeak 中为 )。
测试代码:
\deflen{foo}{3pt}
\showthe\foo
\show\foo
\deflen*{baz}{3pt}
\showthe\baz
\show\baz
\deflen{textwidth}{3pt}
这是终端输出:
> 3.0pt.
l.40 \showthe\foo
?
> \foo=\skip47.
l.41 \show\foo
?
> 3.0pt.
l.44 \showthe\baz
?
> \baz=\dimen133.
l.45 \show\baz
?
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! package error: "already defined"
!
! Control sequence \textwidth already defined.
!
! See the package documentation for further information.
!
! For immediate help type H <return>.
!...............................................
l.46 \deflen{textwidth}{3pt}
? h
|'''''''''''''''''''''''''''''''''''''''''''''''
| The control sequence \textwidth already exists. Please use a new name; the
| command will not be executed.
|...............................................
?