# How can I pass underscore to \newcommand properly?

I'd like to simplify my code appendix with this command definition:

\usepackage{listings}
% ...
\newcommand{\CodeListing}[1]{%
\lstinputlisting[caption=#1]{#1}%
}


That is, the caption should be the file name. However, the caption argument and the file name argument seem to handle underscores differently. For the former, I need to escape them (\_), but for the latter, non-escaped underscores work fine. How can I solve this problem, if I only want to pass the file name once?

! Package Listings Error: File spt2/my\T1\textunderscorefile(.m)' not found.


Here is a minimal example:

\documentclass[a4paper]{scrreprt}
\usepackage{listings}
\begin{document}
\newcommand{\codelst}[1]{
\lstinputlisting[caption=#1]{#1}
}
\codelst{/home/tim/projekt/matlab/path/save\_plot\_as.m}
\end{document}


which works fine for underscore-less paths.

-
Maybe: How can I work with an underscore without escaping? – Marco Daniel Dec 16 '11 at 21:05

It's a very common problem: if you want to typeset an underscore, you need to pass \_, which is not good for a file name. Solution:

\documentclass[a4paper]{scrreprt}
\usepackage{listings}
\newcommand{\codelst}{\begingroup
\catcode_=12 \docodelst}
\newcommand{\docodelst}[1]{%
\lstinputlisting[caption=\texttt{#1}]{#1}%
\endgroup
}
\begin{document}
\codelst{/home/tim/projekt/matlab/path/save_plot_as.m}
\end{document}


It's better to say also \texttt{#1} so that the file name will be printed in typewriter font.

The idea is to change the _ into a printable character, making it lose its special meaning. The trick consists in changing it before the argument is grabbed.

-
Thank you egreg! \texttt makes it nicer, too. Is it possible to do this in a single command definition? (Just curious) – Tim N Dec 16 '11 at 21:10
@TimN It's possible, but the code would be quite intricate. TeX has more than enough space to contain a couple of macros. :) And actually you wouldn't save much (or even lose something) by doing the work with only one command. – egreg Dec 16 '11 at 21:23
Nice! Sadly, this does not seem to work inside environments defined with NewEnviron from environ; cf mwe. – Raphael Apr 24 '15 at 15:55
@Raphael No, it can't work, because the category code is fixed as soon as the code for the \NewEnviron environment has absorbed its contents as an argument. There are workarounds, so maybe you can ask a new question. – egreg Apr 24 '15 at 16:11
Done, thanks! – Raphael Apr 24 '15 at 16:26