2

Consider the following document:

\documentclass{article}
\usepackage{xstring}

\makeatletter
\newcommand{\mycommand@firstchar}[1]{%
    \StrRemoveBraces{#1}[\FirstChar]%
    \StrChar{\FirstChar}{1}[\FirstChar]%
    \FirstChar%
}
\newcommand{\mycommand@removespaces}[1]{\zap@space#1 \@empty}
\newcommand{\mycommand@lowercase}[1]{\expandafter\MakeLowercase\expandafter{#1}}
\newcommand{\makecode}[3]{\mycommand@removespaces{\mycommand@lowercase{%
    \mycommand@firstchar{#1}\StrRemoveBraces{#2}:\StrRemoveBraces{#3}%
}}}
\makeatother

\begin{document}
\makecode{First}{Second}{Third}
%should produce fsecond:third
\end{document}

What I am trying to do is to write a command that takes 3 arguments, keep the letter of the first one, combine it with the second one, adds a colon separator and adds the third parameter, while removing all the spaces and braces and making the whole thing lower case.

However the current code shown above fails to compile, and I don't understand why, and how to solve the problem.

1
  • \MakeLowercase doesn't return the lowercased argument, but the set of instructions to print the argument lowercase.
    – egreg
    Nov 17, 2019 at 0:20

1 Answer 1

2

\MakeLowercase doesn't return its argument in lowercase form, but rather the set of instructions for printing the argument lowercase.

You need an expandable version of \MakeLowercase and expl3 comes to the rescue:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\makecode}{mmm}
 {
  \vincent_makecode:nnn { #1 } { #2 } { #3 }
 }

\tl_new:N \l__vincent_makecode_word_tl

\cs_new_protected:Nn \vincent_makecode:nnn
 {
  \vincent_makecode_process:Nn \tl_head:N { #1 }
  \vincent_makecode_process:Nn \tl_use:N  { #2 }
  :
  \vincent_makecode_process:Nn \tl_use:N { #3 }
 }

\cs_new_protected:Nn \vincent_makecode_process:Nn
 {
  % store the lowercased argument for further processing
  \tl_set:Nx \l__vincent_makecode_word_tl { \tl_lower_case:n { #2 } }
  % remove braces and spaces
  \regex_replace_all:nnN { (\cB.|\cE.|\s) } { } \l__vincent_makecode_word_tl
  % issue the result, #1 is either \tl_head:N or \tl_use:N
  #1 \l__vincent_makecode_word_tl
 }

\ExplSyntaxOff

\begin{document}

\makecode{First}{Second}{Third}

\makecode{{Fi}rs{t}}{Se co{nd}}{T h i r d}

\end{document}

enter image description here

Just for completeness, an xstring version:

\documentclass{article}
\usepackage{xstring}

\makeatletter
\newcommand{\mycommand@firstchar}[1]{%
    \StrRemoveBraces{#1}[\v@First]%
    \StrDel{\v@First}{ }[\v@First]
    \StrChar{\v@First}{1}[\v@First]%
}
\newcommand{\mycommand@remove}[2]{%
  \StrRemoveBraces{#1}[#2]%
  \StrDel{#2}{ }[#2]%
}
\newcommand{\makecode}[3]{%
  \mycommand@firstchar{#1}%
  \mycommand@remove{#2}{\v@Second}%
  \mycommand@remove{#2}{\v@Third}%
  \MakeLowercase{\v@First\v@Second:\v@Third}%
}
\makeatother

\begin{document}

\makecode{First}{Second}{Third}

\makecode{{Fi}rs{t}}{Se co{nd}}{T h i r d}

\end{document}
0

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.