중첩된 \newcommand 및 \renewcommand

중첩된 \newcommand 및 \renewcommand

클래스를 읽으면서 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}

then will은 이 순간부터 will typeset 의 각 사용법을 \myname나타냅니다 .Stefano\mynameStefano

답변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}%
}

where는 \twentisecondscv@repeat한 번만 실행되어야 하는 다른 명령에도 사용할 수 있습니다.

관련 정보