2

My question is closely related to this one. The solution there works fine for text, but here is my scenario.

I want to typeset the names of all packages specially, so it is clear what I refer to. For this, I defined the command:

\newcommand*{\pkg}[1]{\textsf{\detokenize{#1}}}

I use \detokenize because I have to use _ often in the name of a package, so it I don't want the extra \. Also, sometimes I copy-paste the name from somewhere, so it already has the form package_name.


I am using lmodern fonts, mostly out of inertia. Surely, if you can suggest a better font which has a decent underscore and looks nice, that's great. I tried palatino and times, as suggested in the related question. I don't like palatino. times could work, but the \textsf seems too big in relation to normal text.


\documentclass[12pt]{report}
\usepackage{lmodern}        % use modern latin fonts
\usepackage[T1]{fontenc}    % use 8 bit output font encoding with more glyphs
\usepackage[utf8]{inputenc} % so you can type ă

\usepackage{relsize}        % allows you to resize individual characters e.g. underscore
\renewcommand{\_}{\textscale{.5}{\textunderscore}}

\newcommand*{\pkg}[1]{\textsf{\detokenize{#1}}} % typeset the name of a package: \pkg{tum_ardrone}
\newcommand*{\ds}[1]{\textsl{\textsf{\detokenize{#1}}}} % and of a dataset \ds{RIMES}
% these complicated definitions ensure that you always get correct spacing after the command
% and that you cannot forget the correct form (e.g. \FRCNN{}) because this would give you
% bad spacing; and that the name is not hyphenated
\makeatletter
    \@ifdefinable{\FRCNN}{\def\FRCNN#{\mbox{\pkg{Faster R-CNN}}}}
    \@ifdefinable{\CTPN}{\def\CTPN#{\mbox{\pkg{CTPN}}}}
    \@ifdefinable{\RESNET}{\def\RESNET#{\mbox{\pkg{ResNet-101}}}}
    \@ifdefinable{\CRNN}{\def\CRNN#{\mbox{\pkg{CRNN}}}}
\makeatother


\begin{document}

Template\_bin % works

\pkg{Template_bin} % nope

\end{document}

Edit: Forgot to say that I use things like \section{The \pkg{Template_bin}}, \caption[\pkg{Pkg_name}]{...} etc . Ideally, it would work there too, but if it's too difficult I guess I can find a workaround or not use \pkg{} there.

enter image description here

3
  • Neither palatino nor times affects the sans-serif font. Why do you have special characters in filenames? This is just asking for trouble, surely?
    – cfr
    Mar 6, 2018 at 1:07
  • Interesting about the effect of font on sans-serif. I didn't know. They are not filenames, but how I chose to name my datasets :(. This was before writing the report, so all the figures bear these names. Also, I thought _ is a way of avoid trouble with spaces in filenames ? Mar 6, 2018 at 10:16
  • 1
    Well, spaces are bad, for sure, and underscores are good in filenames. But underscores are trouble when processing because they are special characters.
    – cfr
    Mar 6, 2018 at 21:55

2 Answers 2

1

Ask TeX to do the required replacement without touching the other tokens.

I'd prefer \scalebox to \textscale; I also add some simplification for your complicated definitions.

\documentclass[12pt]{report}
\usepackage{lmodern}        % use modern latin fonts
\usepackage[T1]{fontenc}    % use 8 bit output font encoding with more glyphs
\usepackage[utf8]{inputenc} % so you can type ă
\usepackage{graphicx}
\usepackage{xparse}

\RenewDocumentCommand{\_}{}{\scalebox{0.5}[1]{\textunderscore}}

\ExplSyntaxOn
\NewDocumentCommand{\changeunderscore}{m}
 {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \regex_replace_all:nnN { _ } { \c{_} } \l_tmpa_tl
  \tl_use:N \l_tmpa_tl
 }
\ExplSyntaxOff

% typeset the name of a package: \pkg{tum_ardrone}
\newcommand*{\pkg}[1]{\textsf{\changeunderscore{#1}}}
% and of a dataset \ds{RIMES}
\newcommand*{\ds}[1]{\textsl{\textsf{\changeunderscore{#1}}}}
% syntactic sugar
\makeatletter
\newcommand{\newcommandb}[2]{\@ifdefinable{#1}{\def#1##{#2}}}
\makeatother

\newcommandb{\FRCNN}{\mbox{\pkg{Faster R-CNN}}}
\newcommandb{\CTPN}{\mbox{\pkg{CTPN}}}
\newcommandb{\RESNET}{\mbox{\pkg{ResNet-101}}}
\newcommandb{\CRNN}{\mbox{\pkg{CRNN}}}

\newcommandb{\TB}{\pkg{Template_bin}}

\begin{document}

Template\_bin

\pkg{Template_bin}

\TB{}

\end{document}

enter image description here

2
  • Wow ! Super nice ! Thank you, @egreg ! I need to learn LaTeX3 syntax to understand how all this works, but it works ! Thank you for the nice syntactic sugar, too ! p.s. Should I downvote because it doesn't answer the question, haha ? I can't figure out a better title, without \detokenize :( Mar 6, 2018 at 18:20
  • 1
    @CiprianTomoiagă It doesn't use \detokenize, yes; what if your package has an accent in the name? ;-)
    – egreg
    Mar 6, 2018 at 18:26
3

Here I use listofitems to read the \detokenized output of \pkg and replace the instances of catcode12 _ with \_.

\documentclass[12pt]{report}
\usepackage{lmodern}        % use modern latin fonts
\usepackage[T1]{fontenc}    % use 8 bit output font encoding with more glyphs
\usepackage[utf8]{inputenc} % so you can type ă

\usepackage{relsize}        % allows you to resize individual characters e.g. underscore
\usepackage{listofitems}
\renewcommand{\_}{\textscale{.5}{\textunderscore}}
% THIS IS WHAT I AM SEARCHING THE DETOKENIZED STRING FOR
\expandafter\setsepchar\expandafter{\detokenize{_}}%
%
\newcommand*{\pkg}[1]{%
  \edef\tmp{\detokenize{#1}}%
  \readlist\xyz{\tmp}% FIND ALL INSTANCES OF _
  {\sffamily%
  \foreachitem\x\in\xyz{\ifnum\xcnt=1\else\_\fi\x}}% REPLACE _ WITH \_
} % typeset the name of a package: \pkg{tum_ardrone}
\newcommand*{\ds}[1]{\textsl{\textsf{\detokenize{#1}}}} % and of a dataset \ds{RIMES}
% these complicated definitions ensure that you always get correct spacing after the command
% and that you cannot forget the correct form (e.g. \FRCNN{}) because this would give you
% bad spacing; and that the name is not hyphenated
\makeatletter
    \@ifdefinable{\FRCNN}{\def\FRCNN#{\mbox{\pkg{Faster R-CNN}}}}
    \@ifdefinable{\CTPN}{\def\CTPN#{\mbox{\pkg{CTPN}}}}
    \@ifdefinable{\RESNET}{\def\RESNET#{\mbox{\pkg{ResNet-101}}}}
    \@ifdefinable{\CRNN}{\def\CRNN#{\mbox{\pkg{CRNN}}}}
\makeatother


\begin{document}

\textsf{Template\_bin} % works

\pkg{Template_bin} % nope

\pkg{Template_double_bin} % nope

\end{document}

enter image description here


As a follow up for the OP, who expanded the question to include having \pkg in section titles, the best I could do is have a quiet mode of \pkg that did not print out its result, instead saving it in \pkgname. In this way, one could define the \pkgname before the section heading with \pkg[q]{My_bad} and then use the result in the section heading: \section{The package is \pkgname}.

\documentclass[12pt]{report}
\usepackage{lmodern}        % use modern latin fonts
\usepackage[T1]{fontenc}    % use 8 bit output font encoding with more glyphs
\usepackage[utf8]{inputenc} % so you can type ă

\usepackage{relsize}        % allows you to resize individual characters e.g. underscore
\usepackage{listofitems}
\renewcommand{\_}{\textscale{.5}{\textunderscore}}
% THIS IS WHAT I AM SEARCHING THE DETOKENIZED STRING FOR
\expandafter\setsepchar\expandafter{\detokenize{_}}%
%
\makeatletter
\newcommand*{\pkg}[2][\relax]{%
  \edef\tmp{\detokenize{#2}}%
  \readlist\xyz{\tmp}% FIND ALL INSTANCES OF _
  \def\pkgname{}%
  \foreachitem\x\in\xyz{\ifnum\xcnt=1\else\g@addto@macro\pkgname{\_}\fi%
    \expandafter\g@addto@macro\expandafter\pkgname\expandafter{\x}}%
  \expandafter\def\expandafter\pkgname\expandafter{%
    \expandafter\textsf\expandafter{\pkgname}}%
  \ifx\relax#1\relax\pkgname\fi% REPLACE _ WITH \_
} % typeset the name of a package: \pkg{tum_ardrone}
\makeatother
\newcommand*{\ds}[1]{\textsl{\textsf{\detokenize{#1}}}} % and of a dataset \ds{RIMES}
% these complicated definitions ensure that you always get correct spacing after the command
% and that you cannot forget the correct form (e.g. \FRCNN{}) because this would give you
% bad spacing; and that the name is not hyphenated
\makeatletter
    \@ifdefinable{\FRCNN}{\def\FRCNN#{\mbox{\pkg{Faster R-CNN}}}}
    \@ifdefinable{\CTPN}{\def\CTPN#{\mbox{\pkg{CTPN}}}}
    \@ifdefinable{\RESNET}{\def\RESNET#{\mbox{\pkg{ResNet-101}}}}
    \@ifdefinable{\CRNN}{\def\CRNN#{\mbox{\pkg{CRNN}}}}
\makeatother


\begin{document}
\tableofcontents

\pkg[q]{My_bad}
\section{The package is \pkgname}

\textsf{Template\_bin} % works

\pkg{Template_bin} % nope

\pkg{Template_double_bin} % nope

\pkg[q]{My_other_bad}
\let\nextbad\pkgname
\pkg[q]{My_third_bad}
\section{The package names are \nextbad{} and \pkgname}
\end{document}

enter image description here

6
  • Beautiful ! I was thinking it must be something along the lines foreach token in \detokenize; if ..., but I need to learn latex programming. Small question: does the \setsepchar mean that the items in \xyz will be {Template, _, bin}, as opposed to {T, e, m, ..., _, b, i, n} ? Mar 6, 2018 at 10:30
  • Hmm, I now realise that it works on the MWE, but I failed to say that I use \pkg inside section titles and other places like that (captions, etc). And it fails there with ! Incomplete \iffalse; all text was ignored after line 44 , where line 44 is \section{\pkg{Template_bin}} Mar 6, 2018 at 10:53
  • @CiprianTomoiagă The listofitems package (ctan.org/pkg/listofitems) can do multi-level parsing of an input, based on parsing separators you provide. Here is an answer that shows some of its capability, tex.stackexchange.com/questions/338634/…, though you should look at the documentation. Mar 6, 2018 at 10:53
  • @CiprianTomoiagă I cannot make it seamless, but instead provide a quiet mode of \pkg that doesn't output the result immediately, but saves it in \pkgname, to be used later (like in a section heading). Mar 6, 2018 at 11:20
  • 1
    @CiprianTomoiagă The \readlist is not expandable; however the result of the \readlist if fully expandable. This is, again, part of the listofitems package. Mar 6, 2018 at 11:46

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.