Estoy intentando restablecer el contador cada vez que encuentro algo section
basado en esto.doc.
\documentclass{article}
\newcounter{example}[section] % This line reset the counter every time meet a section
\newenvironment{example}[1][]
{\refstepcounter{example}\par\medskip
\subsection*{Example~\theexample. #1} \rmfamily}
{\medskip}
\begin{document}
\section{Section}
\begin{example}
A
\end{example}
\begin{example}
B
\end{example}
\section{Another section}
\begin{example}
C
\end{example}
\end{document}
Esto generará
lo que significa que funciona.
Sin embargo, ahora quiero eliminar el número antes de la sección, así que agregué *
después section
.
\documentclass{article}
\newcounter{example}[section] % Tried to change `section*`, but throws error
\newenvironment{example}[1][]
{\refstepcounter{example}\par\medskip
\subsection*{Example~\theexample. #1} \rmfamily}
{\medskip}
\begin{document}
\section*{Section}
\begin{example}
A
\end{example}
\begin{example}
B
\end{example}
\section*{Another section}
\begin{example}
C
\end{example}
\end{document}
Sin embargo, esta vez, el contador no se reiniciará como
Si cambié a
\newcounter{example}[section*]
arrojará error
No hay ningún contador 'sección*' definido.
¿Cómo restablecer el contador cuando nos reunimos section*
?
Respuesta1
Obtuviste un error \newcounter{example}[section*]
porque section*
no es un contador en LaTeX. section
lo es, pero no section*
.
Primer método: parchear\@startsection
Puede parchear \@startsection
para que \section*
se llame cuando (que es un comando de sección de nivel 1) y solo en este caso, su example
contador se reinicie a 0. Lo siguiente funciona porque \@ssect
solo se llama para comandos de sección no numerados, y solo reiniciamos el contador cuando el nivel del comando de seccionamiento es 1 ( \section
o \section*
).
\documentclass{article}
\usepackage{etoolbox}
\newcounter{example}[section]
\newenvironment{example}[1][]
{\refstepcounter{example}\par\medskip
\subsection*{Example~\theexample. #1}%
\rmfamily}
{\medskip}
\makeatletter
\patchcmd{\@startsection}
{\@ssect}{\ifnum#2=1 \setcounter{example}{0}\fi\@ssect}
{}{\FAILED}
\makeatother
\begin{document}
\section*{Section}
\begin{example}
A
\end{example}
\begin{example}
B
\end{example}
\section*{Another section}
\begin{example}
C
\end{example}
\begin{example}
D
\end{example}
\section{Numbered section}
\begin{example}
E
\end{example}
\begin{example}
F
\end{example}
\end{document}
Segundo método: usar xparse
para redefinir\section
Otra forma de lograr el mismo resultado es usar xparse
para redefinir \section
, como lo hizo egreg enesta respuesta. La ventaja de esta técnica es que no depende de los detalles de implementación de \section
y \@startsection
, por lo tanto, siempre debería funcionar incluso si \section
se ha redefinido y \section
ya no es un comando de LaTeX2e; este puede ser el caso si redefine \section
usando un paquete como titlesec
, o simplemente si intentas acumular varias redefiniciones hechas con la primera técnica. Por tanto, diría que este segundo método es mejor desde el punto de vista de la ingeniería.
\documentclass{article}
\usepackage{xparse}
\newcounter{example}[section]
\newenvironment{example}[1][]
{\refstepcounter{example}\par\medskip
\subsection*{Example~\theexample. #1}%
\rmfamily}
{\medskip}
% Save the original \section command
\let\latexsection\section
% Simple redefinition of \section (including \section*)
\RenewDocumentCommand{\section}{sO{#3}m}{%
\IfBooleanTF{#1}
{\setcounter{example}{0}%
\latexsection*{#3}}
{\latexsection[#2]{#3}}%
}
\begin{document}
\section*{Section}
\begin{example}
A
\end{example}
\begin{example}
B
\end{example}
\section*{Another section}
\begin{example}
C
\end{example}
\begin{example}
D
\end{example}
\section{Numbered section}
\begin{example}
E
\end{example}
\begin{example}
F
\end{example}
\end{document}
Ambas técnicas conducen al siguiente resultado:
Comentarios sobre la implementación de entornos definidos por el usuario
En su entorno real, es posible que desee hacer algo como esto (o una variante) para asegurarse de que su entrada no introduzca espacios no deseados. Esta es una observación general sobre entornos definidos por el usuario; ya que \subsection*
normalmente comienza un nuevo párrafo, a menos que esté utilizando elentrar corriendotipo de diseño: \ignorespaces
probablemente no sea necesario aquí, por ejemplo. De manera similar, \ignorespacesafterend
no debería ser necesario after \par\medskip
, ya que \par
coloca TeX en modo vertical donde se ignoran los espacios, pero de todos modos no debería hacer daño.
\newenvironment{example}[1][]
{\refstepcounter{example}\par\medskip
\subsection*{Example~\theexample. #1}%
\rmfamily
\ignorespaces}
{\unskip
\par\medskip
\ignorespacesafterend}