获取 LuaTeX 中未定义的控制序列的名称

获取 LuaTeX 中未定义的控制序列的名称

我想实现类似于\detokenizeLua 函数的功能。但有一种情况阻碍了我实现目标。

\directlua{tex.sprint("[" .. token.get_next().csname .. "]")}\par
\directlua{tex.sprint("[" .. token.get_next().csname .. "]")}\UNDEFINED

上面的第一行输出[par],其他行输出[]token.get_next().csname用替换token.scan_csname()没有帮助。如何在 LuaTeX 中获取未定义的控制序列的名称?

答案1

请注意,您不会得到空字符串,因为\UNDEFINED未定义,而是因为它从未被 TeX 扫描过(因此没有该名称的内部标记)

这个普通的 luatex

\long\def\z#1{%
\directlua{texio.write_nl("[" .. token.scan_csname() .. "]")}#1%
\directlua{texio.write_nl("[" .. token.get_next().csname .. "]")}#1%
}

\z\par
\z\UNDEFINED

\bye

生成日志

[par]
[par]
[UNDEFINED]
[UNDEFINED]

表明只要\UNDEFINED被 TeX 的#1参数扫描器看到就足以获得您期望的行为。

答案2

一种可能的方法是使用扩展/执行一些后续标记expand的功能scan_toks(),类似于这个答案

在下面的例子中,

  • 函数f执行简单操作token.get_next()(不处理以下标记不在哈希表中的情况)
  • 函数g用于scan_toks(false, true)扩展输入,并\immediateassignment结合\futurelet强制 TeX 对下一个标记进行标记。
  • 函数h用途协程技巧 (尽管不是使用协同程序,而是使用辅助函数)来调用\futurelet\immediateassignment如果它需要在仅扩展上下文中工作,则可以添加;然而在 o 扩展上下文中它仍然无法工作。
%! TEX program = lualatex
\documentclass{article}
\usepackage{luacode}

\ExplSyntaxOn
\use_none:n {\__unused}  % put the token \__unused into the hash table
\cs_new_protected:Npn \__h_aux { \directlua{h_aux()} }
\ExplSyntaxOff

\begin{luacode*}
print("\n\n\n\n")

function f()
    print("f: csname =", token.get_next().csname)
end

function g()
    token.put_next {
        token.create(string.byte "{", 1),
        token.create "immediateassignment",
        token.create "futurelet",
        token.create "__unused",
        token.create(string.byte "}", 2),
    }
    token.scan_toks(false, true)
    print("g: csname =", token.get_next().csname)
end

function h()
    tex.sprint {
        token.create "futurelet",
        token.create "__unused",
        token.create "__h_aux",
    }
end

function h_aux()
    print("h: csname =", token.get_next().csname)
end
\end{luacode*}


% normal behavior: tokens never seen before (not in the hash table) results in empty csname
\directlua{f()}\par
\directlua{f()}\undefined
\directlua{f()}\undefineda
\directlua{f()}\undefineda
\directlua{f()}\undefinedb

% use function g instead
\directlua{g()}\par
\directlua{g()}\undefined
\directlua{g()}\undefineda
\directlua{g()}\undefineda

% just checking, undefinedb is still not in the hash table
\directlua{f()}\undefinedb

% use function h instead
\directlua{h()}\par
\directlua{h()}\undefined
\directlua{h()}\undefinedb
\directlua{h()}\undefinedb

\begin{luacode*}
print("\n\n\n\n")
\end{luacode*}
\begin{document}
\end{document}

输出为

f: csname =     par
f: csname =     undefined
f: csname =
f: csname =
f: csname =
g: csname =     par
g: csname =     undefined
g: csname =     undefineda
g: csname =     undefineda
f: csname =
h: csname =     par
h: csname =     undefined
h: csname =     undefinedb
h: csname =     undefinedb

您可以看到该函数g()h()正确获取 csname,即\undefineda\undefinedb

相关内容