第一個解決方案

第一個解決方案

這有點人為,但假設以下內容作為上下文:

首先,我想為表格加上標籤 as tab:label,為數字加上標籤 asfig:label等等。其次,我想創建一些命令來包含圖形、表格等。

%{caption; label} %table def %table content
\NewDocumentCommand{\includetable}{> { \SplitArgument { 1 } { ; } } m m m}{
  \begin{table}[htb!]
    \captionlabel#1 % the Question is about this line; how do I pass the prefix?
    \begin{tabular}{#2}
        #3
    \end{tabular}
  \end{table}
}

我有一個插入標題和標籤的命令,如下所示:

%caption %label prefix %label
\NewDocumentCommand{\captionlabel}{m O{} m}{
    \caption{#1}\label{#2#3} 
}

問題是是否可以透過某種方式呼叫\captionlabel\includetable傳遞tab:前綴(類似\captionlabel {#1.1}[tab:]{#1.2})。

我知道我可以刪除 中 的可選參數\captionlabel並始終使用 調用\includetable,或者我可以切換to或tab:label的參數順序,或者內聯命令。這基本上只是一個例子。\captionlabel{O{} m m}{m m O{}}

答案1

\NewDocumentCommand用於定義使用者導向的命令,但是expl3當您定義使用者層級命令所基於的程式碼級 API 時,事情會變得更容易、更清晰。原因之一是使用 產生程式碼級函數的變體非常容易\cs_generate_variant:Nn,而使用 定義的命令\NewDocumentCommand不支援這一點。這裡有兩種方法可以解決您的問題,使您的命令介面保持\captionlabel完整。

第一個解決方案

此解決方案使用程式碼層級函數\fabian_insert_caption_and_label:nnn,其中透過提供的兩個參數\SplitArgument佔據相鄰位置(即位置 2 和 3):

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\cs_new_protected:Npn \fabian_insert_caption_and_label:nnn #1#2#3
  { \caption {#2} \label {#1#3} }

\NewDocumentCommand { \includetable } { > { \SplitArgument { 1 } { ; } } m m m }
  {
    \begin{table}[htb!]
    \centering
    \fabian_insert_caption_and_label:nnn { tab: } #1

    \begin{tabular}{#2}
      #3
    \end{tabular}
    \end{table}
  }

% Useless here, but maybe you want it for other code of yours.
\NewDocumentCommand { \captionlabel } { m O{} m }
  {
    \fabian_insert_caption_and_label:nnn {#2} {#1} {#3}
  }

\ExplSyntaxOff

\begin{document}
  \includetable{Caption text; the label}{ll}{This & is\\ a & table}

  See table~\ref{tab:the label} on page~\pageref{tab:the label}.
\end{document}

第二種解決方案

此解決方案使用與第一個解決方案中的程式碼級函數不同的程式碼級函數\fabian_insert_caption_and_label:nnn:它以與您的\captionlabel.為了管理這兩個“不相鄰的參數”,我們在分割 的第一個參數後手動傳遞它們\includetable。請注意,您可以而且可能應該建立與此相對應的程式碼級函數\includetable。這樣,重用程式碼就更容易了(我這樣做是為了不混淆所有問題,但它只是我正在談論的一個簡單的包裝器:見下文)。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\cs_new_protected:Npn \fabian_insert_caption_and_label:nnn #1#2#3
  { \caption {#1} \label {#2#3} }

\cs_generate_variant:Nn \fabian_insert_caption_and_label:nnn { xnx }

\seq_new:N \l_fabian_tmp_seq

\NewDocumentCommand { \includetable } { m m m }
  {
    \seq_set_split:Nnn \l_fabian_tmp_seq { ; } {#1}

    \begin{table}[htb!]
    \centering
    \fabian_insert_caption_and_label:xnx
      { \seq_item:Nn \l_fabian_tmp_seq { 1 } }
      { tab: }
      { \seq_item:Nn \l_fabian_tmp_seq { 2 } }

    \begin{tabular}{#2}
      #3
    \end{tabular}
    \end{table}
  }

\NewDocumentCommand { \captionlabel } { m O{} m }
  {
    \fabian_insert_caption_and_label:nnn {#1} {#2} {#3}
  }

\ExplSyntaxOff

\begin{document}
  \includetable{Caption text; the label}{ll}{This & is\\ a & table}

  See table~\ref{tab:the label} on page~\pageref{tab:the label}.
\end{document}

如果速度是一個問題,我會使用\seq_pop:NN兩次而不是\seq_item:Nn兩次,因為後者每次都會迭代整個序列,而\seq_pop:NN只是存儲和刪除第一個項目,這非常快(結果是\q_no_value當不再有項目可以彈出時) )。

建議的包裝器\includetable

當我上面說我建議你加入一個與你的 相對應的簡單程式碼級函數時\includetable,我的意思很簡單:

\cs_new_protected:Npn \fabian_include_table:nnn #1#2#3
  {
    \seq_set_split:Nnn \l_fabian_tmp_seq { ; } {#1}

    \begin{table}[htb!]
    \centering
    \fabian_insert_caption_and_label:xnx
      { \seq_item:Nn \l_fabian_tmp_seq { 1 } }
      { tab: }
      { \seq_item:Nn \l_fabian_tmp_seq { 2 } }

    \begin{tabular}{#2}
      #3
    \end{tabular}
    \end{table}
  }

\NewDocumentCommand { \includetable } { m m m }
  {
    \fabian_include_table:nnn {#1} {#2} {#3}
  }

這樣,您可以非常輕鬆地定義\fabian_include_table:nnn使用的變體\cs_generate_variant:Nn。如果需要,您也可以更改其介面(假設它不是公共包的一部分),而無需更改使用者級命令的介面\includetable

兩個範例的輸出

螢幕截圖

答案2

我不能推薦這樣的文法。僅出於學術興趣,您可以這樣做:

\documentclass{article}
\usepackage{xparse}

\NewDocumentCommand{\includetable}{> { \SplitArgument { 2 } { ; } } m m m}{%
  \begin{table}[htb!]
    \centering
    \addcaptionlabel#1
    \begin{tabular}{#2}
        #3
    \end{tabular}
  \end{table}
}
\NewDocumentCommand{\captionlabel}{m O{} m}{%
  \caption{#1}\label{#2#3} 
}
\NewDocumentCommand{\addcaptionlabel}{mmm}{%
  \IfNoValueTF{#3}{%
    \captionlabel{#1}{#2}%
  }{%
    \captionlabel{#1}[#2]{#3}%
  }%
}

\begin{document}

\ref{DEF} and \ref{prefixDEF}

\includetable{ABC;DEF}{cc}{11 & 22 \\ 333 & 4}

\includetable{ABC;prefix;DEF}{cc}{11 & 22 \\ 333 & 4}

\end{document}

在此輸入影像描述

相關內容