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, 2015 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, 2015 at 20:19
  • Sorry, this is not ok -- you change the question and leaves my solution useless!
    – user31729
    Nov 24, 2015 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, 2015 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, 2015 at 21:15

3 Answers 3

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, 2015 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, 2015 at 1:15
  • Well, it works fine if I replace : by * as a splitter. No idea why though.
    – mberthet
    Nov 27, 2015 at 1:19
  • 1
    @mberthet Judging from your nickname, you're French. With babel-french, the colon becomes a special character.
    – egreg
    Nov 27, 2015 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, 2015 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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .