1

In my texts I have to deal with lists, whose items need to be formatted seperatly, i.e.:

\funktion[3][]{T}--\funktion{S}--\funktion[3][7]{D}--\funktion{T}

In \funktion which leads to \emphsubsup the formatting takes place and the optional parameters are handled.

How can I shorten this task by a function like \funktionen? I.e.:

\funktionen{[3][]{T},{Sp},[3][{7,9,11}]{D},{T}} or even better:

\funktionen{[3][]T,Sp,[3][{7,9,11}]D,T}

Each argument can contain more than 1 character, including comma!

I've tried it with forcsvlist from the etoolbox package, but it takes (of course) the whole value [3][]{T} as one single argument. Also I don't know how to realize the seperator --.

MWE:

\documentclass[border=5]{standalone}
\usepackage{etoolbox, xparse, fixltx2e, letltxmacro}

\DeclareDocumentCommand{\subsup}{ o o m }{%
\IfValueTF{#1}{%
    \IfValueTF{#2}{%
    \textsubscript{#1}#3\textsuperscript{#2}%
    }{%
    #3\textsuperscript{#1}}%
}{#3}%
}
\DeclareDocumentCommand{\emphsubsup}{ o o m }{\emph{\subsup[#1][#2]{#3}}}%same, only emphasized

\LetLtxMacro{\funktion}{\emphsubsup}

%test
\newcommand*{\funktionen}[1]{%
    \forcsvlist{\funktion}{#1}
}

\begin{document}

    \funktion[3][]{T}--\funktion{Sp}--\funktion[3][7,9,11]{D}--\funktion{T}

    \hskip1ex

    \funktionen{[3][]{T},{Sp},[3][{7,9,11}]{D},{T}}

\end{document}
1
  • This question about extending forcsvtlist to take more than one argument may be useful for you. It's not exactly what you want, but just have to add some braces around each group: \forcsvlistargs{mycmd}{ {{1a}{1b}} , {{2a}{2b}} , {{3a}{3b}} }
    – umarcor
    Commented Sep 30, 2014 at 16:10

3 Answers 3

3

As you are really looking for parsing 'beyond' a document command (i.e. this isn't really standard LaTeX2e-style argument to a simple command) I'd be tempted to code the parser bit myself. Assuming you don't need to worry about nested [/] (in which case I guess you do need xparse) we can do it quite simply using a 'classical' look-ahead approach. I've done this in expl3 but it could also be done easily using \@ifnextchar:

\RequirePackage{fixltx2e}
\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\DeclareDocumentCommand \funktionen { > { \SplitList { , } } m }
  {
    \musicman_parse:n {#1}
  }
\seq_new:N \l__musicman_parse_seq
\tl_new:N \l__musicman_tmp_tl
\cs_new_protected:Npn \musicman_parse:n #1
  {
    \group_begin:
      \seq_clear:N \l__musicman_parse_seq
      \tl_map_inline:nn {#1}
        {
          \tl_clear:N \l__musicman_tmp_tl
          \peek_meaning_ignore_spaces:NTF [ % ]
            { \__musicman_parse_auxi:w }
            { \__musicman_parse_auxiii:w }
          ##1 \q_stop
          \seq_put_right:NV \l__musicman_parse_seq \l__musicman_tmp_tl
        }
      \seq_use:Nn \l__musicman_parse_seq { -- }
    \group_end:
  }
\cs_new_protected:Npn \__musicman_parse_auxi:w [ #1 ]
  {
    \tl_set:Nn \l__musicman_tmp_tl { \textsubscript {#1} }
    \peek_meaning_ignore_spaces:NTF [ % ]
      { \__musicman_parse_auxii:w }
      { \__musicman_parse_auxiii:w }
  }
\cs_new_protected:Npn \__musicman_parse_auxii:w [ #1 ] #2 \q_stop
  {
    \tl_put_right:Nx \l__musicman_tmp_tl
      {
        \exp_not:n {#2}
        \tl_if_blank:nF {#1} { \exp_not:n { \textsuperscript {#1} } }
      }
  }
\cs_new_protected:Npn \__musicman_parse_auxiii:w #1 \q_stop
  { \tl_set:Nn \l__musicman_tmp_tl {#1} }
\ExplSyntaxOff
\begin{document}

\funktionen{[3][]{T},{Sp},[3][{7,9,11}]{D},{T}}

\end{document}

I've used a sequence to hold the 'partial' list of items as this makes it easy to insert the separators (--) without having to do any tests myself for 'end of list' or similar. One could instead use a hand-crafted mapping in this case, but unless performance is vital that tends to be less clear than the approach here.

For the expl3 experts, I note that here we could use \tl_if_head_eq_meaning:nNTF instead of \peek_meaning:NTF as the argument has already been grabbed.

4
  • Thank you! Can you check my question update? Your code is pretty abstract which fits my needs more. I just have to use \emph{\musicman_parse:n {#1}} now in \funktionen. But the delimiter -- is missing.
    – musicman
    Commented Sep 30, 2014 at 8:44
  • @musicman I didn't realise the -- was required in the output :-) Fixed that, but I'm not sure what you mean about \emph.
    – Joseph Wright
    Commented Sep 30, 2014 at 9:10
  • Now it's working perfectly. Thx a lot. In some cases (tones) I need the whole string emphasized, in other cases (functions) normal. Hence one function with \emph, one without, no big deal. But one more little question, in case I need it. What's the code to print out -- with surrounding spaces? line \seq_use:Nn \l__musicman_parse_seq { -- }
    – musicman
    Commented Sep 30, 2014 at 9:34
  • 1
    @musicman In expl3 syntax, ~ is used to represent a space so \seq_use:Nn \l__musicman_parse_seq { ~--~ } or similar might be what you want (perhaps you ant thin spaces and/or control of breaking too: it depends on the use case).
    – Joseph Wright
    Commented Sep 30, 2014 at 10:40
4

If you don't mind the function being executed inside a TeX group then you could try pgffor:

\documentclass[border=5]{standalone}

\usepackage{etoolbox, xparse, fixltx2e, pgffor}

\DeclareDocumentCommand{\funktion}{ o o m }{%
\IfValueTF{#1}{%
    \IfValueTF{#2}{%
    \textsubscript{#1}#3\textsuperscript{#2}%
    }{%
    #3\textsuperscript{#1}}%
}{#3}%
}

%test
\newcommand*{\funktionen}[1]{%%
  \foreach \args [count=\x]in {#1}{%
    \ifnum\x>1--\fi\expandafter\funktion\args%
  }%
}

\begin{document}

\funktion[3][]{T}--\funktion{S}--\funktion[3][7]{D}--\funktion{T}
\hskip1ex

\funktionen{[3][]{T},{S},[3][7]{D},{T}}

\end{document}

enter image description here

However, a custom list parser is fairly straightforward:

\documentclass[border=5]{standalone}

\usepackage{etoolbox, xparse, fixltx2e}


\DeclareDocumentCommand{\funktion}{ o o m }{%
\IfValueTF{#1}{%
    \IfValueTF{#2}{%
    \textsubscript{#1}#3\textsuperscript{#2}%
    }{%
    #3\textsuperscript{#1}}%
}{#3}%
}

\newcommand*{\Funktionen}[1]{%
  \let\FunctionenNext=\relax%
  \FunctionenLoop#1,\FunctionenHalt,%
}
\def\FunctionenHalt{\FunctionenHalt}%
\def\FunctionenLoop#1,{%
  \def\tmp{#1}%
  \ifx\tmp\FunctionenHalt%
    \let\FunctionenNext=\relax%
  \else%
    \ifx\FunctionenNext\relax\else--\fi%
    \funktion#1%
    \let\FunctionenNext=\FunctionenLoop%
  \fi%
  \FunctionenNext%
}
\begin{document}

\funktion[3][]{T}--\funktion{S}--\funktion[3][7]{D}--\funktion{T}

\hskip1ex

\Funktionen{[3][]{T},{S},[3][7]{D},{T}}

\end{document}

The result is the same as before.

2
  • Thank you for the quick reply. I figured out that my real life case is a bit more complex which leads to problems. If I use your code for example, only the first character becomes emphasized, but all need to be. Check my new MWE.
    – musicman
    Commented Sep 30, 2014 at 8:27
  • I've accepted Joseph Wrights answer, since it's pretty cool to use the strings without curly braces. Thx for you answer though :)
    – musicman
    Commented Sep 30, 2014 at 9:30
3

The solution without need to any LaTeX package follows. After

\funktionen{[3][]T,Sp,[3][7,9,11]D,T}

you have stored the following content:

\funktion[3][]{T}--\funktion{Sp}--\funktion[3][7,9,11]{D}--\funktion{T}

in \funktionenL macro. You can execute it by simply running \funktionenL.

\long\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}

\def\funktionen#1{\def\funktionenL{}\funktionenA#1,,}
\def\funktionenA{\let\tmpa=\relax \let\tmpb=\relax \futurelet\next\funktionenB}
\def\funktionenB{\ifx\next[\expandafter\funktionenC \else \expandafter\funktionenF \fi}
\def\funktionenC[#1]{\def\tmpa{#1}\futurelet\next\funktionenD}
\def\funktionenD{\ifx\next[\expandafter\funktionenE \else \expandafter\funktionenF \fi}
\def\funktionenE[#1]{\def\tmpb{#1}\funktionenF}
\def\funktionenF#1,{\ifx,#1,\else
   \ifx\funktionenL\empty \else \addto\funktionenL{--}\fi
   \addto\funktionenL{\funktion}%
   \ifx\tmpa\relax\else \funktionenG{\expandafter[\tmpa]}\fi
   \ifx\tmpb\relax\else \funktionenG{\expandafter[\tmpb]}\fi
   \addto\funktionenL{{#1}}%
   \expandafter\funktionenA
   \fi
}
\def\funktionenG{\expandafter\addto\expandafter\funktionenL\expandafter}

\funktionen{[3][]T,Sp,[3][7,9,11]D,T}

\message{\meaning\funktionenL}

You must log in to answer this question.

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