다소 인위적이지만 다음과 같은 맥락을 가정합니다.
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를 정의하면 작업이 더 쉽고 깔끔해집니다. 그 이유 중 하나는 를 사용하면 코드 수준 함수의 변형을 생성하는 것이 매우 쉬운 \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
. this 에 해당하는 코드 수준 함수를 생성할 수 있고 생성해야 할 수도 있습니다 \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}