Here is a \providelength
command that will define a new length if not already defined, but also checks whether the command passed as argument has been defined with \newlength
, in order to issue an error message if you try to use, say, \providelength{\textit}
.
\documentclass{article}
\makeatletter
\newcommand{\providelength}[1]{%
\@ifundefined{\expandafter\@gobble\string#1}
{% if #1 is undefined, do \newlength
\typeout{\string\providelength: making new length \string#1}%
\newlength{#1}%
}
{% else check whether #1 is actually a length
\sdaau@checkforlength{#1}%
}%
}
\newcommand{\sdaau@checkforlength}[1]{%
% get the first five characters from \meaning#1
\edef\sdaau@temp{\expandafter\sdaau@getfive\meaning#1TTTTT$}%
% compare with the string "\skip"
\ifx\sdaau@temp\sdaau@skipstring
\typeout{\string\providelength: \string#1 already a length}%
\else
\@latex@error
{\string#1 illegal in \string\providelength}
{\string#1 is defined, but not with \string\newlength}%
\fi
}
\def\sdaau@getfive#1#2#3#4#5#6${#1#2#3#4#5}
\edef\sdaau@skipstring{\string\skip}
\makeatother
\begin{document}
\providelength{\foo}
\providelength{\foo}
\providelength{\textit}
\stop
Here is the terminal output:
\providelength: making new length \foo
\providelength: \foo already a length
! LaTeX Error: \textit illegal in \providelength.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.31 \providelength{\textit}
? h
\textit is defined, but not with \newlength
?
A version with expl3
, that avoids the trick for finding if the command is already a length.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\providelength}{m}
{
\cs_if_exist:NTF #1
{
\sdaau_providelength_check:N #1
}
{
\msg_info:nnx { providelength } { making } { \token_to_str:N #1 }
\newlength{#1}
}
}
\cs_new_protected:Nn \sdaau_providelength_check:N
{
\token_if_skip_register:NTF #1
{
\msg_info:nnx { providelength } { not-making } { \token_to_str:N #1 }
}
{
\msg_error:nnx { providelength } { defined } { \token_to_str:N #1 }
}
}
\msg_new:nnn { providelength } { making }
{
\token_to_str:N \providelength :~making~new~length~#1
}
\msg_new:nnn { providelength } { not-making }
{
\token_to_str:N \providelength :~#1~is~already~a~length
}
\msg_new:nnnn { providelength } { defined }
{
#1~illegal~in~\token_to_str:N\providelength
}
{
#1~is~defined,~but~not~with~\token_to_str:N\newlength
}
\ExplSyntaxOff
\begin{document}
\providelength{\foo}
\providelength{\foo}
\providelength{\textit}
\stop
This is the excerpt from the log file
.................................................
. providelength info: "making"
.
. \providelength: making new length \foo
.................................................
\foo=\skip49
.................................................
. providelength info: "not-making"
.
. \providelength: \foo is already a length
.................................................
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! providelength error: "defined"
!
! \textit illegal in \providelength
!
! See the providelength documentation for further information.
!
! For immediate help type H <return>.
!...............................................
l.47 \providelength{\textit}
? h
|'''''''''''''''''''''''''''''''''''''''''''''''
| \textit is defined, but not with \newlength
|...............................................