definir pdfauthor usando macro complexa de processamento de lista

definir pdfauthor usando macro complexa de processamento de lista

Criei uma macro \joinlistque adiciona vírgulas ou outros delimitadores entre os elementos de uma etoolboxlista interna. Possui tratamento especial para listas de apenas dois elementos ("a e b"). Ele também sabe colocar um delimitador diferente entre os dois últimos itens de listas mais longas ("a, b e c"). Aqui está a definição, criada por mim:

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

Salve o texto acima como join-list.stye considere o seguinte pequeno exemplo mostrando um 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}

\joinlistfunciona bem para criar conteúdo do corpo do documento. Vemos "a", depois "a e b" e depois "a, b e c" conforme esperado.

Infelizmente, usar isso \hypersetup{pdfauthor=...}não funciona como esperado. Em vez disso, ele define os metadados do autor PDF do documento como "0 1110 1 e a1 e b1 e c". É evidente que algo correu mal na expansão/avaliação da \joinlistmacro neste contexto.

O que estou fazendo de errado aqui? Como posso consertar isso? Existem outras maneiras de \joinlistmelhorar minha macro? Já existe uma macro semelhante em algum pacote amplamente disponível? (Eu procurei, mas não encontrei nenhum.)

Responder1

O problema é que \joinlistnão é "expansível": ele deve realizar atribuições como \advance\@join@currentnum 1as que não podem ser feitas no valor de pdfauthor=.

Com expl3(a camada de programação não mais experimental para LaTeX3), existe o que você precisa.

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

Existem algumas alterações em relação à sua configuração. As listas têm um nome, em vez de serem chamadas por uma macro; um novo pode ser criado por \newlist. Além disso, a ordem dos argumentos \joinlisté diferente:

  1. o nome da lista;
  2. o que deve ficar entre os elementos no caso de dois elementos;
  3. o que deve ficar entre os elementos quando houver mais de dois (exceto os dois últimos);
  4. o que deveria acontecer entredurardois elementos quando há mais de dois.

Caso a lista esteja vazia nada será produzido; com apenas um elemento, esse será produzido.

Esta versão \joinlisté expansível e não há problema em atribuí-la como valor a pdfauthor=.

Você pode usar o código no preâmbulo como um substituto para o seu no .styarquivo.

insira a descrição da imagem aqui

informação relacionada