Estou tentando zerar o contador toda vez que encontro um section
com base nissodocumento.
\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}
Isto irá gerar
o que significa que funciona.
No entanto, agora quero remover o número antes da seção, então adicionei *
depois 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}
No entanto, desta vez, o contador não será zerado como
Se eu mudasse para
\newcounter{example}[section*]
Isso gerará erro
Nenhuma 'seção*' do contador definida.
Como zerar o contador quando se encontra section*
?
Responder1
Você recebeu um erro \newcounter{example}[section*]
porque section*
não é um contador no LaTeX. section
é, mas não section*
.
Primeiro método: patch\@startsection
Você pode corrigir \@startsection
para que quando \section*
for chamado (que é um comando de seccionamento de nível 1) e somente neste caso, seu example
contador seja zerado. O seguinte funciona porque \@ssect
só é chamado para comandos de seccionamento não numerados, e só zeramos o contador quando o nível do comando de corte é 1 ( \section
ou \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: usando xparse
para redefinir\section
Outra maneira de obter o mesmo resultado é usar xparse
para redefinir \section
, como egreg fez emesta resposta. A vantagem desta técnica é que ela não depende de detalhes de implementação de \section
e \@startsection
, portanto ela deve sempre funcionar mesmo que \section
tenha sido redefinida e não seja \section
mais um comando do LaTeX2e - este pode ser o caso se você redefinir \section
usando um pacote como titlesec
, ou simplesmente se você tentar acumular várias redefinições feitas com a primeira técnica. Assim, eu diria que este segundo método é melhor do ponto de vista da engenharia.
\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 as técnicas levam à seguinte saída:
Observações sobre a implementação de ambientes definidos pelo usuário
Em seu ambiente real, você pode querer fazer algo assim (ou uma variante) para ter certeza de que sua entrada não introduz espaços indesejados. Esta é uma observação geral sobre ambientes definidos pelo usuário; já que \subsection*
normalmente inicia um novo parágrafo - a menos que você esteja usando ocorrer emtipo de layout – \ignorespaces
provavelmente não é necessário aqui, por exemplo. Da mesma forma, \ignorespacesafterend
não deveria ser necessário after \par\medskip
, pois \par
coloca o TeX no modo vertical onde os espaços são ignorados - mas não deve prejudicar, no entanto.
\newenvironment{example}[1][]
{\refstepcounter{example}\par\medskip
\subsection*{Example~\theexample. #1}%
\rmfamily
\ignorespaces}
{\unskip
\par\medskip
\ignorespacesafterend}