# shellescape macro nested in another macro

How do I use a shellescape (| echo "stuff") macro as another macros input if there are "bad" characters like _ contained.

I will use my full example as reference.

The idea is to replace \lstinputlisting{|\string"git archive --remote=ssh://git@server/repo.git VERSION path/to/file 2>/dev/null | tar --extract --file - --to-stdout\string"}

with a macro like this

% set these so they can later be redefined
\providecommand{\GitRemote}{}
\providecommand{\GitIdentifier}{master}

\providecommand{\GitCheckout}[2][\GitIdentifier]{%
% #1 being the version/branch
% #2 being the file
| \string"git archive --remote=\GitRemote #1 \detokenize{#2} 2>/dev/null | tar --extract --file - --to-stdout \string"%
}


with usage \lstinputlisting{\GitCheckout{path_to_file.py}}

MWE:

\documentclass{article}
\usepackage{listings}
\providecommand{\GitRemote}{}
\providecommand{\GitIdentifier}{master}
\providecommand{\GitCheckout}[2][\GitIdentifier]{%
% #1 being the version/branch
% #2 being the file
| \string"git archive --remote=\GitRemote #1 \detokenize{#2} 2>/dev/null | tar --extract --file - --to-stdout \string"%
}
\begin{document}
renewcommand{\GitRemote}{ssh://git@trac.sagemath.org/sage.git}
\lstinputlisting{\GitCheckout{src/sage/coding/goppa.py}}
\end{document}


but i keep getting errors like this

mwe.tex|10 error| Use of \\GitCheckout doesn't match its definition.

so it seems there is some escaping going on (\ to \\)

• you have defined \GitCheckout to take an optional argument which means that it does not work by expansion, and the argument to lstinputlisting must expand to a filename. – David Carlisle Jul 26 at 23:01
• It's not clear why using \providecommand. Anyway, if you use xparse, then you can try \NewDocumentCommand{\GitCheckout}{O{\GitIdentifier}m}{...} – egreg Jul 26 at 23:21

There were multiple problems in this code:

We do not want to escape any character, if used as an input and, as @David Carlisle mentioned, the input for lsinputlistings needs to be expanded. The optional structure is, as @egreg mentioned, better delegated to xparse. For getting an optional command I used the DeclareExpandableDocumentCommand from (i think) here.

Combining these facts we get a function definition of the macro and prequisites as follows:

% https://tex.stackexchange.com/questions/501640/shellescape-macro-nested-in-another-macro?noredirect=1#comment1266953_501640
\usepackage{xparse}

% this is set as fallback
\NewDocumentCommand{\GitRemote}{}{}
\NewDocumentCommand{\GitIdentifier}{}{master}

\NewExpandableDocumentCommand{\GitCheckout} {O{\GitIdentifier} O{\GitRemote} m} {%
|"git archive --remote=#2 #1 #3 2>/dev/null | tar --extract --file - --to-stdout"
}

• Still \ProvideDocumentCommand is very strange. You don't want that \GitIdentifier does something completely unexpected, do you? So you want to be informed that \NewDocumentCommand fails and change the name, rather than having mysterious troubles along the way. – egreg Jul 28 at 19:49
• I remember now, why I have this: I had a weird bug with this always complaining na dfixed it by using provide, but i just sourced the file multiple times; will adopt your change – 927589452 Jul 29 at 7:06