추상 버전

추상 버전

\buildmacro나는 '일반' 문자(예: )의 문자열을 인수로 취하고 Title다음을 만족하는 TeX '매크로 구축' 명령(이라고 부르겠습니다)을 정의하고 싶습니다 .

  • 이 명령은 \buildmacro{Title}이름으로 카운터를 정의 TitleXcounter하고 0으로 초기화합니다.
  • 파일의 특정 지점에서 TeX 명령을 실행하면 카운터가 증가한 다음 해당 값을 이름이 있는 새 TeX 매크로에 넣는 \Title{<arg>}효과가 있습니다 . 여기서 는 의 현재 값입니다 .TitleXcounter<arg>\Title-<x><x>TitleXcounter

    여기에는 <arg>TeX 코드 조각이 있습니다(텍스트, 수학, 기타 TeX 명령의 단락이 포함될 수 있음).

다음과 같은 최소한의 예를 고려하십시오.

\documentclass{article}
\usepackage{ifthen}


\def\buildmacro#1{...}% the definition of \buildmacro

\begin{document}

\buildmacro{Title}

% 'Read' several titles

\Title{The first title}
\Title{The second title}
\Title{The third title}

\newcount\tempcount
\tempcount=1\relax

% 'List' all the Titles
\whiledo{\the\tempcount<\numexpr \thetitleXcounter+1\relax}
        {%
         \textsc{\csname title-\the\tempcount\endcsname}\par
         \advance\tempcount by 1\relax
        }

\end{document}

나는 \csname\endcsname, \expandafter, 및 버전을 '연주'했지만 '행운' \def은 없었습니다.\gdef\long

편집됨(일부 의견에 답변하기 위해):

이것의 목적은 동일한 루트 이름(명령 목록과 유사)을 가진 색인화된 명령 세트를 생성하는 간단한 메커니즘을 갖는 것입니다. \csname <...> \endcsname명령을 실행하기 위해 항상 구성을 사용할 수 있습니다 .

답변1

필요한 흐름에 대한 설명을 보면 매우 간단해 보입니다.

