4

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
6

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}

enter image description here

  • Could someone use \char_set_uccode:nn to have the white spaces replaced by \c_underscore_str? – Skillmon Feb 8 '18 at 21:49
  • 1
    @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
4

Here's a LuaLaTeX-based solution.

enter image description here

\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.

3

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}

enter image description here

It is also available in \thestring.


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

\documentclass{article}
\usepackage{listofitems}
\newcommand\ctest[1]{%
  \setsepchar{ }%
  \readlist\mylist{#1}%
  \foreachitem\i\in\mylist{\ifnum\icnt=1\else\textunderscore\fi%
  \expandafter\uppercase\expandafter{\i}}%
}
\begin{document}
\ctest{one word}
\ctest{one two three words}
\end{document}
  • One quick follow up: if I'm understanding the stringstrings documentation correctly, I'm surprised that \convertchar can accept a null string in the from string argument. Did I just understand that incorrectly? Thanks again for all of the help!!! – Moneer Helu Feb 8 '18 at 21:46
  • @MoneerHelu It is not a null string, but rather a blank space between the braces. – Steven B. Segletes Feb 9 '18 at 2:41

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.