在 \@for 循环的输出上调用 Lua,将“and”添加到逗号分隔列表的末尾

在 \@for 循环的输出上调用 Lua,将“and”添加到逗号分隔列表的末尾

我正在尝试制作一个无包命令,该命令在逗号分隔的列表中应用命令,然后根据语法要求将单词“and”添加到输出中。我已经已经得到了一些帮助构建\apply命令,现在我正在处理\addandtolist命令。\apply\addandtolist命令似乎可以单独工作,但不能组合使用。具体来说,在以下测试文档中,测试 3 失败,但如果从文档中删除测试 3,测试 1 和 2 会成功:

\documentclass[letterpaper]{article}

% This command is for applying a single command to a comma-separated list of tokens, and listing the results separated by ", "
\makeatletter
\newcommand{\apply}[3][, ]{
% #1: optional separator to print between applications; default=[, ]
% #2: command to apply; 
% #3: list to apply command to 
  \def\itemsep{\def\itemsep{#1}} % first call to \itemsep prints nothing; later calls print #1
  \def\zz{\itemsep#2}%
  \@for \listelement:=#3\do{\expandafter\zz\expandafter{\listelement}}%
}
\makeatother

% The following command is for adding an "and" to a comma-separated list, if grammatically appropriate:
\newcommand{\addandtolist}[1]{%
\directlua{
    s = string.explode("#1","")
    commacounter=0
    lastcomma=-1
    for key, value in pairs(s) do 
        if value=="," then 
            commacounter=commacounter+1 
            lastcomma=key
        end
    end
    if commacounter==1 then
        s[lastcomma]=" and "
    elseif commacounter>1 then
        s[lastcomma]=", and "
    end
    t=""
    for key, value in pairs(s) do
        t=t..value
    end
    tex.sprint(t)
}
}

\begin{document}
\noindent Test 1 (succeeds): As hoped, these letters print in lowercase:\\
\apply{\lowercase}{U,V,W,X,Y}\\
\newcommand{\ComplicatedCommand}[1]{\lowercase{#1}}
\apply{\ComplicatedCommand}{U,V,W,X,Y}\\

\ 

\noindent Test 2 (succeeds): These lists get an ``and'' added to them if appropriate:\\
\addandtolist{u}\\
\addandtolist{u, v}\\
\addandtolist{u, v, w, x, y}\\

\noindent Test 3 (fails): Calling the ``addandtolist" command on the output of the apply command returns at error:\\
\addandtolist{\apply{\lowercase}{U,V,W,X,Y}}\\
\addandtolist{\apply{\ComplicatedCommand}{U,V,W,X,Y}}\\


\end{document}

排除检验 3 后的结果:

检测结果

包含测试 3 时出错:

在此处输入图片描述

如果最终结果能与 Lua 配合使用,那就太棒了,但我也接受非 Lua 解决方案。\usepackage不过,我确实希望结果不包含任何调用,因为我想避免调用可能最终干扰其他包的包。

非常感谢您提供的帮助!

答案1

由于您正在遍历 tex 中的列表,因此我将添加and使用相同类型的习语。

在此处输入图片描述

\documentclass[letterpaper]{article}

% This command is for applying a single command to a comma-separated list of tokens, and listing the results separated by ", "
\makeatletter
\newcommand{\apply}[3][, ]{%
% #1: optional separator to print between applications; default=[, ]
% #2: command to apply; 
% #3: list to apply command to 
  \def\zzitemsep{\def\zzitemsep{\ifnum\count@=\z@\space and \else#1\fi}} % first call to \zzitemsep prints nothing; later calls print #1
  \count@\z@
  \@for \listelement:=#3\do{\advance\count@\@ne}%
  \def\zz{\zzitemsep#2}%
  \@for \listelement:=#3\do{\advance\count@\m@ne\expandafter\zz\expandafter{\listelement}}%
}
\makeatother


\begin{document}
\noindent Test 1 (succeeds): As hoped, these letters print in lowercase:\\
\apply{\lowercase}{U}\\
\apply{\lowercase}{U,V}\\
\apply{\lowercase}{U,V,W,X,Y}\\
\newcommand{\ComplicatedCommand}[1]{\lowercase{#1}}
\apply{\ComplicatedCommand}{U,V,W,X,Y}\\


\end{document}

这里进行两次计数列表,以便您知道何时添加and。请注意使用更完整的列表结构,例如,expl3列表长度已经“已知”。

相关内容