최근에 제가 발견한 이 코드 조각은 제가 겪고 있는 문제를 해결하는 데 완전히 도움이 될 것이라고 인터넷을 통해 발견했습니다. 코드는 다음과 같습니다.
\documentclass{article}
\usepackage{catoptions}
\makeatletter
\robust@def*\inputcommandnames{\cpt@testopt\@inputcommandnames{general}}
\newletcs\inputcommandname\inputcommandnames
% #1=stack name, #2=input name(s)
\robust@def*\@inputcommandnames[#1]#2{%
\ifblankFT{#1}{%
\@latex@info{No stack name given: using 'general' instead}%
}{%
% It is possible to iterate over stack names, but leave this for now:
% the use case isn't yet apparent.
\ifinsetTF,{#1}{%
\@latexerr{List '#1' not allowed}\@ehd
}{}%
}%
\ifcsndefTF{name@stack@#1}{}{\csn@def{name@stack@#1}{}}%
\ifcsndefTF{name@stackcount@#1}{}{\csn@def{name@stackcount@#1}{0}}%
\cptdocommalist{#2}{%
\csn@edef{name@stackcount@#1}%
{\the\numexpr\usename{name@stackcount@#1}+1}%
\csn@edef{name@stack@#1}{%
\expandcsnonce{name@stack@#1}\noexpand
\do{\usename{name@stackcount@#1}}{\unexpanded{##1}}%
}%
}%
}
\robust@def*\outputinnormalorder{\@outputcommandnames{normal}}
\newletcs\outputcommandnames\outputinnormalorder
\robust@def*\outputinreverseorder{\@outputcommandnames{reverse}}
% #1=listing/printing order, #2=stack name(s)
\robust@def*\@outputcommandnames#1#2{%
\cptdocommalist{#2}{%
\begingroup
\let\reserved@a\relax
\ifcsndefTF{name@stack@##1}{%
% If the stack is defined but it is currently empty, ignore it
% (but issue a warning). A 'verbose' option for triggering the
% warning will be useful here, but it hasn't been provided:
\ifcsnnullFT{name@stack@##1}{}{%
\@latex@info{Stack '##1' is empty}%
\def\reserved@a####1\endgroup{\endgroup}%
}%
}{%
\@latexerr{Stack '##1' is not defined}\@ehd
}%
\reserved@a
\xifstrcmpTF{#1}{normal}{%
\let\do\curroutputformat
\csname name@stack@##1\endcsname
}{%
\def\name@sentinel####1\name@stop{%
\let\do\curroutputformat####1%
}%
\def\do####1####2####3\name@sentinel####4\name@stop{%
####3\name@sentinel\do{####1}{####2}####4\name@stop
}%
\usename{name@stack@##1}\name@sentinel\name@stop
}%
\endgroup
}%
}
% \commandnameoutputformat<input no.><input item>
\robust@def*\commandnameoutputformat{%
% Skip any spurious spaces before opening brace:
\begingroup
\toks0{##1##2}%
\def\reserved@a{%
\expandafter\endgroup\expandafter\def\expandafter
\curroutputformat\the\toks\expandafter0\expandafter{\the\toks1}%
}%
\afterassignment\reserved@a\toks1=%
}
% If the stack isn't initialized after use, it will start building
% from the last count whenever it is called:
\robust@def*\initializecommandstacks#1{%
\cptdocommalist{#1}{%
\csn@def{name@stackcount@##1}{0}%
\csn@def{name@stack@##1}{}%
}%
}
\newletcs\initializecommandstack\initializecommandstacks
% Set empty stack 'xx' for warning later:
\csn@def{name@stack@xx}{}
\makeatother
% Examples:
\begin{document}
\inputcommandname{I wanted this whole sentence on this input, but when I use a comma it breaks the input and starts a new one}
\inputcommandname{If I don't use commas then it's ok}
\commandnameoutputformat{Input number #1 is: #2.\par}
Output:\par
\outputinnormalorder{general}
\end{document}
따라서 문제는 다음과 같습니다. 코드가 수행하는 작업(명령을 반복하는 변수 저장)을 정확하게 수행하지만 쉼표를 입력할 때마다 자동으로 새 입력을 생성하지 않기를 원합니다. 바꿔보려고 노력했지만 매번 실패했어요. 그런 식으로 작동하도록 수정해 주실 수 있나요("쉼표 분리" 없음)? 관심을 가져주셔서 감사합니다.
답변1
다음을 사용하여 유연한 코드를 얻을 수 있습니다 expl3
.
\documentclass{article}
\usepackage{xparse}
\usepackage{booktabs} % for the last example
\ExplSyntaxOn
% first define the user interface
\NewDocumentCommand{\addtolist}{O{general}m}
{
\marinho_lists_add:nn { #1 } { #2 }
}
\NewDocumentCommand{\listoutputformat}{+m}
{
\marinho_lists_output_format:n { #1 }
}
\NewDocumentCommand{\outputlist}{m}
{
\marinho_lists_output:n { #1 }
}
% define the internal functions
\cs_new_protected:Nn \marinho_lists_add:nn
{
% create the sequence if it doesn't exist
\seq_if_exist:cF { l_marinho_lists_#1_seq }
{
\seq_new:c { l_marinho_lists_#1_seq }
}
% add the item in the form {<number>}{<text>}
\seq_put_right:cx { l_marinho_lists_#1_seq }
{% compute the number based on the sequence length
{ \int_to_arabic:n { \seq_count:c { l_marinho_lists_#1_seq } + 1 } }
{ \exp_not:n { #2 } }
}
}
\cs_new_protected:Nn \marinho_lists_output_format:n
{% the private function holds the format
\cs_set:Nn \__marinho_lists_output_current:nn { #1 }
}
\marinho_lists_output_format:n { #1~--~#2 \par } % a default
\cs_new_protected:Nn \marinho_lists_output:n
{% map the sequence using the current format
\seq_map_function:cN { l_marinho_lists_#1_seq } \__marinho_lists_item:n
}
\cs_new:Nn \__marinho_lists_item:n
{% \__marinho_lists_item:n receives an argument in the form {<number>}{<text>}
% which we pass to \__marinho_lists_output_current:nn as two arguments
\__marinho_lists_output_current:nn #1
}
\ExplSyntaxOff
\setlength{\parindent}{0pt} % just for this example
\begin{document}
\section{Fill in the lists}
This section will have no other output.
\addtolist{%
I wanted this whole sentence on this input, even with commas,
without breaking the sentence
}
\addtolist{If I don't use commas then it's ok}
\addtolist[another]{Some text to go first}
\addtolist[another]{Some text to go second}
\addtolist[another]{Some text to go third}
\addtolist{This is in the general list}
\section{Output the \texttt{general} list}
\listoutputformat{Input number #1 is: #2\par}
\outputlist{general}
\section{Output the list named \texttt{another}}
{%
\listoutputformat{(#1) #2\par}
\outputlist{another}
}
\bigskip
Since the code above was in a group, the \texttt{general}
list will now be output identically as before.
\bigskip
\outputlist{general}
\section{We can do in a \texttt{tabular}}
\listoutputformat{#1 & #2 \\}% for a table
\begin{tabular}{ll}
\toprule
N & \multicolumn{1}{c}{Text} \\
\midrule
\outputlist{another}
\bottomrule
\end{tabular}
\end{document}
선택적 인수가 없으면 \addtolist
"일반" 목록에 추가됩니다. 원하는 만큼 목록을 정의할 수 있습니다. 목록을 출력할 때 \listoutputformat
기본 형식이 적합하지 않은 경우 명령을 사용하십시오. 이는 예제에 표시된 대로 그룹화를 존중합니다.
마지막 예에서는 \outputlist
목록의 모든 항목이 테이블 행을 형성하는 한 매크로를 사용하여 테이블을 작성할 수 있음을 보여줍니다.
카운트를 다시 시작할 수 있는 다른 버전입니다 \addtolist*
(여러 목록은 여전히 허용됨).
\documentclass{article}
\usepackage{xparse}
\usepackage{booktabs} % for the last example
\ExplSyntaxOn
% first define the user interface
\NewDocumentCommand{\addtolist}{sO{general}m}
{
\IfBooleanTF{#1}
{ \marinho_lists_add_restart:nn { #2 } { #3 } }
{ \marinho_lists_add_continue:nn { #2 } { #3 } }
}
\NewDocumentCommand{\listoutputformat}{+m}
{
\marinho_lists_output_format:n { #1 }
}
\NewDocumentCommand{\outputlist}{m}
{
\marinho_lists_output:n { #1 }
}
% define the internal functions
\cs_new_protected:Nn \__marinho_lists_check:n
{
% create the sequence if it doesn't exist
\seq_if_exist:cF { l_marinho_lists_#1_seq }
{
\seq_new:c { l_marinho_lists_#1_seq }
\int_new:c { l_marinho_lists_#1_int }
\int_incr:c { l_marinho_lists_#1_int }
}
}
\cs_new_protected:Nn \marinho_lists_add_restart:nn
{
\__marinho_lists_check:n { #1 }
% add the item in the form {<number>}{<text>}
\int_set:cn { l_marinho_lists_#1_int } { 1 }
\seq_put_right:cx { l_marinho_lists_#1_seq }
{
{ \int_eval:n { \int_use:c { l_marinho_lists_#1_int } } }
{ \exp_not:n { #2 } }
}
\int_incr:c { l_marinho_lists_#1_int }
}
\cs_new_protected:Nn \marinho_lists_add_continue:nn
{
\__marinho_lists_check:n { #1 }
% add the item in the form {<number>}{<text>}
\seq_put_right:cx { l_marinho_lists_#1_seq }
{% compute the number based on the sequence length
{ \int_eval:n { \int_use:c { l_marinho_lists_#1_int } } }
{ \exp_not:n { #2 } }
}
\int_incr:c { l_marinho_lists_#1_int }
}
\cs_new_protected:Nn \marinho_lists_output_format:n
{% the private function holds the format
\cs_set:Nn \__marinho_lists_output_current:nn { #1 }
}
\marinho_lists_output_format:n { #1~--~#2 \par } % a default
\cs_new_protected:Nn \marinho_lists_output:n
{% map the sequence using the current format
\seq_map_function:cN { l_marinho_lists_#1_seq } \__marinho_lists_item:n
}
\cs_new:Nn \__marinho_lists_item:n
{% \__marinho_lists_item:n receives an argument in the form {<number>}{<text>}
% which we pass to \__marinho_lists_output_current:nn as two arguments
\__marinho_lists_output_current:nn #1
}
\ExplSyntaxOff
\setlength{\parindent}{0pt} % just for this example
\begin{document}
\section{Fill in the lists}
This section will have no other output.
\addtolist{%
I wanted this whole sentence on this input, even with commas,
without breaking the sentence
}
\addtolist{If I don't use commas then it's ok}
\addtolist{This is in the general list}
\addtolist*{This will have number 1}
\addtolist{This will have number 2}
\section{Output the \texttt{general} list}
\listoutputformat{Input number #1 is: #2\par}
\outputlist{general}
\section{We can do in a \texttt{tabular}}
\listoutputformat{#1 & #2 \\}% for a table
\begin{tabular}{lp{6cm}}
\toprule
N & \multicolumn{1}{c}{Text} \\
\midrule
\outputlist{general}
\bottomrule
\end{tabular}
\end{document}
답변2
귀하가 게시하는 거의 모든 코드는 쉼표로 구분된 목록을 통해 구현되고 있지만 \cptdocommalist
귀하의 질문에 따르면 전혀 원하지 않는다는 것을 의미한다고 생각합니다.
\documentclass{article}
\newcount\mycount
\newtoks\mylist
%odd name for this command? what is the "name" here?
\def\inputcommandname#1{%
\advance\mycount1
\mylist\expandafter{\the\expandafter\mylist
\expandafter\mydo\expandafter
{\the\mycount}{#1}}}
\def\commandnameoutputformat{\def\mydo##1##2}
\def\outputinnormalorder{\the\mylist}
\begin{document}
\inputcommandname{I wanted this whole sentence on this input, but when I use a comma it breaks the input and starts a new one}
\inputcommandname{If I don't use commas then it's ok}
\commandnameoutputformat{\par Input number #1 is: #2.\par}
Output:\par
\outputinnormalorder
\end{document}