# Escaping from the escaping hell

Given the following MWE, where the argument for the code function contains an underscore:

\documentclass [11pt,oneside,onecolumn]{article}
\usepackage{listings}
\usepackage{filecontents}

\begin{filecontents*}{hello_world.c}
#include <stdio.h>

int main(void) {
printf("Hello World!\n");
// return 0;
}
\end{filecontents*}

\makeatletter
\def\code{\@ifnextchar[{\@with}{\@without}}
\def\@with[#1]#2{
}
\def\@without#1{
\section{#1}
\lstinputlisting[]{#1}
}
\makeatother

\begin{document}
\code{hello_world.c}
\end{document}


The same argument #1 is used in two different functions: section, which requires the underscore to be escaped, and lstinputlisting, which requires the underscore not to be escaped.

If the user escapes the filename, compilation fails because of section. If the user doesn't escape the filename, listings cannot find the filename.

How to solve the issue?

-
Please add a minimal working example (MWE) that illustrates your problem. You might think that this is better but we cannot reproduce what you mean by just copy/pasting your code and compiling. Instead we have to make our own each time which is tedious. Why don't you give a full one as I did in your previous question? – percusse Jul 27 '12 at 15:36
Because I didn't know about makeatletter and makeatother, which I just saw in your answer. Putting everything in a single file without those commands was causing a Use of \@ doesn't match its definition. error, which is why I didn't use a single file. I was doing my best to ease your job. Sorry about that. – Roberto Aloi Jul 27 '12 at 16:14
Note that there are many ways to define commands with optional arguments that are much more robust than using \@ifnextchar. – egreg Jul 27 '12 at 20:37

You can use the eTeX primitive \detokenize to make _ safe and then T1 font encoding so a _ character gets printed as an underscore:

\documentclass [11pt,oneside,onecolumn]{article}
\usepackage[T1]{fontenc}
\makeatletter
\usepackage{listings}

\def\code{\@ifnextchar[{\@with}{\@without}}%
\def\@with[#1]#2{%
}
\def\@without#1{%
\section{\protect\detokenize{#1}}%
\lstinputlisting[]{#1}%
}

\makeatother

\begin{document}

\tableofcontents

\code{hello_world.c}
\end{document}

-
Works beautifully. Thanks. – Roberto Aloi Jul 27 '12 at 16:18
Well, only drawback is that the underscore is not rendered correctly in the TOC (it minimizes the "w"). – Roberto Aloi Jul 27 '12 at 16:20
Sorry a \protect was missing. Also I added some % at the ends of lines (unrelated to your problem but uncommented line ends could produce unwanted white space in the output) – David Carlisle Jul 27 '12 at 16:27

There are several packages that takes care of typesetting file names, e.g. url, path. The following example uses package url. I have assumed that the optional argument of \code has the purpose to pass options to the lstinputlisting command. In this case the hacking with \@ifnextchar is not necessary.

\documentclass [11pt,oneside,onecolumn]{article}
\usepackage[T1]{fontenc}
\usepackage{listings}
\usepackage{url}
\usepackage{makerobust}

% Define \file that typeset a file name using the url package
% that also takes care of hyphenation issues, ...
\newcommand*{\file}{}% to get an error if \file is already defined
\DeclareUrlCommand{\file}{\urlstyle{sf}}
% Different styles are available, e.g.:
% sf: sans serif font (\sffamily)
% rm: roman font (\rmfamily)
% tt: typewriter font (\ttfamily)
\MakeRobustCommand{\file}
% as robust command \file do not need \protect

\newcommand*{\code}[2][]{%
\section{\file{#2}}%
\lstinputlisting[{#1}]{#2}%
}

\begin{document}

\tableofcontents

\code{hello_world.c}

\end{document}

-
you have \makeatother but I don't see a \makeatletter, is that right? – PatrickT Feb 21 '14 at 21:18
@PatrickT: Thanks for noticing. It's probably a left-over from a previous version and I have removed it now. – Heiko Oberdiek Feb 21 '14 at 21:20