Versiones abstractas

Versiones abstractas

Me gustaría definir un comando de 'construcción de macros' de TeX (llamémoslo \buildmacro) que tome como argumento una cadena de caracteres 'normales' (por ejemplo, Title) y que satisfaga lo siguiente:

  • el comando \buildmacro{Title}define el contador con el nombre TitleXcountery lo inicializa a 0.
  • al emitir en algún punto del archivo el comando TeX \Title{<arg>}, esto tendrá el efecto de aumentar el contador TitleXcountery luego poner el valor <arg>en una nueva macro TeX con el nombre \Title-<x>, donde <x>está el valor actual de TitleXcounter;

    aquí, <arg>hay un fragmento de código TeX (que puede contener texto, matemáticas, párrafos de cualquier otro comando TeX).

Considere el siguiente ejemplo mínimo:

\documentclass{article}
\usepackage{ifthen}


\def\buildmacro#1{...}% the definition of \buildmacro

\begin{document}

\buildmacro{Title}

% 'Read' several titles

\Title{The first title}
\Title{The second title}
\Title{The third title}

\newcount\tempcount
\tempcount=1\relax

% 'List' all the Titles
\whiledo{\the\tempcount<\numexpr \thetitleXcounter+1\relax}
        {%
         \textsc{\csname title-\the\tempcount\endcsname}\par
         \advance\tempcount by 1\relax
        }

\end{document}

' Jugué' con \csnamey \endcsname, \expandafter, y las versiones, pero sin 'suerte'.\def\gdef\long

Editado(para responder algunos de los comentarios):

El propósito de esto es tener un mecanismo simple para crear un conjunto de comandos indexados con el mismo nombre raíz (similar a una lista de comandos). Siempre se puede utilizar la \csname <...> \endcsnameconstrucción para emitir los comandos.

Respuesta1

A partir de la descripción del flujo requerido, esto parece bastante simple.

