解析 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}

每个参数可以包含多个字符,包括逗号!

我尝试过从包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

由于您确实在寻找“超越”文档命令的解析(IE这不是一个简单的命令的标准 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}

相关内容