如何防止基于 Lua 的宏对 ConTeXt 中的嵌套宏名起作用?

如何防止基于 Lua 的宏对 ConTeXt 中的嵌套宏名起作用?

我有两个 Lua 函数,它们以不同的方式操作它们的参数,并且定义了两个新的 ConTeXt 宏来让我使用它们。

我试图将它们嵌套在一起,但它们似乎也在消耗和操纵宏调用嵌套顺序会影响它们本身,而不仅仅是输出。在一种嵌套顺序中,这会导致输出不正确;在另一种顺序中,这会导致排版过程中出现致命错误。

这是 MWE:

\startluacode
    userdata = userdata or {}
    
    function userdata.lastWords(s)
        context(s:sub(s:find(" ") + 1))
    end
    
    function userdata.changeCase(s)
        context(s:upper())
    end
\stopluacode

\define[1]\ChangeCase{\ctxlua{userdata.changeCase([==[#1]==])}}
\define[1]\LastWords{\ctxlua{userdata.lastWords([==[#1]==])}}

\starttext

\LastWords{One Two Three A}\par % => "Two Three A"
\ChangeCase{One Two Three B}\par % => "ONE TWO THREE B"
\LastWords{\ChangeCase{One Two Three C}}\par % => "One Two Three C", wrong output
%\ChangeCase{\LastWords{One Two Three D}}\par % uncomment for fatal error

\stoptext

C 的问题在于 \LastWords 会占用全部\ChangeCase{One Two Three C},因此会删除\ChangeCase。这意味着不会删除第一个单词,并且字符串也不会转换为大写。

D 的问题在于它改变了 的大小写,因此由于不是宏,\LastWords它会失败并出现致命错误:\LASTWORDS

! Undefined control sequence

l.1 \LASTWORDS
             {ONE TWO THREE D}

这两者应该只消耗彼此的输出,而不消耗彼此的宏调用。但我不知道如何以这种方式定义它们。

(我知道,MWE 版本\ChangeCase很无聊。我的真实 Lua 代码正在尝试更有趣的案例变化,但这个存根说明了核心问题:Lua 代码也被传递了宏名。)

我是第一次在 ConTeXt 中使用 Lua,对 ConTeXt 的内部结构不是很熟悉。也许我遗漏了某些明显的东西或者做错了。

我的退路是放弃分离这些宏,并为此用途定义一个临时的 \LastWordsChangeCase 宏。这有点恶心,但对这个项目有用。不过,我希望将来能够制作出强大的 Lua 宏,而这些宏却出乎意料地脆弱。我一定是做错了什么。

ConTeXt wiki 上有关 Lua 的文档很基础,似乎没有涵盖这一点。我不知道在 wiki 或邮件列表中尝试哪些搜索词可能会阐明这个问题。

我怎样才能让它按预期工作?

相关内容