установить pdfauthor с помощью сложного макроса обработки списков

установить pdfauthor с помощью сложного макроса обработки списков

Я создал макрос, \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 , and a1 , and b1 , and c". Очевидно, что-то пошло не так с расширением/оценкой макроса \joinlistв этом контексте.

Что я делаю не так? Как это исправить? Есть ли другие способы \joinlistулучшить мой макрос? Существует ли уже похожий макрос в каком-то широкодоступном пакете? (Я искал, но не нашел.)

решение1

Проблема в том, что \joinlistон не «расширяемый»: он должен выполнять такие назначения, \advance\@join@currentnum 1которые не могут быть выполнены в значении pdfauthor=.

С expl3(уже не экспериментальным уровнем программирования для LaTeX3) есть то, что вам нужно.

\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отличается:

  1. название списка;
  2. что должно располагаться между элементами в случае двух элементов;
  3. что должно располагаться между элементами, когда их больше двух (за исключением последних двух);
  4. что должно быть междупоследнийдва элемента, когда их больше двух.

Если список пуст, ничего не будет создано; если в нем есть только один элемент, он будет создан.

Эта версия \joinlistявляется расширяемой, и нет никаких проблем с ее указанием в качестве значения pdfauthor=.

Вы можете использовать код в преамбуле в качестве замены вашего кода в .styфайле.

введите описание изображения здесь

Связанный контент