将宏/新命令范围限制在部分内

将宏/新命令范围限制在部分内

如何将 a 的范围限制\newcommand为 a \section?这就是我想要的:

  1. 该命令仅在内部定义\section,而不是全局定义;
  2. 命令范围就是它本身\section,在其之外是看不到的;
  3. a 是否看到该命令并不重要\subsection(如果它也看到该命令,那可能就说得通了);并且
  4. 可以在不同的命令中再次定义该命令\section而不会产生错误(我知道这\renewcommand可以解决它,但如果可能的话我愿意使用它\newcommand)。

我所拥有的是(由于这两个定义而产生错误):

\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}

[编辑] 就我的具体情况而言,我将\newcommand在一个部分中拥有大约 20-30 个不同的内容,这些内容可能会或可能不会在文档的不同部分中使用(重新定义)。

答案1

您可以添加代码\section以使其\blipo未定义:

\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}

以下是终端会话的一部分:

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

在此处输入图片描述


对于更通用的版本,如果您希望在每个部分中有几个命令未定义,请使用以下列表处理函数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}

我们在\preto的开头添加代码\section。如果您使用的类或包重新定义\section,则可能需要使用

\usepackage{xpatch}

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

反而。

2023 年更新

利用 LaTeX 内核的当前特性:

\documentclass{article}

\ExplSyntaxOn

\clist_new:N \g_daniel_onlysection_commands_clist

\NewDocumentCommand{\onlysectioncommands}{m}
 {
  \clist_gput_right:Nn \g_daniel_onlysection_commands_clist { #1 }
 }

\AddToHook{cmd/section/before}
 {
  \clist_map_function:NN \g_daniel_onlysection_commands_clist \cs_undefine:N
 }

\ExplSyntaxOff
  
%%% Here we set the special commands and
%%% 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}

\verb|\blipo| is not defined here, attempt to use it generates error.
\blipo{}
\foo

\end{document}

答案2

看起来这个问题可以通过用括号括起来来解决。一个最简单的例子如下:

\documentclass[10pt,a4paper]{article}
\begin{document}

\section{Section A}
{
\newcommand{\sectionowner}{me}
This section belongs to \sectionowner
}
\section{Section B}
{
\newcommand{\sectionowner}{you}
This section belongs to \sectionowner
}

\end{document}

\sectionowner其中使用 定义了两次命令\newcommand

答案3

使用\renewcommand

\documentclass{article}
\begin{document}

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

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

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

\end{document}

相关内容