3

I use the following line to write into the PDF the name of the git repository with source code of the document:

\input|"git config --get remote.origin.url | xargs basename"

I am facing a problem with one repository with underscore in the name, e.g. repo_name, as the special character makes my compiler switch to math mode.

I could probably use the \catcode as shown in the other answer, but it's not only the underscore that may cause problems, and I would prefer to make it robust against all special characters that may occur in directory names.

MaciekS
  • 277
  • 1
    you could use \detokenize but that would make all characters inactive but if you have any non-ascii utf8 filenames they then will show as the individual bytes, so it is probably better just to make the ascii characters safe by setting their catcodes, you could use (or copy bits of) \verb – David Carlisle Jul 11 '17 at 10:09

1 Answers1

3

You can use catchfile:

\documentclass{article}
\usepackage{catchfile}

\begin{document}

\CatchFileDef\repository{|"kpsewhich eng_rs.sty | xargs basename"}{\catcode`_=12 }

\texttt{\repository}

\texttt{\meaning\repository}

\end{document}

I used a file name having an underscore, just by way of example.

enter image description here

A possibly better version, with xparse:

\documentclass{article}
\usepackage[T1]{fontenc}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\getfilename}{O{}mo}
 {
  % #1 = optional list of characters to be made printable
  % #2 = variable part
  % #3 = optional command to save the returned token list in
  \tl_set_from_file:Nnn \l_maciek_filename_tl
   {
    \maciek_filename_setother:n { #1 }
   }
   {
    |"#2"
   }
  \IfValueTF{#3}
   {
    \tl_clear_new:N #3
    \tl_set_eq:NN #3 \l_maciek_filename_tl
   }
   {
    \tl_use:N \l_maciek_filename_tl
   }
 }

\cs_new_protected:Nn \maciek_filename_setother:n
 {
  \tl_map_function:nN { #1 } \char_set_catcode_other:N
 }

\ExplSyntaxOff

\begin{document}

\getfilename[_]{kpsewhich eng_rs.sty | xargs basename}

\getfilename[_]{kpsewhich eng_rs.sty | xargs dirname}[\foo]

\meaning\foo

\getfilename[\%]{ls | grep b}

\getfilename[\%_]{ls | grep y}

\end{document}

I have created two files a%b.tex and a_x%y.tex just to show the usage of the first optional argument. A backslash is needed for characters such as backslash, percent and hash mark (#).

enter image description here

egreg
  • 1,121,712
  • That's fantastic, @egreg! Cheers! Just for reference the link to the package documentation: http://anorien.csc.warwick.ac.uk/mirrors/CTAN/macros/latex/contrib/oberdiek/catchfile.pdf – MaciekS Jul 11 '17 at 10:58
  • @MaciekS Other characters can be managed in a similar way, just add to the trailing argument. – egreg Jul 11 '17 at 10:59