# Macro to capitalize all letters and change breaks to underlines

I'm trying to make a macro that will take an input phrase, capitalize all letters, and replace all breaks with underlines:

\ctest{one word} => ONE_WORD


I've been trying to use the stringstrings package for this:

\newcommand{\ctest}[1]{%
\solelyuppercase[e]{#1}%
\getargs{\thestring}%
{\fontfamily{pcr}\selectfont \argi\underline{{ }}\argii}}


I'm happy with the result, but I need the macro to be flexible in accepting phrases with one, two, three, or four words. I can use \narg to get the word count, but I have no idea how to call \argi, \argii, ... flexibly.

Any help would be greatly appreciated!

• Do you need to save the result, or merely output it? – Steven B. Segletes Feb 8 '18 at 21:19
• You should just use VIM. ;) – AmagicalFishy Feb 9 '18 at 1:21

With expl3, with support for accented characters:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc} % just for testing strange chars

\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\ctest}{m}
{
% set the token list to the upper case version of the inptu
\tl_set:Nx \l_tmpa_tl { \tl_upper_case:n { #1 } }
% replace spaces with underscores
\tl_replace_all:Nnn \l_tmpa_tl { ~ } { \c_underscore_str }
% produce the text
\texttt{\tl_use:N \l_tmpa_tl}
}

\ExplSyntaxOff

\begin{document}

\ctest{one word}

\ctest{élite über Straße l'Hôpital}

\end{document}


• Could someone use \char_set_uccode:nn to have the white spaces replaced by \c_underscore_str? – Skillmon Feb 8 '18 at 21:49
• @Skillmon Not really: TeX normalizes tokens with category code 10 to spaces. You can only set the \uccode to another character, not to a macro. – egreg Feb 8 '18 at 21:54

Here's a LuaLaTeX-based solution.

\documentclass{article}
\usepackage{luacode} % for 'luacode' env. and '\luastring' macro
%% Lua-side code
\begin{luacode}

function ctest ( s )
tex.sprint (string.upper ( string.gsub ( s , "%s" , "\\_" ) ) )
end

\end{luacode}
%% LaTeX-side code
\newcommand\ctest[1]{\directlua{ctest(\luastring{#1})}}

\begin{document}
\ctest{one word}

\ctest{several no longer separate words}
\end{document}


Addendum: If the argument of \ctest may contain unicode-encoded characters, simply switch the line

   tex.sprint ( string.upper ( string.gsub ( "%s" , "\\_" ) ) )


in the Lua function to

   tex.sprint ( unicode.utf8.upper ( unicode.utf8.gsub ( s , "%s","\\_" ) ) )


i.e., replace string.upper with unicode.utf8.upper and string.gsub with unicode.utf8.gsub.

Maybe this? T1 encoding (or rather, not OT1) is essential here.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{stringstrings}
\newcommand\ctest[1]{%
\convertchar[e]{#1}{ }{\_}%
\caseupper[v]{\thestring}
}
\begin{document}
\ctest{one word} $a_b$
\ctest{one two three words}
\end{document}


It is also available in \thestring.

This might be a better way, using the listofitems package:

\documentclass{article}
\usepackage{listofitems}
\newcommand\ctest[1]{%
\setsepchar{ }%