Primeira solução

Primeira solução

É um pouco artificial, mas assuma o seguinte como contexto:

Primeiro, quero adicionar rótulos para tabelas como tab:label, para figuras como fig:labele assim por diante. Segundo, quero criar alguns comandos para incluir figuras, tabelas, etc.

%{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}
}

E eu tenho um comando que insere uma legenda e um rótulo, que tem a seguinte aparência:

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

A questão é se é de alguma forma possível chamar \captionlabele \includetablepassar o tab:prefixo (algo como \captionlabel {#1.1}[tab:]{#1.2}).

Eu sei que poderia remover o argumento opcional \captionlabele sempre chamar \includetablewith tab:label, ou poderia mudar a ordem dos argumentos \captionlabelpara {O{} m m}ou {m m O{}}, ou incorporar o comando. É basicamente apenas um exemplo.

Responder1

\NewDocumentCommandserve para definir comandos voltados para o usuário, mas as coisas ficam mais fáceis e limpas quando expl3você define uma API em nível de código na qual os comandos em nível de usuário são baseados. Uma das razões é que é muito fácil gerar variantes de funções em nível de código com \cs_generate_variant:Nn, enquanto os comandos definidos com \NewDocumentCommandnão suportam isso. Aqui estão duas maneiras de resolver seu problema que mantêm \captionlabelintacta a interface do seu comando.

Primeira solução

Esta solução usa uma função em nível de código \fabian_insert_caption_and_label:nnnonde os dois argumentos fornecidos \SplitArgumentocupam posições adjacentes (ou seja, posições 2 e 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}

Segunda solução

Esta solução usa uma função em nível de código \fabian_insert_caption_and_label:nnndiferente daquela da primeira solução: ela aceita os argumentos na mesma ordem que o seu arquivo \captionlabel. Para gerenciar os dois “argumentos não adjacentes”, passamos-os manualmente após dividirmos o primeiro argumento de \includetable. Observe que você poderia, e provavelmente deveria, criar uma função em nível de código correspondente a this \includetable. Dessa forma, reaproveitar o código fica mais fácil (não fiz isso para não misturar todos os problemas, mas é apenas um simples wrapper que estou falando: veja abaixo).

\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}

Se a velocidade for uma preocupação, eu usaria \seq_pop:NNduas vezes em vez de \seq_item:Nnduas vezes, porque o último itera toda a sequência todas as vezes, enquanto \seq_pop:NNapenas armazena e remove o primeiro item, o que é muito rápido (o resultado é \q_no_valuequando não há mais nenhum item para aparecer ).

Invólucro sugerido para\includetable

Quando eu disse acima, sugiro que você adicione uma função simples em nível de código correspondente ao seu \includetable, o que eu quis dizer foi simplesmente algo assim:

\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}
  }

Dessa forma, você pode definir facilmente variantes de \fabian_include_table:nnnuso de \cs_generate_variant:Nn. Você também pode alterar sua interface se necessário (supondo que não faça parte de um pacote público) sem alterar a interface do comando em nível de usuário \includetable.

Saída de ambos os exemplos

Captura de tela

Responder2

Não posso recomendar tal sintaxe. Apenas por interesse acadêmico, veja como você pode fazer:

\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}

insira a descrição da imagem aqui

informação relacionada