在宏之前和之后执行“makeatletter”代码

在宏之前和之后执行“makeatletter”代码

我正在使用子文件包来处理大型项目。

我将主文件放在主目录中,将子文件放在子目录中。为了在主文件中编译时在子文件中使用 \input 命令,我需要在 \subfile 命令之前手动更改输入路径,然后在之后恢复。

示例代码如下(复制自此处回答),

\makeatletter
\providecommand*{\input@path}{}
\edef\input@path{{subfile_path/}\input@path}% subfolder path
\makeatother

\subfile{subfile_path/subfile}

\makeatletter
\providecommand*{\input@path}{}
\edef\input@path{{./}\input@path}% restore
\makeatother

我想问一下是否可以将“makeatletter”代码封装到命令中。我尝试定义一个新命令

\newcommand{\autosubfile}[2]{
  \makeatletter
  \providecommand*{\input@path}{}
  \edef\input@path{{#1/}\input@path}% subfolder path
  \makeatother
  \subfile{#1/#2}
  \makeatletter
  \providecommand*{\input@path}{}
  \edef\input@path{{./}\input@path}% restore
  \makeatother
}

但如果失败了。以下是错误消息:

ERROR: LaTeX Error: Command \input already defined.

--- TeX said ---
               Or name \end... illegal, see p.192 of the manual.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...                                              

本文提到的 etoolbox 包回答可能会有帮助,但我不知道如何更改 \subfile 的参数数量,或者定义一个新命令来执行“makeatletter”代码片段。

谢谢你的帮助。

答案1

你应该有\makeatletter @任何使用名称中的命令的定义。

您还含糊其辞地给出了您所指的答案。

  1. \providecommand{\input@path}{}只需做一次。
  2. 您不断地添加内容\input@path而不是恢复内容。

您可以这样做:

\makeatletter
\providecommand*{\input@path}{} % in case it's undefined
\newcommand{\autosubfile}[2]{% <- don't forget
  % save the current \input@path
  \let\saved@input@path\input@path
  \edef\input@path{{#1/}\input@path}% subfolder path
  \subfile{#1/#2}%
  % restore \input@path to its previous value
  \let\input@path\saved@input@path
}
\makeatother

答案2

你的错误(在用户开始了解 TeX 功能时很常见)是基于对 TeX 中 tokenizer 和扩展处理器的协作的误解。Tokenizer\foo总是像一个 token一样创建控制序列当数据第一次从输入文件读取时。宏被保存在 TeX 内存中,作为 tokenizer 创建的 token 序列,而不是字符串。当宏被展开时,展开处理器会将 token 序列更改为另一个 token 序列。

举例来说:

\def\yourmacro{
    \makeatletter %... instruction for tokenizer in your example
        % this is not processed when macro body is read, 
        % this is saved only to TeX memory
    \foo@bar  %... tokenizer creates \foo and @ and b and a and r
              % and this is saved to TeX memory in macro body
    \makeaother %... instruction for tokenizer without effect
}

... usage of \yourmacro % expand processor replaces it by \makeatletter
                        % followed by \foo, @, b, a, r and \makeatother.
                        % Now, \makeatletter is instruction for tokenizer without
                        % effect because \foo, @, b, a, r are tokenized already.

另一方面正确的用法:

\makeatletter %... instrution for tokenizer, all new read data are
              % tokenized differently now.
\def\yourmacro{
   ...
   \foo@bar   % one token \foo@bar is saved to TeX memory in macro body
   ...
}
\makeatother % instruction for tokenizer to behave normally

... usage of \yourmacro % expand processor replaces it by ... \foo@bar ...

相关内容