
El siguiente ejemplo muestra que el contador autodefinido en el tabularx
entorno no comienza con "1". No puedo entender cómo definir el comando para que siempre comience con "1". ¿Ideas?
\documentclass{article}
\usepackage{enumitem}
\usepackage{cleveref}
\usepackage{etoolbox}
\usepackage{booktabs}
\usepackage{ltxtable}
\usepackage{ltablex}
\makeatletter\newcommand*{%
\CreateCounterIfNotExists}[1]{\begingroup%
\@ifundefined{c@#1}{\newcounter{#1}}{}%
\endgroup}\makeatother
\def\sdef#1{\expandafter\def\csname#1\endcsname}
\newcommand\requirement[3]{%
\CreateCounterIfNotExists{my#1}%
\sdef{themy#1}{#1\arabic{my#1}}%
\refstepcounter{my#1}%
\label{#2} #1\arabic{my#1}: #3%
}
\begin{document}
\requirement{A}{req:foo:a}{Starts with 1}
\requirement{A}{req:foo:b}{continues with 2}
\requirement{B}{req:hop:a}{Starts with 1}
\requirement{B}{req:hop:b}{continues with 2}
\begin{tabularx}{\textwidth}{lX}
\caption{Requirements}\\
\label{tbl:reqs}\\
\toprule
\textbf{Area}& \textbf{Description} \\\midrule
\requirement{C}{req:bar:A}{Starts with 3}
\requirement{C}{req:bar:B}{Continues with 4}
&
This should start with C1 \\\midrule
\end{tabularx}
\end{document}
Respuesta1
No puedes definir contadores mientras tabularx
hace su trabajo.
Una solución puede ser definir el que necesitas de tabularx
antemano, o hacerlo en diferido usando el .aux
archivo.
\documentclass{article}
\usepackage{enumitem}
\usepackage{etoolbox}
\usepackage{booktabs}
\usepackage{ltxtable}
\usepackage{ltablex}
\usepackage{cleveref}
\makeatletter
\newcommand\requirement[3]{%
\protected@write\@auxout{}{\string\CreateCounter{#1}}%
\@ifundefined{c@my#1}
{#1??: #3}
{\refstepcounter{my#1}\label{#2}#1\arabic{my#1}: #3}%
}
\newcommand{\CreateCounter}[1]{%
\@ifundefined{c@my#1}
{\newcounter{my#1}\global\@namedef{themy#1}{#1\arabic{my#1}}}
{}%
}
\AtEndDocument{\let\CreateCounter\@gobble}
\makeatother
\begin{document}
{\requirement{A}{req:foo:a}{Starts with 1}}
\requirement{A}{req:foo:b}{continues with 2}
\requirement{B}{req:hop:a}{Starts with 1}
\requirement{B}{req:hop:b}{continues with 2}
\noindent
\begin{tabularx}{\textwidth}{lX}
\caption{Requirements}\label{tbl:reqs}\\
\toprule
\textbf{Area}& \textbf{Description} \\
\midrule
\requirement{C}{req:bar:A}{Starts with 1}
\requirement{C}{req:bar:B}{Continues with 2} & This should start with C1 \\
\midrule
\end{tabularx}
\end{document}
La primera vez \requirement{X}
que se utiliza, el número no se generará, pero sí en la siguiente ejecución de LaTeX.
Respuesta2
Casi nunca debes declarar un contador dentro de una macro, debes declararlo una vez en el preámbulo y solo usarlo. entonces tabularx
lo sabría y conservaría su valor al realizar la configuración de ancho de prueba.
\documentclass{article}
\usepackage{enumitem}
\usepackage{cleveref}
\usepackage{etoolbox}
\usepackage{booktabs}
\usepackage{ltxtable}
\usepackage{ltablex}
\newcounter{myA}\renewcommand\themyA{A\arabic{myA}}
\newcounter{myB}\renewcommand\themyB{B\arabic{myB}}
\newcounter{myC}\renewcommand\themyC{C\arabic{myC}}
\newcommand\requirement[3]{%
\refstepcounter{my#1}%
\label{#2}#1\arabic{my#1}: #3%
}
\begin{document}
\requirement{A}{req:foo:a}{Starts with 1}
\requirement{A}{req:foo:b}{continues with 2}
\requirement{B}{req:hop:a}{Starts with 1}
\requirement{B}{req:hop:b}{continues with 2}
\begin{tabularx}{\textwidth}{lX}
\caption{Requirements}\\
\label{tbl:reqs}\\
\toprule
\textbf{Area}& \textbf{Description} \\\midrule
\requirement{C}{req:bar:A}{Starts with 3}
\requirement{C}{req:bar:B}{Continues with 4}
&
This should start with C1 \\\midrule
\end{tabularx}
\end{document}
Respuesta3
Como en las soluciones mencionadas por David Carlisle y egreg: los contadores no deben definirse on-the-fly
.
Utilicé un enfoque similar al de David Carlisle, proporcionando comandos \NewDocumentCounter
, \DeclareRequirement
, DeclareRequirements
que se pueden usar solo en el preámbulo, para evitar el uso accidental.
\documentclass{article}
\usepackage{enumitem}
\usepackage{etoolbox}
\usepackage{booktabs}
\usepackage{ltxtable}
\usepackage{ltablex}
\usepackage{cleveref}
\usepackage{xparse}
\NewDocumentCommand{\NewDocumentCounter}{m}{%
\ifltxcounter{#1}{%
}{%
\typeout{Creating counter #1}
\newcounter{#1}%
}
}
\NewDocumentCommand{\DeclareRequirement}{m}{%
\NewDocumentCounter{my#1}%
\expandafter\renewcommand\csname themy#1\endcsname{#1\arabic{my#1}}
}%
\listgadd\reqlist{}
\NewDocumentCommand{\DeclareRequirements}{+m}{%
\forcsvlist{\listgadd\reqlist}{#1}
\forlistloop{\DeclareRequirement}{\reqlist}
}%
\makeatletter
\@onlypreamble{\NewDocumentCounter}
\@onlypreamble{\DeclareRequirement}
\@onlypreamble{\DeclareRequirements}
\makeatother
\DeclareRequirements{A,B,C} % Declare all requirement counters in a row ...
\newcommand\requirement[3]{%
\refstepcounter{my#1}%
\label{#2} #1\arabic{my#1}: #3%
}
\begin{document}
\requirement{A}{req:foo:a}{Starts with 1}
\requirement{A}{req:foo:b}{continues with 2}
\requirement{B}{req:hop:a}{Starts with 1}
\requirement{B}{req:hop:b}{continues with 2}
\begin{tabularx}{\textwidth}{lX}
\caption{Requirements}\\
\label{tbl:reqs}\\
\toprule
\textbf{Area}& \textbf{Description} \\\midrule
\requirement{C}{req:bar:A}{Starts with 3 no longer} %\themyC
\requirement{C}{req:bar:B}{Continues with 4 no longer} %\themyC
&
This should start with C1 \\\midrule
\end{tabularx}
\end{document}