如何克服无法创建以“\end”开头的命令的问题

如何克服无法创建以“\end”开头的命令的问题

以下简单文件在编译期间出现错误:

\documentclass{article}
\newcommand{\enda}{E}
\begin{document}
dddd
\end{document}

错误信息是:

! LaTeX Error: Command \enda already defined.
           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.
...                                              

l.2 \newcommand{\enda}{E}

Your command was ignored.
Type  I <command> <return>  to replace it with another command,
or  <return>  to continue without it.

似乎无论我在 Latex 后面输入什么\end(例如\endb\endklghfsgfljs或任何有效的命令名称)都会产生相同的错误。当将dofend更改为另一个字母(例如,s)时,这似乎没问题。

我如何定义一个我想要的名称的命令?

笔记:我的问题不是这是否是保留字,而是如何绕过阻塞。一个稍微不同的问题是在 latex2e 中保留的结束宏名称。我无法找到符合我意图的问题。我希望遇到和我相同问题的人能比链接中的问题更容易找到这个问题。

答案1

这是由于环境的工作方式而“设计”的。不过,你可以使用 TeX\def原语

\documentclass{article}
\def\enda{\operatorname{End}}
\begin{document}
dddd \enda
\end{document}

但前提是所调用的环境a将是一个问题!

答案2

\NewDocumentCommand您可以利用不检查初始的事实\end,但只不允许定义现存的(即已经明确定义的)命令。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\newendcommand}{smO{0}om}
 {
  \cs_if_exist:NTF #2
   {% don't want to redefine anyway
    \newcommand{#2}{}%
   }
   {
    \IfBooleanTF { #1 }
     {% short
      \tl_set:Nn \l__farreo_newendcommand_arg_tl { m }
     }
     {% long
      \tl_set:Nn \l__farreo_newendcommand_arg_tl { +m }
     }
    \farreo_newendcommand:nnnn { #2 } { #3 } { #4 } { #5 }
   }
 }

\tl_new:N \l__farreo_newendcommand_arg_tl

\cs_new_protected:Nn \farreo_newendcommand:nnnn
 {
  \tl_if_novalue:nTF { #3 }
   {% no optional argument
    \exp_args:NNx
    \NewExpandableDocumentCommand
    #1
    { \prg_replicate:nn { #2 } { \l__farreo_newendcommand_arg_tl } }
    { #4 }
   }
   {
    \exp_args:NNx
    \NewDocumentCommand
    #1
    {
     \exp_not:n { +O{#3} }
     \prg_replicate:nn { #2 - 1 } { \l__farreo_newendcommand_arg_tl }
    }
    { #4 }
   }
 }
\ExplSyntaxOff

\newendcommand\endenumerate[1]{x} % <-- error
\newendcommand{\endo}{E}
\newendcommand{\endopt}[2][OPT]{{\ttfamily\#1=#1, \#2=\detokenize{#2}}}
\newendcommand*{\endstar}[1]{{\ttfamily\#1=#1}}

\begin{document}

\endo

\endopt{x}

\endopt[Y]{x\par}

\endstar{x\par} % <-- error

\end{document}

当然,您可以直接使用\NewDocumentCommand;它需要与不同的语法\newcommand,但功能更强大。

该指令\newendcommand{\endenumerate}{}引发错误

! LaTeX Error: Command \endenumerate already defined.
               Or name \end... illegal, see p.192 of the manual.

最后一次调用\endstar{x\par}却引发了错误

Runaway argument?
{x
! Paragraph ended before \endstar  was complete.

因为\endstar已被调用\newendcommand*。相反,在其参数中\endopt接受。\par

enter image description here

答案3

\newcommand内部用于\@ifdefinable检查命令是否可定义。

在其他内容下,\@ifdefinable检查相关命令名称的前三个字母是否为e, n, d。为此,\ifx将对宏进行比较,\@qend该宏的扩展会将这些字母作为类别代码 12(其他)的显式字符标记。

如果愿意,您可以暂时用\@qend在您想要的命令名称的“字符串化”中未出现的标记序列覆盖定义:

\documentclass{article}

\makeatletter
\newcommand\savedqend{}
\newcommand\changeqend[1]{\let\savedqend=\@qend \long\def\@qend{#1}}%
\newcommand\restoreqend{\let\@qend=\savedqend}%
\makeatother

\changeqend{ThisStuffIsNotOfCatcodeTwelveButOfCatCodeEleven}
\newcommand{\endomorphism}{Endomorphism}
\restoreqend

\begin{document}
\endomorphism
\end{document}

\renewcommand但如果您坚持使用 LaTeX 语法,您也可以使用:

\renewcommand不使用\@ifdefinable,因此不检查相关命令名称的前三个字母。只需通过 分配一个虚拟定义\def,然后执行\renewcommand

以下代码提供了宏\mynicenewcommand和,\myniceprovidecommand它们为您执行这些操作。\renewcommand并且\DeclareRobustCommand不需要mynice‑变体,因为它们不使用\@ifdefinable

\documentclass{article}

\makeatletter
\newcommand\myniceprovidecommand[1]{%
  \edef\reserved@a{\expandafter\@gobble\string#1}%
  \@ifundefined\reserved@a{\def#1{Dummy}\renewcommand#1}%
                          {\renewcommand\reserved@a}%
}%
\newcommand\mynicenewcommand[1]{%
  \edef\reserved@a{\expandafter\@gobble\string#1}%
  \@ifundefined\reserved@a{\def#1{Dummy}\renewcommand}%
                          {\newcommand}%
  #1%
}%
\makeatother

\mynicenewcommand{\endomorphism}{Endomorphism}

\myniceprovidecommand{\endomorphism}{EndomorphismB}

\begin{document}
\endomorphism
\end{document}

相关内容