4

On this code:

\documentclass{article}
\usepackage{catchfilebetweentags,regexpatch,verbatim}
\tracingpatches
\tracingxpatches
\newcommand{\test}{testone (testtwo)}
\begin{document}
\xpatchcmd*{\test}{(}{(\verb|}{}{}
\xpatchcmd*{\test}{)}{|)}{}{}
\test
\show\test
\end{document}

produces the error:

! LaTeX Error: \verb ended by end of line.

and \show\test outputs the following:

> \test=\long macro:
->testone (\verb |testtwo|).
l.11 \show\test

It is apparent that \xpatchcmd introduces an extra space after \verb, which is taken as the start/end character to \verb instead of |.

First question: is there a way to change that on \xpatchcmd*?

As a workaround I switched to shortvrb and it works, but another problem arises when I am closer to the "real" situation. MWE:

\documentclass{article}
\usepackage{catchfilebetweentags,regexpatch,verbatim,shortvrb}
\MakeShortVerb{\|}
\tracingpatches
\tracingxpatches
\def\test{testone (\testtwo)}
\begin{document}
\xpatchcmd*{\test}{(}{(|}{}{}
\xpatchcmd*{\test}{)}{|)}{}{}
\test
\show\test
\end{document}

As we see, these codes differs on the use of shortvrb and on the definition of the \test macro. I would expect that this string (\testtwo) will be taken with the verbose operator | but it won't.

Second question: why this behavior and how to make it work?

  • Do you really need \verb? Your one example uses \testtwo, the other testtwo. – Werner Dec 5 '16 at 22:36
  • \verb can not work in the argument of another command so it can't do anything useful even if you did manage to patch it in. You do not say what is the intended outcome of the change. It must be possible without using \verb – David Carlisle Dec 5 '16 at 22:47
  • the space after \verb is not a space token in the definition it is simply an artefact of the way \show shows commands. the issue is that the end delimiter is patched in with incorrect catcode, but you do not need verb here. – David Carlisle Dec 5 '16 at 22:49
  • @Werner What I call the "real" situation is when the \test macro includes a macro, that's why \testtwo and not testtwo. The latter was used in my first example in which using \verb works and it can be changed with for example \ttfamily, so no need to use verbatim output. The real case includes a backslash. I need that the \test command outputs literally the string \testtwo after some patches, like the first example but including the backslash. – Emilio Lazo Dec 6 '16 at 5:01
  • @DavidCarlisle Thanks, I forgot that \verb can't be used as the argument of another command. Also you are right on that the space on \show is a visual artifact! I'm sorry. – Emilio Lazo Dec 6 '16 at 5:07
3

If your real example is actually real, then I would take from it that you want the argument between the parentheses (...) to be set in \ttfamily, but it contains a single control sequence starting with \. For that, the following patch provides a work-around:

enter image description here

\documentclass{article}

\usepackage{etoolbox}

\def\test{testone (\testtwo)}

\begin{document}

\patchcmd{\test}{(}{(\begingroup\ttfamily\string}{}{}
\patchcmd{\test}{)}{\endgroup)}{}{}
\test
\show\test

\end{document}

\string followed by a control sequence turns the escape \ into a printable backslash. The .log file shows

> \test=macro:
->testone (\begingroup \ttfamily \string \testtwo \endgroup ).
l.12 \show\test
  • It works. \string does the job with \ttfamily enclosed inside a group. I'll adapt it to a more real situation. As you may guess, the purpose is not patching a command on the way shown in the MWE. It should work inside the documentation part of a .dtx to read the generated .tex files and parses some comments from them to take all relevant parts. I'll comment later. Thanks @Werner! – Emilio Lazo Dec 6 '16 at 5:25
3

Let's do an experiment:

\documentclass{article}

\newcommand{\test}{testone \verb|testtwo|}

\begin{document}

\show\test

\test

\end{document}

On the terminal you get

> \test=\long macro:
->testone \verb |testtwo|.
l.7 \show\test

? 

! LaTeX Error: \verb ended by end of line.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.9 \test

so you see that it's not a problem with regexpatch and, in particular, with \xpatchcmd.

The fact is that \verb cannot be used in the argument to another command, including the replacement text of a macro.

Using \shortvrb doesn't help.

  • Ok, you are right. It is not \xpatchcmd problem. I forgot that \verb can't be used inside another command. So how can I deal with the backshash which is part of the \test command if I can't do \verb inside a command? – Emilio Lazo Dec 6 '16 at 5:00
  • @EmilioLazo How to solve the problem depends on the real situation. A single control sequence can be accommodated with Werner's workaround, but more general text can't be managed that way. – egreg Dec 6 '16 at 8:55
  • Everything as expected. Now it is possible to have these macro names (like \testtwo) not only enclosed on parenthesis as I though, but in any place on the \test macro and more than one occurrence. Now should be good if \xpatchcmd* may catch all backslashes to substitute them with the \begingroup\ttfamily\string solution, given by @Werner, but in that case, the \endgroup primitive should be placed just after the end of that macro, i.e. when the category code of the next character is different than 11. Thanks again! – Emilio Lazo Dec 7 '16 at 22:59
  • I'm using \regexpatchcmd*{\test}{\c{[A-Za-z]*}}{\c{begingroup}\c{ttfamily}\c{string}\0\c{endgroup}}{}{}. It works good but the search pattern matchs the macros with A-Za-z but if another character has the letter catcode it won't match. How can be generalized to all letter catcodes? I have no success with \cC and \cL. Also would be good adding {} after \c{endgroup} to add a blank space when needed. For example when typing \LaTeX{} in a document. How to do that? – Emilio Lazo Dec 8 '16 at 7:16
  • Anybody can help me adding {} with their correct catcodes (1 and 2) at the end of the replace group on \regexpatchcmd*? I mean, after \c{endgroup} in my last comment... Please! – Emilio Lazo Dec 13 '16 at 18:10

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.