Skip to content

\patchcmd doesn't allow replacing ## and gives misleading instructions #31

@zauguin

Description

@zauguin

Take the document

\RequirePackage{etoolbox}
\tracingpatches
\newcommand\victim{##}
\patchcmd\victim{##}{}{}{\ERROR}
\stop

This fails with

[debug] tracing \patchcmd on input line 4
[debug] analyzing '\victim'
[debug] ++ control sequence is defined
[debug] ++ control sequence is a macro
[debug] -- nested patching command and parameters in patch
[debug] -> the patching command seems to be nested in the
[debug]    argument to some other command
[debug] -> the patch text seems to contain # characters
[debug] -> either avoid nesting or use # characters with
[debug]    category code 12 in the patch text
[debug] -> simply doubling the # characters will not work
! Undefined control sequence.
<argument> \ERROR 

Here etoolbox seems to mis-analyze the situation:
While the patch text contains a #, it is not nested in any command argument. Also following the advice to give # catcode 12 doesn't work:

\RequirePackage{etoolbox}
\tracingpatches
\newcommand\victim{##}
\begingroup
  \catcode`#=12
  \csname @firstofone\endcsname {%
  \endgroup
  \patchcmd\victim{##}{}{}{\ERROR}
}
\stop

gives the same output.

After weakening the relevant test using

\makeatletter
\protected\long\def\etb@ifhashcheck#1#2#3{#2}
\makeatother

the actual patching seems to work fine though, suggesting that the only issue is the falsely triggered check.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions