Erste Lösung

Erste Lösung

Es klingt ein bisschen künstlich, aber nehmen wir als Kontext Folgendes an:

Erstens möchte ich Beschriftungen für Tabellen hinzufügen tab:label, für Abbildungen usw. fig:labelZweitens möchte ich einige Befehle erstellen, um Abbildungen, Tabellen usw. einzuschließen.

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

Und ich habe einen Befehl, der eine Überschrift und ein Label einfügt, das wie folgt aussieht:

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

\captionlabelDie Frage ist, ob es irgendwie möglich ist, von anzurufen \includetableund das tab:Präfix zu übergeben (so etwas wie \captionlabel {#1.1}[tab:]{#1.2}).

Ich weiß, dass ich das optionale Argument in entfernen \captionlabelund immer \includetablemit aufrufen könnte tab:label, oder ich könnte die Reihenfolge der Argumente von \captionlabelin {O{} m m}oder ändern {m m O{}}oder den Befehl inline einfügen. Es ist im Grunde nur ein Beispiel.

Antwort1

\NewDocumentCommanddient zum Definieren von benutzerorientierten Befehlen, aber es ist einfacher und übersichtlicher, expl3wenn Sie eine API auf Codeebene definieren, auf der die Befehle auf Benutzerebene basieren. Einer der Gründe ist, dass es sehr einfach ist, Varianten von Funktionen auf Codeebene mit zu generieren \cs_generate_variant:Nn, während mit definierte Befehle \NewDocumentCommanddies nicht unterstützen. Hier sind zwei Möglichkeiten, Ihr Problem zu lösen, bei denen die Schnittstelle Ihres Befehls intakt bleibt \captionlabel.

Erste Lösung

Diese Lösung verwendet eine Funktion auf Codeebene, \fabian_insert_caption_and_label:nnnbei der die beiden über bereitgestellten Argumente \SplitArgumentbenachbarte Positionen einnehmen (nämlich die Positionen 2 und 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}

Zweite Lösung

Diese Lösung verwendet eine andere Funktion auf Codeebene \fabian_insert_caption_and_label:nnnals die erste Lösung: Sie akzeptiert die Argumente in der gleichen Reihenfolge wie Ihre\captionlabel . Um die beiden „nicht benachbarten Argumente“ zu verwalten, übergeben wir sie manuell, nachdem wir das erste Argument von selbst aufgeteilt haben \includetable. Beachten Sie, dass Sie eine entsprechende Codeebenenfunktion erstellen könnten und wahrscheinlich auch sollten \includetable. Auf diese Weise ist die Wiederverwendung des Codes einfacher (ich habe es nicht getan, um nicht alle Probleme zu vermischen, aber ich spreche nur von einem einfachen Wrapper: siehe unten).

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

Wenn Geschwindigkeit ein Problem ist, würde ich verwenden\seq_pop:NN „twice“ statt \seq_item:Nn„twice“ verwenden, da letzteres jedes Mal die gesamte Sequenz durchläuft, während \seq_pop:NNnur das erste Element gespeichert und entfernt wird, was sehr schnell ist (das Ergebnis ist, \q_no_valuewenn kein Element mehr zum Entfernen vorhanden ist).

Empfohlene Verpackung für\includetable

Wenn ich das oben sage, würde ich vorschlagen, dass Sie eine einfache Funktion auf Codeebene hinzufügen, die Ihrer\includetable , die Ihrem entspricht, meinte ich einfach so etwas wie das:

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

Auf diese Weise können Sie sehr einfach Varianten definieren von\fabian_include_table:nnn . \cs_generate_variant:NnSie können bei Bedarf auch die Schnittstelle ändern (vorausgesetzt, es ist nicht Teil eines öffentlichen Pakets), ohne die Schnittstelle des Befehls auf Benutzerebene zu ändern \includetable.

Ausgabe beider Beispiele

Bildschirmfoto

Antwort2

Ich kann eine solche Syntax nicht empfehlen. Nur aus akademischem Interesse können Sie Folgendes tun:

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

Bildbeschreibung hier eingeben

verwandte Informationen