Анализ csv-списка, функция с >1 параметрами в качестве обратного вызова

Анализ csv-списка, функция с >1 параметрами в качестве обратного вызова

В своих текстах мне приходится иметь дело со списками, пункты которых необходимо форматировать отдельно, например:

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

В \funktionкотором происходит \emphsubsupформатирование и обрабатываются необязательные параметры.

Как можно сократить эту задачу с помощью функции типа \funktionen? То есть:

\funktionen{[3][]{T},{Sp},[3][{7,9,11}]{D},{T}}или даже лучше:

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

Каждый аргумент может содержать более 1 символа, включая запятую!

Я пробовал это с forcsvlistиз etoolboxпакета, но он (конечно) принимает все значение [3][]{T}как один аргумент. Также я не знаю, как реализовать разделитель --.

МВЭ:

\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

Поскольку вы действительно ищете синтаксический анализ «за пределами» команды документа (то естьэто не совсем стандартный аргумент в стиле LaTeX2e для простой команды) Я бы поддался соблазну самому написать код для синтаксического анализатора. Предполагая, что вам не нужно беспокоиться о вложенных [/ ](в этом случае, я полагаю, вам нужно xparse), мы можем сделать это довольно просто, используя «классический» подход с опережением. Я сделал это в , expl3но это также можно легко сделать с помощью \@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}

Я использовал последовательность для хранения «частичного» списка элементов, так как это упрощает вставку разделителей ( --) без необходимости самостоятельно проводить какие-либо тесты для «конца списка» или чего-то подобного. Вместо этого в этом случае можно было бы использовать вручную созданное отображение, но если производительность не имеет решающего значения, то это будет менее понятно, чем подход здесь.

Для expl3экспертов отмечу, что здесь мы могли бы использовать \tl_if_head_eq_meaning:nNTFвместо , \peek_meaning:NTFпоскольку аргумент уже был услышан.

решение2

Если вас не смущает выполнение функции внутри TeXгруппы, то вы можете попробовать 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}

введите описание изображения здесь

Однако пользовательский парсер списков довольно прост:

\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}

Результат тот же, что и прежде.

решение3

Далее следует решение без необходимости использования какого-либо пакета LaTeX. После

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

Вы сохранили следующий контент:

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

в \funktionenLмакросе. Вы можете выполнить его, просто запустив \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}

Связанный контент