使用複雜的列表處理巨集設定 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 、 a1 、 b1 、 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檔案中您的程式碼。

在此輸入影像描述

相關內容