這有點人為,但假設以下內容作為上下文:
首先,我想為表格加上標籤 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}