
\joinlist
내부 목록 의 요소 사이에 쉼표나 기타 구분 기호를 추가하는 매크로를 만들었습니다 etoolbox
. 두 개의 요소("a 및 b")만 있는 목록에 대한 특수 처리 기능이 있습니다. 또한 긴 목록의 마지막 두 항목("a, b 및 c") 사이에 다른 구분 기호를 배치하는 방법도 알고 있습니다. 내가 만든 정의는 다음과 같습니다.
% typical use: \joinlist{\listmacro}{, }{, and }{ and }
\RequirePackage{etoolbox}
\newcommand{\@join@ignore}[1]{} % used to ignore current list element when counting
\newcount\@join@listlength % used to count length of list
\newcount\@join@currentnum % used to track current list element number
\newcommand{\joinlist}[4]{%
%
% count list elements
\@join@listlength 0 %
\forlistloop{\advance\@join@listlength 1\relax\@join@ignore}{#1}%
%
% now join list elements, tracking current element number
\@join@currentnum 0 %
\forlistloop{%
\advance\@join@currentnum 1 %
\ifnumequal{\the\@join@currentnum}{1}%
{}% first
{% not first
\ifnumequal{\the\@join@currentnum}{\the\@join@listlength}%
{% last
\ifnumequal{\the\@join@listlength}{2}%
{#4}% last of exactly two
{#3}% last of more than two
}%
{#2}% neither first nor last
}%
}%
{#1}}
위의 내용을 로 저장한 join-list.sty
후 문제를 보여주는 다음의 작은 예를 고려하십시오.
\documentclass{article}
\usepackage{hyperref}
\usepackage{join-list}
\begin{document}
\newcommand{\people}[0]{}
\listadd{\people}{a}
\joinlist{\people}{, }{, and }{ and } % a
\listadd{\people}{b}
\joinlist{\people}{, }{, and }{ and } % a and b
\listadd{\people}{c}
\joinlist{\people}{, }{, and }{ and } % a, b, and c
\hypersetup{pdfauthor=\joinlist{\people}{, }{, and }{ and }}
\end{document}
\joinlist
문서 본문 내용을 만드는 데 적합합니다. 예상대로 "a", "a 및 b", "a, b 및 c"가 표시됩니다.
불행하게도 이것을 사용하면 \hypersetup{pdfauthor=...}
원하는 대로 작동하지 않습니다. 대신 문서의 PDF 작성자 메타데이터를 "0 1110 1 , a1 , b1 , c"로 설정합니다. 분명히 \joinlist
이 맥락에서 매크로를 확장/평가하는 데 뭔가 크게 잘못되었습니다 .
내가 여기서 뭘 잘못하고 있는 걸까? 이 문제를 어떻게 해결할 수 있나요? 내 \joinlist
매크로를 개선할 수 있는 다른 방법이 있습니까 ? 널리 사용되는 패키지에 유사한 매크로가 이미 존재합니까? (검색했지만 아무것도 발견하지 못했습니다.)
답변1
문제는 "확장 가능"하지 않다는 것입니다 . 즉, 값에서는 수행할 수 없는 \joinlist
할당을 수행해야 합니다 .\advance\@join@currentnum 1
pdfauthor=
(더 이상 LaTeX3의 실험적인 프로그래밍 계층이 아님)을 사용하면 expl3
필요한 것이 있습니다.
\documentclass{article}
\usepackage{hyperref}
\RequirePackage{xparse}
\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\joinlist}{ m m m m }
{
\seq_use:cnnn { g_liblit_list_#1_seq } { #2 } { #3 } { #4 }
}
\cs_generate_variant:Nn \seq_use:Nnnn { c }
\NewDocumentCommand{\newlist}{ m }
{
\seq_new:c { g_liblit_list_#1_seq }
}
\NewDocumentCommand{\listadd}{ m m }
{
\seq_gput_right:cn { g_liblit_list_#1_seq } { #2 }
}
\ExplSyntaxOff
\begin{document}
\newlist{people}
\listadd{people}{a}
\joinlist{people}{ and }{, }{, and } % a
\listadd{people}{b}
\joinlist{people}{ and }{, }{, and } % a and b
\listadd{people}{c}
\joinlist{people}{ and }{, }{, and } % a, b, and c
\hypersetup{pdfauthor=\joinlist{people}{ and }{, }{, and }}
\end{document}
설정과 관련하여 몇 가지 변경 사항이 있습니다. 목록은 매크로에 의해 호출되지 않고 이름을 갖습니다. 에 의해 새로운 것이 생성될 수 있습니다 \newlist
. 또한 인수의 순서도 \joinlist
다릅니다.
- 목록 이름;
- 요소가 두 개인 경우 요소 사이에 무엇이 들어가야 할까요?
- 2개 이상이면 요소 사이에 무엇을 넣어야 할까요(마지막 2개 제외).
- 그 사이에 무엇이 들어가야 할까?마지막요소가 2개 이상이면 2개입니다.
목록이 비어 있으면 아무것도 생성되지 않습니다. 단 하나의 요소만 있으면 그 요소가 생성됩니다.
이 버전의 는 \joinlist
확장 가능하며 에 값을 제공하는 데 문제가 없습니다 pdfauthor=
.
파일에서 귀하의 코드를 대체하기 위해 서문의 코드를 사용할 수 있습니다 .sty
.