If your first word is always separated from the rest by a space, you can do with the following code:
\documentclass{article}
\makeatletter
\newcommand{\transform}[1]{\transform@#1\@nil}
\def\transform@@prefix{my}
\def\transform@#1 #2\@nil{%
\lowercase{\def\transform@@start{#1}}%
\ifx\transform@@start\transform@@prefix
\textbf{#2}%
\else
\textit{#2}%
\fi
}
\makeatother
\begin{document}
\transform{my big world} should return \textbf{big world}.
\transform{our small world} should return \textit{small world}.
\transform{your world} should return \textit{world}
\transform{My world} should return \textbf{world}
\end{document}
The first word is isolated and its lowercase version is matched with my
.
Since you want a colon, rather than a space, it's possible to manage the absence of a prefix.
\documentclass{article}
\makeatletter
\newcommand{\transform}[1]{\transform@#1::\@nil}
\def\transform@@prefix{my}
\def\transform@#1:#2:#3\@nil{%
\if\relax\detokenize{#2}\relax
% no colon in #1
\textit{#1}%
\else
\lowercase{\def\transform@@start{#1}}%
\ifx\transform@@start\transform@@prefix
\textbf{#2}%
\else
\textit{#2}%
\fi
\fi
}
\makeatother
\begin{document}
\transform{my:big world} should return \textbf{big world}.
\transform{our:small world} should return \textit{small world}.
\transform{your:world} should return \textit{world}
\transform{My:world} should return \textbf{world}
\transform{world} should return \textit{world}
\end{document}
An expl3
version, which is also (almost) fully expandable (it is not really because of \textit
and \textbf
, but we can use \text_expand:n
to take care of that.
\documentclass{article}
\ExplSyntaxOn
% just for the final test
\cs_new_eq:NN \textexpand \text_expand:n
%%%
\NewExpandableDocumentCommand{\transform}{sm}
{
\IfBooleanTF{#1}
{
\tohiko_transform:V #2
}
{
\tohiko_transform:n { #2 }
}
}
\cs_new:Npx \tohiko_transform:n #1
{% colons are special in expl3
\exp_not:N \__tohiko_transform:w #1 \c_colon_str \c_colon_str \exp_not:N \q_stop
}
\cs_generate_variant:Nn \tohiko_transform:n { V }
\use:x
{% colons are special in expl3
\cs_new:Npn \exp_not:N \__tohiko_transform:w
##1 \c_colon_str ##2 \c_colon_str ##3 \exp_not:N \q_stop
}
{
\tl_if_empty:nTF { #2 }
{
\__tohiko_transformed:Nn \textit { #1 }
}
{
\__tohiko_transform:nn { #1 } { #2 }
}
}
\cs_new:Npn \__tohiko_transform:nn #1 #2
{
\str_if_eq:eeTF { \str_lowercase:n { #1 } } { my }
{
\__tohiko_transformed:Nn \textbf { #2 }
}
{
\__tohiko_transformed:Nn \textit { #2 }
}
}
\cs_new:Npn \__tohiko_transformed:Nn #1 #2
{
#1{\tl_trim_spaces:n{#2}}
}
\ExplSyntaxOff
\newcommand{\testA}{my:hello world}
\newcommand{\testB}{our:hello world}
\begin{document}
\transform{my: big world} should return \textbf{big world}.
\transform{our:small world} should return \textit{small world}.
\transform{your:world } should return \textit{world}.
\transform{My:world} should return \textbf{world}.
\transform{world} should return \textit{world}.
\transform*{\testA} should return \textbf{hello world}.
\transform*{\testB} should return \textit{hello world}.
\edef\test{\textexpand{\transform{my: big world}}}
\texttt{\meaning\test}
\edef\test{\textexpand{\transform*{\testB}}}
\texttt{\meaning\test}
\end{document}
This is essentially the same as @gernot's answer but reduces the number of \expandafter
s and \csname
s making the code more readable, imho.
The approach uses two steps of processing, the first step just reads in the first argument (the others are curried) and creates the macro names from it, resulting in two new arguments. The next step then gets all the arguments.
\documentclass[]{article}
\usepackage{tikz}
\makeatletter
\newcommand\newABC[1]
{%
% #1: name for macro and box
% #2: before (curried)
% #3: raise (curried)
% #4: after (curried)
% #5: contents (curried)
\expandafter\newABC@\csname #1\expandafter\endcsname\csname #1box\endcsname
}
\newcommand\newABC@[6]
{%
% #1: macro
% #2: box-macro
% #3: before
% #4: raise
% #5: after
% #6: contents
\newsavebox#2%
\sbox#2{\mathalpha{\hspace{#3pt}\raisebox{#4pt}{#6}\hspace{#5pt}}}%
\newcommand#1{\usebox#2}%
}
\makeatother
\newABC{ehh}{1}{1}{.5}
{%
\begin{tikzpicture}
\node at (0,0){\(h\)};
\end{tikzpicture}%
}
\begin{document}
A\ehh b
\end{document}
As requested a few explanations on the code:
\csname
expands all following tokens until it finds an \endcsname
and the result is turned into a control sequence.
\expandafter
steps over the next token (regardless which kind of token, an opening brace for instance is a token as well which could be stepped over with this) and expands the token after that one once (if that token isn't expandable nothing happens).
So \expandafter\stuff\csname foo\endcsname
will result in \stuff
being stepped over and \csname
being expanded once. Within a single step of expansion \csname
expands all following tokens until it finds an \endcsname
and leaves everything in between as the name of a control sequence. In this case it'll find foo
(letters don't expand further), and so after \csname
is done the \expandafter
will be removed from the input stream and \stuff
put back, so the input will now contain \stuff\foo
.
We can utilize the fact that \csname
expands everything until it finds an \endcsname
to build two control sequences at once (in the following the next thing TeX will evaluate will be preceded by |>
and the tokens stored to be put back because TeX stepped over them will be preceded by ||
-- this is the same style the unravel
package would use, though my steps might not be the same that package would show):
|> \expandafter\stuff\csname foo\expandafter\endcsname\csname bar\endcsname
will first step over \stuff
, so the input will look like this (this is less than one step of expansion, more a step of processing):
|| \expandafter\stuff
|> \csname foo\expandafter\endcsname\csname bar\endcsname
Now \csname
will start grabbing/expanding tokens, and because of \expandafter
the \endcsname
will not be found, instead TeX steps over it and expands what follows:
|| \expandafter\stuff
|| \csname foo\expandafter\endcsname
|> \csname bar\endcsname
Now the second \csname
grabs/expands tokens until it finds \endcsname
and turn the found string into a control sequence:
|| \expandafter\stuff
|| \csname foo\expandafter\endcsname
|| \csname bar
|> \endcsname
and
|| \expandafter\stuff
|| \csname foo\expandafter\endcsname
|| \bar
Now the second \csname
is done with one step of expansion and the second \expandafter
will be removed and the token which followed it put back, so the next step of processing would look like
|| \expandafter\stuff
|| \csname foo
|> \endcsname\bar
The first \csname
finally finds its \endcsname
and this will become
|| \expandafter\stuff
|| \foo\bar
Now also the first \csname
had its step of expansion from \expandafter
, so it'll be removed and \stuff
put back, so this eventually becomes
|> \stuff\foo\bar
and now \stuff
can do stuff.
Even though the above was visualized in many small steps of processing when we look at expansion steps this is all done in a single step, because \expandafter
will in a single step expand the \csname
and that will fully expand the remaining stuff in this one step.
Best Answer
You can use
\@tfor
. I provide also a better redefinition of the dot under according to your wish:What does
\@tfor
do? Its syntax isThe scratch macro is traditionally
\next
, but it can be anything. The<tokens>
part is any (brace balanced) list of tokens. In the loop, LaTeX essentially does\def<scratch macro>{<next token>}
, sowill perform
However, with
\@tfor\next:=d {sa}\do{\d{\next}}
we will just obtainExplicit space tokens are ignored and braced groups of tokens are treated as one.
The
expl3
analog is\tl_map_inline:nn
:No scratch macro is used: the current item in the loop is denoted by
#1
(which becomes##1
in the body of a definition, as usual).In this particular case where just a single command is applied with the current item as argument, one can use
\tl_map_function:nN
:which has the same effect and is shorter. It can also appear in a full expansion context (not for this particular case, because of
\d
).