7

I have a "second order" incompatibility problem between: classicthesis, StrSubstitute and accented characters. Here is a MWE:

\documentclass[italian]{article}
\usepackage[utf8]{inputenc}
\usepackage[nochapters]{classicthesis}
\usepackage{xstring}

\begin{document}
Il modello associa un valore di \StrSubstitute{verità}{x}{y}\
ad ogni formula.
\end{document}

The compilation gives the following error:

! Argument of \MT@res@a has an extra }.

But if I remove the classicthesis package, or remove the StrSubstitute command or remove the accented character: then the compilation works without errors!

1
  • 7
    this isn't really related to classicthesis other than it loads microtype – David Carlisle May 28 '18 at 10:46
6

xstring functions use \edef which means that any commands that do not work by pure expansion are likely to fail. You get the same error with this simplified input

\documentclass[italian]{article}
\usepackage[utf8]{inputenc}
\usepackage{microtype}


\begin{document}
Il modello associa un valore di 
\edef\foo{verità}

ad ogni formula.
\end{document}

You could use

 {\def\protect{\noexpand\protect\noexpand}\StrSubstitute{verità}{x}{y}}

which makes no error, but drops the accent, depending on the actual requirement it is probably easiest to use an expandable string replace function rather than xstring.

this for example replaces x by y while preserving the accented a

\documentclass[italian]{article}
\usepackage[utf8]{inputenc}
\usepackage{microtype}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand\repl{mmm}
 {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \regex_replace_once:nnN { #2 } { #3 } \l_tmpa_tl
  \tl_use:N \l_tmpa_tl
 }
\ExplSyntaxOff

\begin{document}
Il modello associa un valore di \repl{vxerità}{x}{y}
ad ogni formula.
\end{document}
6
  • Can you suggest an expandable string replace function? I need to replace the "!" character used in the \index command with a space. – Emanuele Paolini May 28 '18 at 11:04
  • @EmanuelePaolini updated answer – David Carlisle May 28 '18 at 11:13
  • maybe \usepackage{l3regex} is required? – Emanuele Paolini May 28 '18 at 11:32
  • @EmanuelePaolini oh only if you have an old installation, I tested the answer as posted, regex has been a part of core expl3 for some time – David Carlisle May 28 '18 at 12:12
  • 1
    @moewe I shall summon the culprit to come back and fix it! – David Carlisle May 28 '18 at 14:15
5

The problem, as you discovered, is that \StrSubstitute executes \edef on its arguments. However, this can be avoided.

\documentclass[italian]{article}
\usepackage[utf8]{inputenc}
\usepackage[nochapters]{classicthesis}
\usepackage{xstring}

\begin{document}

Il modello associa un valore di
\saveexpandmode\noexpandarg
\StrSubstitute{virità}{i}{e}
\restoreexpandmode\
ad ogni formula.

\bigskip

\saveexpandmode\noexpandarg
\StrSubstitute{viritò}{ò}{à}
\restoreexpandmode\

\end{document}

If you never need other modes (check the manual, section 3.1.1), you can issue \noexpandarg in the preamble and forget about saving and restoring it.

An easier method might be to use an expl3 implementation (currently classicthesis raises an error, which you can safely ignore).

\documentclass[italian]{article}
\usepackage[utf8]{inputenc}
\usepackage[nochapters]{classicthesis}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\xStrSubstitute}{mmmo}
 {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \tl_replace_all:Nnn \l_tmpa_tl { #2 } { #3 }
  \IfNoValueTF{#4}
   { \tl_use:N \l_tmpa_tl }
   { \tl_set_eq:NN #4 \l_tmpa_tl }
 }
\ExplSyntaxOff

\begin{document}

Il modello associa un valore di
\xStrSubstitute{virità}{i}{e}\
ad ogni formula.

\bigskip

\xStrSubstitute{viritò}{ò}{à}

\end{document}

enter image description here

4

listofitems to the rescue.

\documentclass[italian]{article}
\usepackage[utf8]{inputenc}
\usepackage[nochapters]{classicthesis}
\usepackage{listofitems}
\newcommand\loiStrSubstitute[3]{%
  \setsepchar{#2}%
  \readlist\mylist{#1}%
  \foreachitem\x\in\mylist{\ifnum\xcnt=1\else#3\fi\x}%
}
\begin{document}
Il modello associa un valore di \loiStrSubstitute{verità}{e}{x}\
ad ogni formula.

\loiStrSubstitute{verità}{à}{x}

\loiStrSubstitute{verititità}{i}{o}
\end{document}

enter image description here

If you need a star version of the macro that only substitutes the first occurrence,

\documentclass[italian]{article}
\usepackage[utf8]{inputenc}
\usepackage[nochapters]{classicthesis}
\usepackage{listofitems}
\makeatletter
\newcommand\loiStrSubstitute{%
  \@ifstar{\loiStrSubstitutefirst}{\loiStrSubstituteall}}
\makeatother
\newcommand\loiStrSubstituteall[3]{%
  \setsepchar{#2}%
  \readlist\mylist{#1}%
  \foreachitem\x\in\mylist{\ifnum\xcnt=1\else#3\fi\x}%
}
\newcommand\loiStrSubstitutefirst[3]{%
  \setsepchar{#2}%
  \readlist\mylist{#1}%
  \foreachitem\x\in\mylist{\ifnum\xcnt=1\else\ifnum\xcnt=2\relax#3\else#2\fi\fi\x}%
}
\begin{document}
Il modello associa un valore di \loiStrSubstitute{verità}{e}{x}\
ad ogni formula.

\loiStrSubstitute{verità}{à}{x}

\loiStrSubstitute{verititità}{i}{o}

\loiStrSubstitute*{verititità}{i}{o}
\end{document}

enter image description here

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.