Однажды я нашел в Интернете этот фрагмент кода, который, как я недавно заметил, полностью поможет мне с моей проблемой. Вот код:
\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}