PDFAuthor mithilfe eines komplexen Listenverarbeitungsmakros festlegen

PDFAuthor mithilfe eines komplexen Listenverarbeitungsmakros festlegen

Ich habe ein Makro erstellt, \joinlistdas Kommas oder andere Trennzeichen zwischen den Elementen einer etoolboxinternen Liste einfügt. Es hat eine spezielle Behandlung für Listen mit nur zwei Elementen („a und b“). Es weiß auch, wie man zwischen den letzten beiden Elementen längerer Listen („a, b und c“) ein anderes Trennzeichen einfügt. Hier ist die von mir erstellte Definition:

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

Speichern Sie das Obige unter join-list.styund betrachten Sie dann das folgende kleine Beispiel, das ein Problem zeigt:

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

\joinlistfunktioniert gut zum Erstellen von Dokumenttextinhalten. Wir sehen wie erwartet „a“, dann „a und b“, dann „a, b und c“.

Leider \hypersetup{pdfauthor=...}funktioniert die Verwendung dieses Makros nicht wie erhofft. Stattdessen werden die PDF-Autorenmetadaten des Dokuments auf "0 1110 1 , und a1 , und b1 , und c" gesetzt. Offensichtlich ist beim Erweitern/Auswerten des \joinlistMakros in diesem Kontext etwas gründlich schiefgelaufen.

Was mache ich hier falsch? Wie kann ich das beheben? Gibt es andere Möglichkeiten, mein \joinlistMakro zu verbessern? Gibt es bereits ein ähnliches Makro in einem weit verbreiteten Paket? (Ich habe gesucht, aber keines gefunden.)

Antwort1

Das Problem besteht darin, dass \joinlistnicht „erweiterbar“ ist: Es muss Zuweisungen durchführen, wie \advance\@join@currentnum 1sie im Wert von nicht möglich sind pdfauthor=.

Mit expl3(der nicht mehr ganz so experimentellen Programmierschicht für LaTeX3) haben Sie, was Sie brauchen.

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

Es gibt einige Änderungen in Bezug auf Ihre Einstellung. Listen haben einen Namen, anstatt durch ein Makro aufgerufen zu werden; eine neue kann durch erstellt werden \newlist. Auch die Reihenfolge der Argumente \joinlistist anders:

  1. der Listenname;
  2. was sollte im Fall von zwei Elementen zwischen den Elementen stehen;
  3. was zwischen den Elementen stehen soll, wenn es mehr als zwei gibt (außer den letzten beiden);
  4. was soll zwischen denzuletztzwei Elemente, wenn mehr als zwei vorhanden sind.

Falls die Liste leer ist, wird nichts erzeugt, wenn sie nur ein Element enthält, wird dieses erzeugt.

Diese Version von \joinlistist erweiterbar und kann problemlos als Wert an übergeben werden pdfauthor=.

Sie können den Code in der Präambel als Ersatz für Ihren Code in der .styDatei verwenden.

Bildbeschreibung hier eingeben

verwandte Informationen