Читая класс, twentysecondcv.cls
я заметил, что есть команда, определенная следующим образом:
\newcommand\skills[1]{
\renewcommand{\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}
}
}
для чего используется вложенная \renewcommand
внутренняя часть \newcommand
?
Полный классна GitHub.
решение1
Определение \skills
таким образом приводит к тому, что при первом использовании ему требуется аргумент. Затем skills
он переопределяется для сохранения этого значения (плюс некоторая обработка), так что с этого момента команда (без аргумента) воспроизводит то, для чего она была настроена при первом вызове.
В качестве примера возьмем определение
\newcommand\myname[1]{\renewcommand\myname{#1}}
Когда вы выполняете
\myname{Stefano} % corresponds to \renewcommand\myname{Stefano}
то \myname
будет означать Stefano
с этого момента и далее, т.е. каждое использование \myname
будет набрано Stefano
.
решение2
TeX не имеет переменныхкак таковойкак и другие языки программирования. Существуют специальные регистры для хранения таких вещей, как счетчики (целые числа), измерения, потоки ввода и вывода, списки токенов и т. д., но по большей части все определяется в терминах макросов. Это означает, что для сохранения информации в переменной вместо этого определяется макрос.
То, что было сделано здесь, неидиоматично и ограничено тем, что теперь команда \skills
изменила свое значение безвозвратно, и наивный пользователь класса обнаружит неожиданные результаты, если использует ее \skills
дважды. Обычно, вместо того, чтобы переопределять команду, можно было бы сделать что-то вроде этого:
\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}
}
}
который сохранит значение \@skills
для последующего использования (в этом классе документа последующее использование происходит в \makeprofile
определении команды).
Более идиоматичным было бы, на самом деле, сделать
\newcommand\skills[1]{\def\@skills{#1}}
а затем перенести всю tikzpicture
окружающую среду в \makeprofile
определение.
решение3
Команда \makeprofile
определяется как
\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}
}
и вы должны сказать, \skills{x,y,z}
прежде чем сделать \makeprofile
.
Я не считаю это хорошим программированием, поскольку оно не позволяет проверять наличие ошибок.
Было бы лучше сделать
\newcommand{\skills}[1]{%
\def\twentysecondscv@skills{...#1...}%
}
и в \makeprofile
, вместо вызова\skills
, делайте
\ifdefined\twentysecondscv@skills
\twentysecondscv@skills
\else
\ClassError{twentysecondscv}
{No \protect\skills found}
{You need to define \protect\skills before doing \protect\makeprofile}%
\fi
При использовании этого кода сообщение об ошибке будет содержать точную информацию о том, что именно пошло не так.
Также, \skillstext
кажется, нигде не используется в предоставленных шаблонах. Если кто-то забудет \skills
, то вызов \makeprofile
просто проглотит \skillstext
. Если нет\skilltext
команда не появляется, он сожрёт \scriptsize
, который, кажется, существует только для того, чтобы быть проглоченным или полностью проигнорированным.
Даже лучше
\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}%
}
где\twentisecondscv@repeat
может использоваться также для других команд, которые должны быть выполнены только один раз.