Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I want to write a macro in which I can split a string with a linking character (like a hyphen) into different words. So, I have something like \macro{one-two-three} which I would like to split into three different words. Similarly, \macro{four-five} should print "four five" (please note the space).

A restriction is that I don't want to load any package to keep the tex-file as small as possible. So I don't want to use xstring or substr or anything else.

How do I write a macro which returns me the separate words?

I'm new here, so my apologies if I didn't explain my problem clearly.

share|improve this question
    
Welcome to TeX.SX! With "return" you mean that writing \macro{four-five} LaTeX should print "four five"? –  egreg Oct 29 '12 at 14:44
    
Welcome to TeX.sx! A tip: You can use backticks ` to mark your inline code. –  Corentin Oct 29 '12 at 14:44
    
Yes indeed. The space inbetween is mandatory for me. –  Peter Oct 29 '12 at 14:45
4  
If you want to keep your tex-file small loading a suitable package is the way to go. I doubt that a handmade definition can be shorter than \usepackage{...}. –  Ulrike Fischer Oct 29 '12 at 14:46

2 Answers 2

This will work without any package; but it would be much easier with xstring or xparse:

\documentclass{article}
\makeatletter
\newcommand{\splitlist}[1]{\@splitlist#1\@nil}
\def\@splitlist#1\@nil{%
  \if\relax\detokenize{#1}\relax
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi
  {\@spl@tlist#1-\@nil}%
}
\def\@spl@tlist#1-#2\@nil{%
  #1\space
  \if\relax\detokenize{#2}\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {\unskip}%
  {\@spl@tlist#2\@nil}%
}
\makeatother

\begin{document}

X\splitlist{}X

X\splitlist{A}X

X\splitlist{A-B}X

X\splitlist{A-B-C}X

\end{document}

enter image description here

Version with xstring:

\usepackage{xstring}
\newcommand{\splitlist}[1]{\StrSubstitute{#1}{-}{ }}

Version with xparse:

\usepackage{xparse}
\NewDocumentCommand{\splitlist}{>{\SplitList{-}}m}
 {\ProcessList{#1}{\addaspace}\unskip}
\newcommand{\addaspace}[1]{#1\space}

Advanced version with xparse:

\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\splitlist}{ m }
 {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \tl_replace_all:Nnn \l_tmpa_tl { - } { ~ }
  \l_tmpa_tl
 }
 \ExplSyntaxOff

Alternative way suggested by Herbert:

\newcommand{\splitlist}{%
  \begingroup\lccode`~=`-
  \lowercase{\def~}{ }%
  \catcode`-=\active
  \splitlistaux}
\newcommand{\splitlistaux}[1]{%
  #1\endgroup}

However this definition disallows \splitlist being in the argument to another command.

share|improve this answer
    
if we make - active and then let-\space maybe another idea –  Herbert Oct 29 '12 at 16:06
    
@Herbert It indeed can be. –  egreg Oct 29 '12 at 16:09
    
Wow, thanks for this elaborate answer, it works perfectly! –  Peter Oct 29 '12 at 16:29

What about something like

\documentclass{article}

\makeatletter
\newcommand\macro[1]{\@macro[#1-]}
\def\@macro[#1-#2]{#1%
  \if\relax\detokenize{#2}\relax
  \else%
    \space\@macro[#2]%
  \fi}
\makeatother

\begin{document}

\macro{one-two-three}

\macro{four-five}

\macro{six}

\end{document}
share|improve this answer
    
This is also a nice solution, and easier to understand for me as a newbee. Thanks a lot! –  Peter Oct 29 '12 at 16:30

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.