12

The following simple file gets an error during compilation:

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

The error message is:

! 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.

It seems that what ever I put after \end (say \endb, \endklghfsgfljs or whatever valid command name) Latex will produce the same error. When the d of end is changed into another letter (say, s) this seems to go fine.

How do I define a command with the name I want?

Note: my question is not whether this is a reserved word but how to bypass the obstruction. A slightly different question is are-end-macro-names-reserved-in-latex2e. I couldn't find this question with my intentions in mind. I expect that somebody stumbling upon the same problem as me would find this question more easily than the one in the link.

0

3 Answers 3

16

This is 'by design' due to the way environments work. You can though use the TeX \def primitive

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

with the proviso that an environment called a would be an issue!

3
  • The original macro name was endomorphisms so I think I'm safe :)
    – user167417
    Jul 27, 2018 at 15:47
  • @TTFarreo Sure: I have \endo for work reasons ...
    – Joseph Wright
    Jul 27, 2018 at 15:51
  • 5
    @TTFarreo endomorphisms are safe enough if you keep them refrigerated, but make sure you use them within 24 hours of opening the packaging ;)
    – alephzero
    Jul 27, 2018 at 16:30
3

You can exploit the fact that \NewDocumentCommand doesn't check for initial \end, but only disallows defining existing (that is, already explicitly defined) commands.

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

Of course you could directly use \NewDocumentCommand; it requires a different syntax than \newcommand, but it's much more powerful.

The instruction \newendcommand{\endenumerate}{} raises the error

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

The last call \endstar{x\par} instead raises the error

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

because \endstar has been called with \newendcommand*. To the contrary, \endopt accepts \par in its arguments.

enter image description here

1

\newcommand internally uses \@ifdefinable for checking whether a command is definable.

Beneath other things \@ifdefinable checks whether the first three letters of the command-name in question are e, n, d. For doing this, \ifx-comparison is done to a macro \@qend whose expansion yields these letters as explicit character tokens of category code 12 (other).

If you wish, you can temporarily override the definition of \@qend with a token sequence which does not occur in the "stringification" of the command-name desired by you:

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

But you can also use \renewcommand if you insist in having something with LaTeX syntax:

\renewcommand doesn't use \@ifdefinable, thus doesn't check the first three letters of the command-name in question. Just assign a dummy-definition via \def, then perform \renewcommand.

The following code provides macros \mynicenewcommand and \myniceprovidecommand which do these things for you. \renewcommand and \DeclareRobustCommand don't require mynice‑variants as they don't use \@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}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy