
He creado una macro \joinlist
que agrega comas u otros delimitadores entre los elementos de una etoolbox
lista interna. Tiene un manejo especial para listas de sólo dos elementos ("a y b"). También sabe cómo poner un delimitador diferente entre los dos últimos elementos de listas más largas ("a, byc"). Aquí está la definición, creada por mí:
% 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}}
Guarde lo anterior como join-list.sty
y luego considere el siguiente pequeño ejemplo que muestra un problema:
\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
funciona bien para crear contenido del cuerpo del documento. Vemos "a", luego "a y b", luego "a, b y c" como se esperaba.
Desafortunadamente, usar esto \hypersetup{pdfauthor=...}
no funciona como se esperaba. En su lugar, establece los metadatos del autor del PDF del documento en "0 1110 1, a1, b1 y c". Es evidente que algo salió muy mal al ampliar/evaluar la \joinlist
macro en este contexto.
¿Qué estoy haciendo mal aquí? ¿Cómo puedo arreglar esto? ¿Existen otras formas de \joinlist
mejorar mi macro? ¿Existe ya una macro similar en algún paquete ampliamente disponible? (Busqué pero no encontré ninguno).
Respuesta1
El problema es que \joinlist
no es "ampliable": debe realizar asignaciones que \advance\@join@currentnum 1
no se pueden realizar en el valor de pdfauthor=
.
Con expl3
(la capa de programación ya no tan experimental para LaTeX3), hay lo que necesitas.
\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}
Hay algunos cambios con respecto a su configuración. Las listas tienen un nombre, en lugar de ser llamadas por una macro; Se puede crear uno nuevo mediante \newlist
. Además, el orden de los argumentos \joinlist
es diferente:
- el nombre de la lista;
- qué debe ir entre los elementos en caso de dos elementos;
- qué debe ir entre los elementos cuando hay más de dos (excepto los dos últimos);
- ¿Qué debería pasar entre losúltimodos elementos cuando son más de dos.
En caso de que la lista esté vacía no se producirá nada; con un solo elemento, ese será producido.
Esta versión de \joinlist
es ampliable y no hay problema en darle como valor pdfauthor=
.
Puede utilizar el código del preámbulo como reemplazo directo del suyo en el .sty
archivo.