4

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.

8
  • 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. – mberthet 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 ? – mberthet 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
1

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}

enter image description here

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}
4
  • Thank you a lot, this seems perfect. I will try it out ASAP. – mberthet 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 ? – mberthet Nov 27 '15 at 1:15
  • Well, it works fine if I replace : by * as a splitter. No idea why though. – mberthet Nov 27 '15 at 1:19
  • 1
    @mberthet Judging from your nickname, you're French. With babel-french, the colon becomes a special character. – egreg Nov 27 '15 at 9:34
3

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}
1
  • 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. – mberthet Nov 24 '15 at 21:48
0

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.

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.