最初の解決策

最初の解決策

少し不自然ですが、文脈として次のことを想定します。

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から呼び出し\includetabletab:プレフィックス ( のようなもの\captionlabel {#1.1}[tab:]{#1.2}) を渡すことが何らかの方法で可能かどうかです。

のオプション引数を削除して常に をで\captionlabel呼び出すか、 の引数の順序を または に切り替えるか、コマンドをインライン化できることはわかっています。基本的には単なる例です。\includetabletab: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}

ここに画像の説明を入力してください

関連情報