Una vez encontré en Internet este fragmento de código que recientemente noté que me ayudaría totalmente con un problema que tengo. Aquí está el código:
\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}
Entonces, aquí está el problema: quiero que el código haga exactamente lo que hace (almacenar variables que se repiten sobre un comando) pero sin crear automáticamente nuevas entradas cada vez que escribo comas. He intentado cambiarlo, pero siempre he fallado. ¿Podrían modificarlo para que funcione de esa manera (sin "romper comas")? Gracias por la atención.
Respuesta1
Puede obtener un código flexible usando 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}
Sin un argumento opcional, \addtolist
se agrega a la lista "general". Puedes definir tantas listas como quieras. Al generar una lista, utilice un \listoutputformat
comando si el formato predeterminado no es adecuado. Esto respeta la agrupación, como se muestra en el ejemplo.
El ejemplo final muestra que puede usar la \outputlist
macro para crear una tabla, siempre que cada elemento de la lista forme una fila de la tabla.
Una versión diferente que permite reiniciar el conteo, con \addtolist*
(aún se permiten varias listas).
\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}
Respuesta2
casi todo el código que publicas se implementa en una lista separada por comas, \cptdocommalist
pero creo que tu pregunta implica que no quieres eso en absoluto, pero tal vez
\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}