2

I followed this answer to define a command such that underscores in its parameter can be kept.

However, this does not work if the command is called inside an environment that has been defined with NewEnviron from environ:

\documentclass[a4paper]{scrreprt}
\newcommand{\cmd}{\begingroup
  \catcode`_=12 \cmdint}
\newcommand{\cmdint}[1]{%
  \texttt{#1}%
  \endgroup
}

\newenvironment{wrap}{}{}
\usepackage{environ}
\NewEnviron{wrap2}{\BODY}

\begin{document}
\cmd{some_test}

\begin{wrap}
  \cmd{some_test}
\end{wrap}

\begin{wrap2}
  \cmd{some_test}
\end{wrap2}
\end{document}

This compiles to

enter image description here

Say I can not do without environ (I've actually been struggling for about an hour to get rid of it in my actual document, without success), how can I fix this?

  • You want to have verbatim content then? – user31729 Apr 24 '15 at 16:44
  • @ChristianHupfer Not necessarily; I want to use it for \input but also for \texttt. – Raphael Apr 24 '15 at 16:59
3

The solution depends on the alphabet, used for the variables. If these are identifiers with upper and lower case letters, digits, underscore and some other harmless symbols (with category code 12/other, as punctuation chars) then \detokenize can be used to normalize the category codes of the identifier to token with category code 12 (same as digits):

\documentclass[a4paper]{scrreprt}

\newcommand*{\cmd}[1]{\texttt{\detokenize{#1}}}

\newenvironment{wrap}{}{}
\usepackage{environ}
\NewEnviron{wrap2}{\BODY}

\begin{document}
\cmd{some_test}

\begin{wrap}
  \cmd{some_test}
\end{wrap}

\begin{wrap2}
  \cmd{some_test}
\end{wrap2}
\end{document}

Result

  • Heh, that's actually the nicer fix for the original problem. Maybe you should post an answer to the question I got this from? – Raphael Apr 24 '15 at 17:10
  • How is this different from the approach with scantokens? Are there situations where you would prefer one over the other? – Raphael Apr 27 '15 at 11:15
  • 1
    @Raphael \detokenize is easier in usage. It converts all characters to category code 12 and the space character to category code 10. \scantokens is more complicate, it's the equivalent from writing the contents to a file and reread it. End of line characters can cause unwanted white spaces unless disabled (\errorcontextlines=-1). Also the category codes for the characters, which an appear in the result has to be set to safe values. – Heiko Oberdiek Apr 27 '15 at 12:11
  • Thanks. It seems that detokenize is indeed the better solution for my use case since the limitations don't bother me here. – Raphael Apr 27 '15 at 14:32
2

It seems like this is also a situation where \scantokens could come in nicely:

\documentclass[a4paper]{scrreprt}
\newcommand{\cmd}{\begingroup
  \catcode`_=12 \cmdint}
\newcommand{\cmdint}[1]{%
  \texttt{\scantokens{#1\noexpand}}%
  \endgroup
}

\newenvironment{wrap}{}{}
\usepackage{environ}
\NewEnviron{wrap2}{\BODY}

\begin{document}
\cmd{some_test}

\begin{wrap}
  \cmd{some_test}
\end{wrap}

\begin{wrap2}
  \cmd{some_test}
\end{wrap2}
\end{document}

The problem with your original is that within a \NewEnviron type environment, the tokens have already been read in and their catcodes are already set before they get fed to your macro. By using \scantokens, the catcodes are essentially reassigned.

For further details about using \scantokens @egreg has a nice explanation in response to my question at Could someone further elucidate expansion, catcodes, and scantokens…?

  • How is this different from the approach with detokenize? Are there situations where you would prefer one over the other? – Raphael Apr 27 '15 at 11:15
  • 1
    @Raphael Since I'll skip @HeikoOberdiek 's details. With \scantokens, you can employ macros which will expand in the usual way: so you could write somthing like \scantokens{Hello \textbf{world}\empty} and the \textbf will take effect: this would be difficult to achieve with \detokenize. Of course, you shouldn't be using \scantokens alone like this. I chose to use it because that would preserve the other structures you were already using and in the manner that you defined them. \detokenize could potentially require you to rethink how your macros should be defined. – A.Ellett Apr 27 '15 at 13:29
  • Thanks; it seems that detokenize is indeed the better solution for my use case (I only need a workaround for filenames with underscores), but yours is probably the one with general merit for egreg's pattern. – Raphael Apr 27 '15 at 14:31

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.