\newcommand\buildmacro[1]{%
  % Create a new counter named after the argument
  \newcounter{#1Xcounter}%
  % Create a new command named after the argument,
  % itself taking one argument
  \expandafter\newcommand\csname #1\endcsname[1]{%
    % Step the counter
    \stepcounter(#1Xcounter)%
    % Store the argument
    \expandafter\newcommand\csname #1-\arabic{#1Xcounter}\endcsname
      {##1}%
  }%
}

일반 버전도 요청되었기 때문에

\long\def\buildmacro#1{%
  \csname newcount\expandafter\endcsname\csname #1Xcounter\endcsname
  \long\expandafter\def\csname #1\endcsname##1{%
    \global\expandafter\advance\csname #1Xcounter\endcsname by 1
    \expandafter\def\csname #1-\expandafter\number\csname #1Xcounter\endcsname
      \endcsname
      {##1}%
  }%
}

답변2

제가 코멘트에서 언급한 것처럼, 매크로 이름을 구성할 때 하이픈이나 숫자를 사용할 수 없습니다. 단, 매크로 이름을 사용할 때 해당 코드를 작성하거나 \csname ... \endcsname고양이 코드가 변경되었는지 확인하지 않는 한은 사용할 수 없습니다.

따라서 제안된 사용자 인터페이스를 수정하는 것이 필요합니다.

기본 아이디어는 목록의 이름과 해당 목록 내의 항목 색인을 제공하여 검색할 수 있는 일련의 색인화된 인수 목록을 만드는 것 같습니다.

이는 쉼표로 구분된 목록을 사용하여 구현할 수 있습니다. 다음은 expl3개발자가 안정적이라고 간주하는 구문 만 사용하는 제안된 인터페이스입니다 .

\buildmacro{<list identifier>}
\addmacro{<list identifier>}{<item to be added>}
\fetchmacro{<list identifier>}{<index of item to be fetched>}
\listmacro{<list identifier>}

첫 번째는 새 목록을 초기화하여 설정합니다. 두 번째는 목록에 항목을 추가합니다. 세 번째는 목록에서 항목을 가져옵니다. 네 번째는 목록의 모든 항목을 순차적으로 나열합니다.

개념 증명(원래는 아니지만):

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new_protected_nopar:Nn \digitalink_buildmacro:n
{
  \clist_new:c { g_digitalink_#1_clist }
}
\NewDocumentCommand \buildmacro { m }
{
  \digitalink_buildmacro:n { #1 }
}
\NewDocumentCommand \addmacro { m +m }
{
  \clist_gput_right:cn { g_digitalink_#1_clist }
  {
    #2
  }
}
\NewDocumentCommand \fetchmacro { m m }
{
  \clist_item:cn { g_digitalink_#1_clist } { #2 }
}
\NewDocumentCommand \listmacro { m }
{
  \clist_use:cn { g_digitalink_#1_clist } { \par }
}
\ExplSyntaxOff
\begin{document}
\buildmacro{dititle}
\addmacro{dititle}{Here's some text.}
\addmacro{dititle}{Here's some more.}
\fetchmacro{dititle}{1}
\fetchmacro{dititle}{2}
\fetchmacro{dititle}{1}

List:

\listmacro{dititle}
\end{document}

개념의 증거

답변3

A \@namedef\@nameuse버전, catcode 변경 없이는 불가능한 '매크로' 이름을 위조합니다.

\newcounter매크로 내부 할당으로 인해 카운터 레지스터에 문제가 발생할 수 있습니다.

\documentclass{article}

\makeatletter
\newcommand{\buildmacro}[1]{%
  \newcounter{#1Xcounter}%
    \expandafter\newcommand\csname #1\endcsname[1]{%
      \stepcounter{#1Xcounter}%
      \@namedef{#1-\number\value{#1Xcounter}}{##1}%
  }
}

\newcommand{\displaymacrocontent}[2]{%
  \@nameuse{#1-#2}%
}
\makeatother



\begin{document}

\buildmacro{Title}
\Title{The first title}
\Title{The second title}
\Title{The third title}

\newcount\tmpcntr

\loop\unless\ifnum\tmpcntr > 4
\advance\tmpcntr by 1
\displaymacrocontent{Title}{\number\tmpcntr}

\repeat



\end{document}

여기에 이미지 설명을 입력하세요

답변4

의사코드에 표시되는 효과는 목록 매크로를 사용하면 훨씬 더 쉽게 얻을 수 있습니다. 이 매크로를 사용하면 그 안에 개체 수를 알 필요 없이 스테핑 카운터 없이 루프를 수행할 수 있습니다.

\documentclass{article}

\makeatletter
\newcommand{\Titlecontainer}{\@empty}% initialize
\newcommand{\Title}[1]{%
  \expandafter\def\expandafter\Titlecontainer\expandafter{%
    \Titlecontainer\LISTSEP{#1}%
  }%
}
\makeatother

\begin{document}

\Title{The first title}
\Title{The second title}
\Title{The third title}

% 'List' all the Titles
\begingroup % keep the change to \LISTSEP local
\def\LISTSEP#1{\textsc{#1}\par}
\Titlecontainer
\endgroup

\end{document}

여기에 이미지 설명을 입력하세요

"추상적" 버전:

\documentclass{article}

\makeatletter
\newcommand{\Titlecontainer}{\@empty}% initialize
\newcommand{\Title}[1]{%
  \expandafter\def\expandafter\Titlecontainer\expandafter{%
    \Titlecontainer\LISTSEP{#1}%
  }%
}
\newcommand{\listmap}[2]{% #1 is the list name, #2 the code
  \begingroup\def\LISTSEP##1{#2}#1\endgroup
}
\makeatother

\begin{document}

\Title{The first title}
\Title{The second title}
\Title{The third title}

% 'List' all the Titles
\listmap{\Titlecontainer}{\textsc{#1}\par}

\end{document}

다음을 사용하면 훨씬 더 쉽습니다 expl3.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\Title}{m}
 {
  \seq_put_right:Nn \digitalink_titles_seq { #1 }
 }
\NewDocumentCommand{\ProcessTitles}{+m}
 {
  \seq_map_inline:Nn \digitalink_titles_seq { #1 }
 }
\seq_new:N \digitalink_titles_seq
\ExplSyntaxOff

\begin{document}

\Title{The first title}
\Title{The second title}
\Title{The third title}

\ProcessTitles{\textsc{#1}\par}

\newcounter{titlecount}
\ProcessTitles{\stepcounter{titlecount}\arabic{titlecount} -- #1\par}

\end{document}

여기에 이미지 설명을 입력하세요


추상 버전

고전적인 방법

\documentclass{article}

\makeatletter
\newcommand{\definelist}[1]{%
  \@namedef{#1}##1{%
    \expandafter\def\csname #1@container\expandafter\expandafter\expandafter\endcsname
    \expandafter\expandafter\expandafter{%
      \csname #1@container\endcsname\LISTSEP{##1}%
    }%
  }%
  \@namedef{#1@container}{\@empty}% initialize
}
\newcommand{\maplist}[2]{%
  \begingroup
  \def\LISTSEP##1{#2}%
  \@nameuse{#1@container}%
  \endgroup
}
\makeatother

\definelist{Title}

\begin{document}

\Title{The first title}
\Title{The second title}
\Title{The third title}

% 'List' all the Titles
\maplist{Title}{\textsc{#1}\par}

\newcounter{tempcount}
\maplist{Title}{\stepcounter{tempcount}\arabic{tempcount} -- #1\par}

\end{document}

와 함께expl3

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\definelist}{m}
 {
  \seq_new:c { l_digitalink_list_#1_seq }
  \cs_new_protected:cpn { #1 } ##1
   {
    \seq_put_right:cn { l_digitalink_list_#1_seq } { ##1 }
   }
 }
\NewDocumentCommand{\maplist}{m +m}
 {
  \seq_map_inline:cn { l_digitalink_list_#1_seq } { #2 }
 }
\ExplSyntaxOff

\definelist{Title}

\begin{document}

\Title{The first title}
\Title{The second title}
\Title{The third title}

% 'List' all the Titles
\maplist{Title}{\textsc{#1}\par}

\newcounter{tempcount}
\maplist{Title}{\stepcounter{tempcount}\arabic{tempcount} -- #1\par}

\end{document}

관련 정보