\newcommand\buildmacro[1]{%
  % Create a new counter named after the argument
  \newcounter{#1Xcounter}%
  % Create a new command named after the argument,
  % itself taking one argument
  \expandafter\newcommand\csname #1\endcsname[1]{%
    % Step the counter
    \stepcounter(#1Xcounter)%
    % Store the argument
    \expandafter\newcommand\csname #1-\arabic{#1Xcounter}\endcsname
      {##1}%
  }%
}

Como también se solicitó una versión simple.

\long\def\buildmacro#1{%
  \csname newcount\expandafter\endcsname\csname #1Xcounter\endcsname
  \long\expandafter\def\csname #1\endcsname##1{%
    \global\expandafter\advance\csname #1Xcounter\endcsname by 1
    \expandafter\def\csname #1-\expandafter\number\csname #1Xcounter\endcsname
      \endcsname
      {##1}%
  }%
}

Respuesta2

Como mencioné en un comentario, no se pueden usar guiones ni números al construir nombres de macros, a menos que siempre escriba el equivalente \csname ... \endcsnameo se asegure de que los códigos cat se cambien al usarlos.

Por lo tanto, es necesario modificar la interfaz de usuario sugerida.

La idea básica parece ser crear una serie de listas indexadas de argumentos que se pueden recuperar dando el nombre de la lista y el índice del elemento dentro de esa lista.

Esto podría implementarse utilizando listas separadas por comas. A continuación se muestra una interfaz sugerida que utiliza únicamente expl3la sintaxis considerada estable por los desarrolladores:

\buildmacro{<list identifier>}
\addmacro{<list identifier>}{<item to be added>}
\fetchmacro{<list identifier>}{<index of item to be fetched>}
\listmacro{<list identifier>}

El primero configura las cosas inicializando una nueva lista. El segundo agrega un elemento a una lista. El tercero busca un elemento de una lista. El cuarto enumera todos los elementos de una lista de forma secuencial.

Prueba de concepto (aunque difícilmente original):

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new_protected_nopar:Nn \digitalink_buildmacro:n
{
  \clist_new:c { g_digitalink_#1_clist }
}
\NewDocumentCommand \buildmacro { m }
{
  \digitalink_buildmacro:n { #1 }
}
\NewDocumentCommand \addmacro { m +m }
{
  \clist_gput_right:cn { g_digitalink_#1_clist }
  {
    #2
  }
}
\NewDocumentCommand \fetchmacro { m m }
{
  \clist_item:cn { g_digitalink_#1_clist } { #2 }
}
\NewDocumentCommand \listmacro { m }
{
  \clist_use:cn { g_digitalink_#1_clist } { \par }
}
\ExplSyntaxOff
\begin{document}
\buildmacro{dititle}
\addmacro{dititle}{Here's some text.}
\addmacro{dititle}{Here's some more.}
\fetchmacro{dititle}{1}
\fetchmacro{dititle}{2}
\fetchmacro{dititle}{1}

List:

\listmacro{dititle}
\end{document}

prueba de concepto

Respuesta3

A \@namedefy \@nameuseversión, falsificando nombres de 'macro' que no serían posibles sin el cambio de catcode.

La asignación del \newcounterinterior de las macros puede causar problemas con los registros del contador.

\documentclass{article}

\makeatletter
\newcommand{\buildmacro}[1]{%
  \newcounter{#1Xcounter}%
    \expandafter\newcommand\csname #1\endcsname[1]{%
      \stepcounter{#1Xcounter}%
      \@namedef{#1-\number\value{#1Xcounter}}{##1}%
  }
}

\newcommand{\displaymacrocontent}[2]{%
  \@nameuse{#1-#2}%
}
\makeatother



\begin{document}

\buildmacro{Title}
\Title{The first title}
\Title{The second title}
\Title{The third title}

\newcount\tmpcntr

\loop\unless\ifnum\tmpcntr > 4
\advance\tmpcntr by 1
\displaymacrocontent{Title}{\number\tmpcntr}

\repeat



\end{document}

ingrese la descripción de la imagen aquí

Respuesta4

El efecto que estás mostrando en tu pseudocódigo se obtiene mucho más fácilmente con una macro de lista, que permite hacer un bucle sin tener que saber cuántos objetos hay en él y sin contar pasos.

\documentclass{article}

\makeatletter
\newcommand{\Titlecontainer}{\@empty}% initialize
\newcommand{\Title}[1]{%
  \expandafter\def\expandafter\Titlecontainer\expandafter{%
    \Titlecontainer\LISTSEP{#1}%
  }%
}
\makeatother

\begin{document}

\Title{The first title}
\Title{The second title}
\Title{The third title}

% 'List' all the Titles
\begingroup % keep the change to \LISTSEP local
\def\LISTSEP#1{\textsc{#1}\par}
\Titlecontainer
\endgroup

\end{document}

ingrese la descripción de la imagen aquí

Una versión “abstracta”:

\documentclass{article}

\makeatletter
\newcommand{\Titlecontainer}{\@empty}% initialize
\newcommand{\Title}[1]{%
  \expandafter\def\expandafter\Titlecontainer\expandafter{%
    \Titlecontainer\LISTSEP{#1}%
  }%
}
\newcommand{\listmap}[2]{% #1 is the list name, #2 the code
  \begingroup\def\LISTSEP##1{#2}#1\endgroup
}
\makeatother

\begin{document}

\Title{The first title}
\Title{The second title}
\Title{The third title}

% 'List' all the Titles
\listmap{\Titlecontainer}{\textsc{#1}\par}

\end{document}

Aún más fácil con expl3:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\Title}{m}
 {
  \seq_put_right:Nn \digitalink_titles_seq { #1 }
 }
\NewDocumentCommand{\ProcessTitles}{+m}
 {
  \seq_map_inline:Nn \digitalink_titles_seq { #1 }
 }
\seq_new:N \digitalink_titles_seq
\ExplSyntaxOff

\begin{document}

\Title{The first title}
\Title{The second title}
\Title{The third title}

\ProcessTitles{\textsc{#1}\par}

\newcounter{titlecount}
\ProcessTitles{\stepcounter{titlecount}\arabic{titlecount} -- #1\par}

\end{document}

ingrese la descripción de la imagen aquí


Versiones abstractas

Método clásico

\documentclass{article}

\makeatletter
\newcommand{\definelist}[1]{%
  \@namedef{#1}##1{%
    \expandafter\def\csname #1@container\expandafter\expandafter\expandafter\endcsname
    \expandafter\expandafter\expandafter{%
      \csname #1@container\endcsname\LISTSEP{##1}%
    }%
  }%
  \@namedef{#1@container}{\@empty}% initialize
}
\newcommand{\maplist}[2]{%
  \begingroup
  \def\LISTSEP##1{#2}%
  \@nameuse{#1@container}%
  \endgroup
}
\makeatother

\definelist{Title}

\begin{document}

\Title{The first title}
\Title{The second title}
\Title{The third title}

% 'List' all the Titles
\maplist{Title}{\textsc{#1}\par}

\newcounter{tempcount}
\maplist{Title}{\stepcounter{tempcount}\arabic{tempcount} -- #1\par}

\end{document}

Conexpl3

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\definelist}{m}
 {
  \seq_new:c { l_digitalink_list_#1_seq }
  \cs_new_protected:cpn { #1 } ##1
   {
    \seq_put_right:cn { l_digitalink_list_#1_seq } { ##1 }
   }
 }
\NewDocumentCommand{\maplist}{m +m}
 {
  \seq_map_inline:cn { l_digitalink_list_#1_seq } { #2 }
 }
\ExplSyntaxOff

\definelist{Title}

\begin{document}

\Title{The first title}
\Title{The second title}
\Title{The third title}

% 'List' all the Titles
\maplist{Title}{\textsc{#1}\par}

\newcounter{tempcount}
\maplist{Title}{\stepcounter{tempcount}\arabic{tempcount} -- #1\par}

\end{document}

información relacionada