根据参数进行分支的动词宏(实现关联列表)

根据参数进行分支的动词宏(实现关联列表)

我想在 LaTeX 中实现一个简单的关联列表。我的想法是,我可以输入\branch|Some arbitrary !_{} text here|,它将Some arbitrary !_{} text here在 (静态) 映射表中查找string → string并根据需要进行替换。

有两个棘手的方面:

  • 解析命令的逐字参数。为此,我可以使用xparse及其\NewDocumentCommand

  • 实现关联列表。为此我可以使用嵌套\ifstrequal命令。

不过,我不确定如何将两者结合起来。这是一个 MWE;它适用于关联列表AAA → "Found some As", BBB → "Found some Bs"

\documentclass{article}

\usepackage[english]{babel}
\usepackage{etoolbox}
\usepackage{xparse}

\NewDocumentCommand\branch{v}{%
  \ifstrequal{#1}{AAA}{Found some As!}{%
    \ifstrequal{#1}{BBB}{Found some Bs!}{%
      Key not found: \texttt{#1}!}}}

\begin{document}
\branch|AA|\\
\branch|AAA|\\
\branch/BBB/\\
\branch!BB!

\branch|AA!}/|
\branch|BB!\/:|
\end{document}

我应该如何修改这个 MWE 来添加最后两个键(AA!}/BB!\/:)的映射?虽然我的\branch命令可以很好地解析它们,但我不知道将逐字字符串传递给的优雅方法\ifstrequal。我目前最好的方法是:

\NewDocumentCommand\MakeTable{v v v v}{%
  \NewDocumentCommand\fancybranch{v}{%
    \ifstrequal{##1}{#1}{Found some As!}{%
      \ifstrequal{##1}{#2}{Found some Bs!}{%
        \ifstrequal{##1}{#3}{Found some weird As!}{%
          \ifstrequal{##1}{#4}{Found some weird Bs!}{%
            Key not found: \texttt{#1}!}}}}}}

\MakeTable|AAA||BBB||AA!}/||BB!\/:|

这让我可以使用\fancybranch而不是branch,一切看起来都很好,但看起来不太优雅;欢迎提出建议。有没有更好的方法来实现这个? 使用etoolboxxparse依赖这个\MakeTable宏看起来有点重量级(另一方面,代码本身就相当易读)。

答案1

由于您评论说可能会有更轻量级的版本,即无软件包版本,请注意,这使用 csname 哈希表来查找项目,而不是通过列表进行线性搜索。

\documentclass{article}

\makeatletter

\def\branch{%
\begingroup
\let\do\@makeother\dospecials
\xxbranch}
\def\xxbranch#1{\def\tmp##1#1{\endgroup\xbranch{##1}}\tmp}

\def\xbranch#1{%
\expandafter\ifx\csname X-\detokenize{#1}\endcsname\relax
\texttt{\detokenize{#1}} Not found%
\else
\csname X-\detokenize{#1}\expandafter\endcsname
\fi}

\def\defbranch{%
\begingroup
\let\do\@makeother\dospecials
\xxdefbranch}
\def\xxdefbranch#1{\def\tmp##1#1{\endgroup\xdefbranch{##1}}\tmp}
\def\xdefbranch#1{\expandafter\def\csname X-\detokenize{#1}\endcsname}

\defbranch|AAA|{Found some As!}
\defbranch|BBB|{Found some Bs!}
\defbranch|AA!}/|{Found some weird As!}
\defbranch|BB!\/:|{Found some weird Bs!}


\begin{document}
\branch|AA|\\
\branch|AAA|\\
\branch/BBB/\\
\branch!BB!

\branch|AA!}/|
\branch|BB!\/:|
\end{document}

答案2

充分利用expl3

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand\branch{v}
 {
  \clement_branch:n { #1 }
 }
\cs_new_protected:Nn \clement_branch:n
 {
  \str_case_x:nnF { #1 }
   {
    {AAA}{Found~some~As!}
    {BBB}{Found~some~Bs!}
    {AA!\c_right_brace_str/}{Found~some~weird~As!}
    {BB!\c_backslash_str/:}{Found~some~weird~Bs!}
   }
   {Key~not~found~\texttt{#1}!}
 }
\ExplSyntaxOff

\begin{document}
1. \branch|AA|

2. \branch|AAA|

3. \branch/BBB/

4. \branch!BB!

5. \branch|AA!}/|

6. \branch|BB!\/:|

\end{document}

在此处输入图片描述

一种可以更容易地定义各个分支的替代方法。

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand\branch{v}
 {
  \clement_branch:n { #1 }
 }
\NewDocumentCommand{\definebranch}{vm}
 {
  \prop_gput:Nnn \g_clement_branches_prop { #1 } { #2 }
 }

\cs_new_protected:Nn \clement_branch:n
 {
  \prop_get:NnN \g_clement_branches_prop { #1 } \l__clement_branch_temp_tl
  \quark_if_no_value:VTF \l__clement_branch_temp_tl
   { Key~not~found~\texttt{#1}! }
   { \tl_use:N \l__clement_branch_temp_tl }
 }
\cs_generate_variant:Nn \quark_if_no_value:nTF { V }
\prop_new:N \g_clement_branches_prop
\tl_new:N \l__clement_branch_temp_tl
\ExplSyntaxOff

\definebranch|AAA|{Found some As!}
\definebranch|BBB|{Found some Bs!}
\definebranch|AA!}/|{Found some weird As!}
\definebranch|BB!\/:|{Found some weird Bs!}

\begin{document}
1. \branch|AA|

2. \branch|AAA|

3. \branch/BBB/

4. \branch!BB!

5. \branch|AA!}/|

6. \branch|BB!\/:|

\end{document}

相关内容