# How to use stringstrings to include braces in to-string

Macrons in LaTeX are typset with '\=' preceeding the character, for example '\=o' creates an 'o' with a macron. I would like to use stringstrings to define a newcommand to replace all '/' characters with the macron '\=' sequence. The catch- the letter 'i' is special. In LaTeX you have to use a non-dotted 'i', e.g. '\={\i}' in order to create the 'i' with a macron. This special case is breaking my new command. Here is my attempt at this:

\documentclass{article}
\usepackage{stringstrings}
\newcommand\macronify[1]{%
\convertword[q]{#1}{/i}{\={\i}}%
\convertchar{\thestring}{/}{\=}%
}
\begin{document}
This is a test: \macronify{laud/o, laud/are, laud/av/i, laudatum}.
\end{document}


Running pdflatex on this creates a PDF, and the first two words do have the macrons as expected, but the 3rd word with the troublesome 'i' is messed up. It is displayed as ' . . 22 .. , laudatum'.

Thanks for any help.

Here is a easier solution involving xstring

\documentclass{article}
\usepackage{xstring}
\newcommand\macronify[1]{%
\saveexpandmode\expandarg
\StrSubstitute{\noexpand#1}{/i}{\noexpand\=\i}[\temp]%
\StrSubstitute\temp/{\noexpand\=}\restoreexpandmode
}
\begin{document}
This is a test: \macronify{laud/o, laud/are, laud/av/i, laudatum}.
\end{document}


I recommend against the use of stringstrings package for this task, because it is slow, inefficient, and not intended for manipulating non-regex tokens.

But, as a matter of pride, having written the package long ago, I feel compelled to solve the problem using it. I did have to edit a package routine that had forgotten a % or two and thus introduced stray spaces without the edit.

The key is, for manipulating non-regex tokens (like \= and \i), the capability is quite limited and involves encoding such tokens in ascii escape sequences, manipulating those sequences with regex routines, and then repopulating the resulting string with the original macro tokens.

\documentclass{article}
\usepackage{stringstrings}
\newcommand\macronify[1]{%
\encodetoken{\i}%
\encodetoken[2]{\=}%
\convertword[e]{#1}{/i}{\=\i}%
\convertchar[e]{\thestring}{/}{\=}%
\retokenize{\thestring}\thestring%
\decodetoken{\i}%
\decodetoken[2]{\=}%
}

%%%%% ADDED SOME MISSING % SIGNS IN THIS stringstings CODE
\makeatletter
\renewcommand\testmatchingchar[3]{%
\setbox0=\hbox{%
\substring[e]{#1}{#2}{#2}\+%
\isnextbyte[q]{\EscapeChar}{#3}%
\if T\theresult%
\isnextbyte[q]{\EscapeChar}{\thestring}%
\if T\theresult%
\if \@teststring\@testcode\matchingchartrue\else\matchingcharfalse\fi
\else
\global\matchingcharfalse%
\fi
\else
\if \thestring#3\global\matchingchartrue\else\global\matchingcharfalse\fi
\fi}%
\?}
%%%%%
\makeatother

\begin{document}
This is a test: \macronify{laud/o, laud/are, laud/av/i, laudatum}.
\end{document}


I consider my honor defended.

I'm not sure how to do it with stringstrings, but there's an easier method:

\documentclass{article}
\usepackage{xparse}

\DeclareTextCompositeCommand{\=}{\encodingdefault}{i}{\={\i}}

\ExplSyntaxOn
\NewDocumentCommand\macronify{m}
{
\tl_set:Nn \l_tmpa_tl { #1 }
\tl_replace_all:Nnn \l_tmpa_tl { / } { \= }
\tl_use:N \l_tmpa_tl
}
\ExplSyntaxOff

\begin{document}
This is a test: \macronify{laud/o, laud/are, laud/av/i, laudatum}.
\end{document}


The first instruction defines \=i as a known combination that is transformed into \={\i}. Thus we just have to substitute / with \= and this is the job of \tl_replace_all:Nnn.

Note that your macro with stringstrings applied to laud/o produces

laud\unhbox \voidb@x \bgroup \let \unhbox \voidb@x \setbox \@tempboxa \hbox {o\global \mathchardef \accent@spacefactor \spacefactor }\accent 22 o\egroup \spacefactor \accent@spacefactor


which is not something I'd like to transform my tokens into.