[Tex/LaTex] Limit macro/newcommand scope to section

groupingmacros

How can I limit the scope of a \newcommand to a \section? This is what I'd like to have:

  1. The command is defined only inside the \section, not globally;
  2. The command scope is that \section and cannot be seen outside of it;
  3. It should not matter if a \subsection sees the command or not (it probably makes sense that it sees it as well); and
  4. The command can be defined again in a different \section without generating errors (I know that \renewcommand could solve it but I'd like to use \newcommand if possible).

What I have is (which generates an error because of the two definitions):

\documentclass{article}
\begin{document}

\section{First section}
\newcommand*{\blipo}{Jill}
Hello \blipo{}. \blipo{} is blonde.

\section{Second section}
\newcommand*{\blipo}{ET}
Hello \blipo{}. \blipo{} is green.

\section{Third section}
Not defined here. Attempt to use it generates error.

\end{document}

[edit] In my particular case, I'll be having around 20-30 different \newcommand in a single section which may or may not be used (redefined) in different sections of the document.

Best Answer

You can add code to \section so that \blipo gets undefined:

\documentclass{article}
\usepackage{etoolbox}

\preto\section{\undef\blipo}


\begin{document}

\section{First section}
\newcommand*{\blipo}{Jill}
Hello \blipo{}. \blipo{} is blonde.

\section{Second section}
\newcommand*{\blipo}{ET}
Hello \blipo{}. \blipo{} is green.

\section{Third section}
Not defined here. Attempt to use it generates error.
\blipo{}

\end{document}

Here's a piece of the terminal session:

! Undefined control sequence.
l.19 \blipo
           {}
?

enter image description here


For a more general version, where you want several commands to get undefined at each section, use the list processing functions of etoolbox:

\documentclass{article}
\usepackage{etoolbox}

%%% The helper macros
\newcommand{\onlysectioncommands}[1]{%
  \forcsvlist{\listadd\sectioncommandslist}{#1}}
\preto\section{%
  \forlistloop{\undef}{\sectioncommandslist}}

%%% Here we set the special commands; the
%%% list can be augmented anywhere
\onlysectioncommands{\blipo,\foo}


\begin{document}

\section{First section}
\newcommand*{\blipo}{Jill}
\newcommand{\foo}{foo}

Hello \blipo{}. \blipo{} is blonde. \foo

\section{Second section}
\newcommand*{\blipo}{ET}
\newcommand{\foo}{bar}

Hello \blipo{}. \blipo{} is green. \foo

\section{Third section}
\newcommand{\foo}{baz}

Not defined here. Attempt to use it generates error.
\blipo{}
\foo

\end{document}

With \preto we add code at the start of \section. If the class or packages you're using redefine \section, you may need to use

\usepackage{xpatch}

\xpretocmd{\section}
  {\forlistloop{\undef}{\sectioncommandslist}}
  {}{}

instead.

Related Question