
\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}