2

I'm trying to patch an AMC's macro, named \AMCopenShow using etoolbox.

However, I got an error that gives many options but that I don't know how to solve, or even if it is possible to do it.

[debug] tracing \patchcmd on input line 64
[debug] analyzing '\AMCopenShow'
[debug] ++ control sequence is defined
[debug] ++ control sequence is a macro
[debug] -- macro cannot be retokenized cleanly
[debug] -> the macro may have been defined under a category
[debug]    code regime different from the current one
[debug] -> the replacement text may contain special control
[debug]    sequence tokens formed with \csname...\endcsname;
[debug] -> the replacement text may contain carriage return,
[debug]    newline, or similar characters

How can I successfully patch the command? And the code for the ones that doesn't have the software can be reproduced with this example:

\documentclass{article}

\usepackage{etoolbox}
% from automultiplechoice.sty
\makeatletter
\newcommand\AMCopenShow[4]{
  \ifAMC@ensemble\def\AMCid@name{#3}\AMCid@quest=#4\fi%
  \ifAMC@ensemble\ifAMCformulaire@dedans%
    \AMC@amclog{AUTOQCM[Q=\the\AMCid@quest]^^J}%
  \fi\fi%
  {\setkeys{AMCOpen}{#1}%
    \ifKV@AMCOpen@lineup%
      \ifAMC@ensemble\else\par\fi%
      \ifAMC@correc\smash{\AMCopen@answer}\fi\dotfill%
    \else%
      \hspace*{.5em}\linebreak[1]\hspace*{\fill}%
    \fi%
    {\AMCnoCompleteMulti%
      \def\AMCbeginAnswer{}\def\AMCendAnswer{}%
      \def\AMCanswer##1##2{\ifAMC@ensemble ##1\else%
          \ifAMC@inside@box ##1\else{\AMCboxOutsideLetter{##1}{##2}}\fi\fi%
        \hspace{\AMCopen@Hspace}}%
      \fboxsep=\AMCopen@boxmargin%
      \fboxrule=\AMCopen@boxframerule%
      \fcolorbox{\AMCocol@BoxFrameRule}{\AMCocol@Background}{%
        \ifAMC@ensemble\AMCopen@question%
          \ifx\@empty\AMCopen@question\@empty\else\hspace{\AMCopen@Hspace}\fi%
        \fi%
        \begin{choicescustom}[o]%
          \ifx\AMCocol@Foreground\@empty\@empty\else%
            \def\AMC@boxcolor{\AMCocol@Foreground}%
          \fi%
          #2%
          \ifKV@AMCOpen@scan\else\AMCdontScan\fi%
          \ifKV@AMCOpen@annotate\else\AMCdontAnnotate\fi%
        \end{choicescustom}%
        \ifx\@empty\AMCotextReserved\@empty%
          \hspace{-\AMCopen@Hspace}%
        \else%
          \ifx\AMCocol@Foreground\@empty\@empty%
            \AMCotextReserved%
          \else%
            \textcolor{\AMCocol@Foreground}{\AMCotextReserved}%
          \fi%
        \fi%
      }}%
    \ifKV@AMCOpen@lineup\else%
      \par\nobreak\noindent%
      \hspace*{\fill}{%
        \fboxrule=\AMCopen@framerule%
        \fcolorbox{\AMCocol@FrameRule}{white}{%
          \csname\AMCopen@contentcommand\endcsname
        }}%
      \vspace{7mm}\par%
    \fi%
  }%
  \ifAMC@ensemble\ifAMCformulaire@dedans%
  \AMC@amclog{AUTOQCM[FQ]^^J}%
  \fi\fi%
}
\makeatother

\tracingpatches
\patchcmd{\AMCopenShow}{\vspace{-7mm}\par}{\vspace{0mm}\par}{}{\PackageWarning{this}{No patch}}

\begin{document}
\end{document}

Update

The hack from egreg helps patching the macro. But sadly it doesn't work. Probably fixing the macro broke something that is defined inside the package.

Example with questions that breaks the patch:

\documentclass{article}

\usepackage[box,lang=ES]{automultiplechoice}
\usepackage{regexpatch}


\makeatletter

% get rid of the initial space
\begingroup
\toks0=\expandafter{\AMCopenShow{#1}{#2}{#3}{#4}}
\toks0=\expandafter\expandafter\expandafter{\expandafter\@gobble\the\toks0}
\edef\x{\endgroup
  \noexpand\renewcommand\noexpand\AMCopenShow[4]{\the\toks0}
}\x

% do the real patch; \ddt is just a signal for raising an error if
% the patch doesn't succeed
\xpatchcmd{\AMCopenShow}{\vspace{7mm}\par}{\vspace{0mm}\par}{}{\ddt}
\makeatother

\begin{document}
\element{general}{
  \begin{question}{Yaounde} 
  What is the capital city of Cameroon?
  \AMCOpen{lineup=true,hspace=0.1mm,boxmargin=0.1ex}{\wrongchoice{$>$}\scoring{1}\correctchoice{$<$}\scoring{2}} 
\end{question}
}

\element{general}{
\begin{question}{id2}
\begin{choicescustom}[o]
        \wrongchoice[T]{}
        \correctchoice[F]{}
\end{choicescustom}
This is a True or False question.
\end{question}
}
\onecopy{1}{
\insertgroup{general}
}
\end{document}
  • You can't use \patchcmd for patching macros containing ^^J. – egreg Nov 18 '15 at 23:48
  • 1
    It's also not patchable with regexpatch because of the silly space that starts off the replacement text (added to the list of fixes to regexpatch). Copy the macro and do the change manually. – egreg Nov 19 '15 at 0:00
  • I have that fix, but was hoping that there was another solution. More flexible one. Well, thanks. – adn Nov 19 '15 at 2:11
1

The problem is that the replacement text you want to patch contains ^^J and etoolbox doesn't like such macros.

The regexpatch package is able to do it, but it seems to refuse patching badly written macros such as \AMCopenShow, which has an unprotected end-of-line at the beginning.*

Thus we need first to get rid of that space and this is possible with standard methods:

\begingroup
\toks0=\expandafter{\AMCopenShow{#1}{#2}{#3}{#4}}
\toks0=\expandafter\expandafter\expandafter{\expandafter\@gobble\the\toks0}
\edef\x{\endgroup
  \noexpand\renewcommand\noexpand\AMCopenShow[4]{\the\toks0}
}\x

If \vspace{7mm} appeared at the outer brace level in the replacement text, it would be possible to do the patch in a similar way. However, regexpatch is now able to patch the macro. Full code:

\documentclass{article}

\usepackage{automultiplechoice}
\usepackage{regexpatch}

\makeatletter
% get rid of the initial space
\begingroup
\toks0=\expandafter{\AMCopenShow{#1}{#2}{#3}{#4}}
\toks0=\expandafter\expandafter\expandafter{\expandafter\@gobble\the\toks0}
\edef\x{\endgroup
  \noexpand\renewcommand\noexpand\AMCopenShow[4]{\the\toks0}
}\x

% do the real patch; \ddt is just a signal for raising an error if
% the patch doesn't succeed
\xpatchcmd{\AMCopenShow}{\vspace{7mm}\par}{\vspace{0mm}\par}{}{\ddt}
\makeatother

\begin{document}
\footnotesize\texttt{\meaning\AMCopenShow}
\end{document}

enter image description here

* Seriously, it's an issue that will be fixed

  • Thanks for helping with the patch. However, the expansion and fixing the macro seems to break the functionality of AMC. Do you think is worth it to fix it or just ride with a redefinition of the main macro? – adn Nov 19 '15 at 15:14
  • 1
    @adn When simple patching doesn't work, the best is to modify the original manually. – egreg Nov 19 '15 at 16:53

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.