# LaTeX xstring \StrCut with macros

I've been trying to give some formatted input to \StrCut from the xstring package in a very complex code, and I've been getting an error.

Here is a MWE :

\documentclass[a4paper]{article}
\usepackage{xstring}

\begin{document}

\newcommand{\test}{\emph{First} part:Second part}
\StrCut{\test}{:}\firstpart\secondpart%
\firstpart --- \secondpart%

\end{document}


I get this error :

! Use of \@xs@StrCut@@ doesn't match its definition.
\text@command #1->\def \reserved@a {
#1}\ifx \reserved@a \@empty \let \check@...
l.7 \StrCut{\test}{:}
\firstpart\secondpart%


Any tip ?

EDIT :

With this MWE :

\documentclass[a4paper]{article}

\usepackage{xstring}

\begin{document}

\newcommand{\test}{\emph{First} part:Second part}
\newcommand{\testbis}{\test}

\expandarg\StrCut{\testbis}{:}\firstpart\secondpart%

\firstpart --- \secondpart%

\end{document}


I don't get any error, but the output is not what I expect, since \test isn't cut.

• Welcome to TeX.SX! You have to expand the argument here, i.e. \expandarg\StrCut etc.
– user31729
Nov 24 '15 at 17:27
• Thank you a lot ! It cuts the mistake, but it does not solve completely my problem, because my issue was with a macro inside a macro, see my second MWE in Edit. Nov 24 '15 at 20:19
• Sorry, this is not ok -- you change the question and leaves my solution useless!
– user31729
Nov 24 '15 at 21:00
• Sorry then, this is my first question here, I don't know what I should do. Your answer is totally fine for my first question, and does not work for my second question. Should I open another thread for my second question ? Nov 24 '15 at 21:13
• No, I'll try. I suspect that it's not possible to use it the way you've done
– user31729
Nov 24 '15 at 21:15

You don't need \StrCut for this application. There are two problems with your code:

1. You seem to want an arbitrary layer of macros above macros
2. You want to use “dangerous” commands such as \emph, that don't survive full expansion.

You can use \protected@edef in order to overcome the two issues:

\documentclass{article}

\makeatletter
\newcommand{\splitatcolon}[3]{%
\protected@edef\split@temp{#1}%
\expandafter\split@colon\split@temp:\@nil{#2}{#3}%
}
\def\split@colon#1:#2\@nil#3#4{%
\def#3{#1}%
\if\relax\detokenize{#2}\relax
% no colon
\let#4\@empty
\else
\split@eatcolon#2\@nil{#4}%
\fi
}
\def\split@eatcolon#1:\@nil#2{\def#2{#1}}
\makeatother

\begin{document}

\newcommand{\test}{\emph{First} part:Second part}
\newcommand{\testbis}{\test}

\splitatcolon{\emph{First} part:Second part}\firstpart\secondpart

\firstpart\ --- \secondpart

\splitatcolon{\test}\firstpart\secondpart

\firstpart\ --- \secondpart

\splitatcolon{\testbis}\firstpart\secondpart

\firstpart\ --- \secondpart

\splitatcolon{\emph{First} part:Second part:Third part}\firstpart\secondpart

\firstpart\ --- \secondpart

\splitatcolon{\secondpart}\secondpart\thirdpart

\firstpart\ --- \secondpart\ --- \thirdpart

\end{document}


The same idea with xstring:

\documentclass{article}
\usepackage{xstring}

\makeatletter
\newcommand{\splitatcolon}[3]{%
\protected@edef\split@temp{#1}%
\saveexpandmode
\expandarg\StrCut{\split@temp}{:}#2#3%
\restoreexpandmode
}
\makeatother

\begin{document}

\newcommand{\test}{\emph{First} part:Second part}
\newcommand{\testbis}{\test}

\splitatcolon{\emph{First} part:Second part}\firstpart\secondpart

\firstpart\ --- \secondpart

\splitatcolon{\test}\firstpart\secondpart

\firstpart\ --- \secondpart

\splitatcolon{\testbis}\firstpart\secondpart

\firstpart\ --- \secondpart

\splitatcolon{\emph{First} part:Second part:Third part}\firstpart\secondpart

\firstpart\ --- \secondpart

\splitatcolon{\secondpart}\secondpart\thirdpart

\firstpart\ --- \secondpart\ --- \thirdpart

\end{document}

• Thank you a lot, this seems perfect. I will try it out ASAP. Nov 24 '15 at 23:52
• Your code definitely works fine. Sadly in some conditions I couldn't get \splitatcolon working fine. I had a lot of trouble finding out what was the problem, and I've finally understood that it comes from the babel package with the french option. If you add \usepackage[french]{babel} in your code above, it stops working. Any idea why, and how could I cope with this issue ? Nov 27 '15 at 1:15
• Well, it works fine if I replace : by * as a splitter. No idea why though. Nov 27 '15 at 1:19
• @mberthet Judging from your nickname, you're French. With babel-french, the colon becomes a special character. Nov 27 '15 at 9:34

The cutting fails most likely due to \emph, so expand the arguments:

\documentclass[a4paper]{article}
\usepackage{xstring}

\begin{document}

\newcommand{\test}{\emph{First} part:Second part}
\expandarg\StrCut{\test}{:}{\firstpart}{\secondpart}%
\firstpart\ --- \secondpart%

\end{document}


Update

\documentclass[a4paper]{article}

%\usepackage{xstring}

\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\StrCutNew}{mmmm}{%
\tl_set:Nx \l_tmpa_tl {#1}%
\seq_set_split:NnV \l_tmpa_seq {#2} {\l_tmpa_tl}
\expandafter\DeclareDocumentCommand\csname #3\endcsname{}{\seq_item:Nn \l_tmpa_seq{1}}
\expandafter\DeclareDocumentCommand\csname #4\endcsname{}{\seq_item:Nn \l_tmpa_seq{2}}
}
\ExplSyntaxOff

\begin{document}

\newcommand{\test}{First part:Second part}
\newcommand{\testbis}{\test}
\StrCutNew{\test}{:}{firstpart}{secondpart}

\firstpart\ --- \secondpart

\StrCutNew{\test}{:}{firstpart}{secondpart}

\firstpart\ --- \secondpart

\end{document}

• Thank you for helping me. I've just tried your updated code, it crashes for me when I use \emph{...} in the \test command. I got a good result using \StrExpand[3]{\testbis}{\testbisexp} and then feeding \testbisexp to StrCut. But it does not suit me since it depends on the level of expand necessary of \testbis, and I do not know it, it can vary. Nov 24 '15 at 21:48

I found something which seems to be working well for the Edit :

\documentclass[a4paper]{article}

\usepackage{xstring}

\begin{document}

\newcommand{\test}{\emph{First} part:Second part}
\newcommand{\testbis}{\test}

\StrExpand[2]{\test}{\toto}
\StrExpand[2]{\testbis}{\totobis}

\expandarg\StrCut{\emph{First} part:Second part}{:}\firstpart\secondpart%
\firstpart --- \secondpart%

\expandarg\StrCut{\test}{:}\firstpart\secondpart%
\firstpart --- \secondpart%

\expandarg\StrCut{\testbis}{:}\firstpart\secondpart%
\firstpart --- \secondpart%

\expandarg\StrCut{\toto}{:}\firstpart\secondpart%
\firstpart --- \secondpart%

\expandarg\StrCut{\totobis}{:}\firstpart\secondpart%
\firstpart --- \secondpart%

\end{document}


It still doesn't solve the issue in my complex code, but I can't get a MWE to reproduce the issue. I'll come back :D

Thank you Christian Hupfer for your help.