Ian Thompson's code is good, but you could add the check whether you can define a new length in the first place; calling, say,
\deflen{textwidth}{6pt}
would issue an error message at \newlength
, but it would set \textwidth
nonetheless. Since you are in a style file you don't need \makeatletter
for @
commands, so you can do
\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}%
}
The code given as second argument to \@ifdefinable
is executed only if the control sequence given as first argument is undefined; otherwise an error is raised and the code is ignored.
Note that prefix
stands for the prefix used in the style file for not clobbering other packages' macros.
A LaTeX3 version could be
\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
Note that \deflen{foo}{6pt}
will define \l_prefix_foo_skip
as the internal name of the register, but also \foo
at the user level. The *-version would allocate a rigid length register (a \dimen
, in TeXspeak).
Test code:
\deflen{foo}{3pt}
\showthe\foo
\show\foo
\deflen*{baz}{3pt}
\showthe\baz
\show\baz
\deflen{textwidth}{3pt}
Here's the terminal output:
> 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.
|...............................................
?