11

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.

15

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!

  • The original macro name was endomorphisms so I think I'm safe :) – user167417 Jul 27 '18 at 15:47
  • @TTFarreo Sure: I have \endo for work reasons ... – Joseph Wright Jul 27 '18 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 '18 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