少し不自然ですが、文脈として次のことを想定します。
tab:label
まず、表には、図にはなどのラベルを追加したいと思いますfig: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
tab:label
\captionlabel
{O{} m m}
{m m O{}}
答え1
\NewDocumentCommand
はユーザー向けコマンドを定義するためのものですが、 ではexpl3
ユーザー レベル コマンドのベースとなるコード レベル API を定義すると、より簡単かつ簡潔になります。その理由の 1 つは、 ではコード レベル関数のバリアントを生成するのが非常に簡単であるのに対し\cs_generate_variant:Nn
、 で定義されたコマンドでは\NewDocumentCommand
これがサポートされていないことです。ここでは、コマンドのインターフェイスをそのまま維持しながら問題を解決する 2 つの方法を紹介します\captionlabel
。
最初の解決策
\fabian_insert_caption_and_label:nnn
このソリューションでは、 を介して提供される 2 つの引数が\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}
2番目の解決策
このソリューションでは、最初のソリューションとは異なるコード レベルの関数を使用します\fabian_insert_caption_and_label:nnn
。つまり、 と同じ順序で引数を受け入れます\captionlabel
。2 つの「隣接しない引数」を管理するために、 の最初の引数を分割した後、それらを手動で渡します\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
速度が懸念される場合は、twiceではなく、twice を使用します\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}