Nested \newcommand and \renewcommand
TeX does not have variables per se like other programming languages. There are special-purpose registers for holding things like counts (integers), dimensions, input and output streams, token lists, etc. but for the most part everything is defined in terms of macros. That means, to save information in a variable, one defines a macro instead.
What was done here is non-idiomatic and limited in that now the \skills
command has changed its meaning irrevocably and the naïve user of the class will discover unexpected results should she use \skills
twice. Normally, rather than redefining the command, one would have instead done something like this:
\newcommand\skills[1]{
\def\@skills{
\begin{tikzpicture}
\foreach [count=\i] \x/\y in {#1}{
\draw[fill=maingray,maingray] (0,\i) rectangle (6,\i+0.4);
\draw[fill=white,mainblue](0,\i) rectangle (\y,\i+0.4);
\node [above right] at (0,\i+0.4) {\x};
}
\end{tikzpicture}
}
}
which would store the value in \@skills
for later usage (in this document class, the later usage comes in the the \makeprofile
command definition.
A more idiomatic thing, in fact would have been to do
\newcommand\skills[1]{\def\@skills{#1}}
and then to move the whole tikzpicture
environment to the \makeprofile
definition.
Defining \skills
this way has the effect that at the first usage, it needs an argument. Then skills
is redefined to store this value (plus some processing) such that from now on, the command (without argument) reproduces what it was set up for at the first call.
As an example, take the definition
\newcommand\myname[1]{\renewcommand\myname{#1}}
When you execute
\myname{Stefano} % corresponds to \renewcommand\myname{Stefano}
then \myname
will stand for Stefano
from this moment onwards, i.e., each usage of \myname
will typeset Stefano
.
The command \makeprofile
is defined as
\newcommand{\makeprofile}{
\begin{tikzpicture}[remember picture,overlay]
\node [rectangle, fill=sidecolor, anchor=north, minimum width=9cm, minimum height=\paperheight+1cm] (box) at (-5cm,0.5cm){};
\end{tikzpicture}
%------------------------------------------------
\begin{textblock}{6}(0.5, 0.2)
[...irrelevant code...]
\profilesection{Skills}
\skills
\skillstext
\scriptsize
%(*)[The skill scale is from 0 (Fundamental Awareness) to 6 (Expert).]
%------------------------------------------------
\end{textblock}
}
and you're supposed to say \skills{x,y,z}
before doing \makeprofile
.
I don't find it good programming, because this cannot check for mistakes.
It would be better to do
\newcommand{\skills}[1]{%
\def\twentysecondscv@skills{...#1...}%
}
and in \makeprofile
, instead of calling \skills
, do
\ifdefined\twentysecondscv@skills
\twentysecondscv@skills
\else
\ClassError{twentysecondscv}
{No \protect\skills found}
{You need to define \protect\skills before doing \protect\makeprofile}%
\fi
With this code, the error message would refer to exactly what's gone wrong.
Also \skillstext
seems to be nowhere used in the provided templates. If one forgets \skills
then the call in \makeprofile
will just swallow \skillstext
. If no \skilltext
command appears, it will gobble \scriptsize
, which seems there just for the purpose of being swallowed or being completely ignored.
Even better
\newcommand{\skills}[1]{%
\def\twentysecondscv@skills{...#1...}%
\renewcommand{\skills}[1]{\twentysecondscv@repeat{\skills}}%
}
\newcommand{\twentysecondscv@repeat}[1]{%
\ClassError{twentysecondscv}
{Multiple \protect#1 ignored}
{You should have just one \protect#1 command}%
}
where \twentisecondscv@repeat
can be used also for other commands that are supposed to be issued only once.