info vars 命令在 proc 中无法正常工作

info vars command is not working properly inside a proc

我正在尝试使用 TCL 进行一些变量自动完成(这是为 jimtcl 设计的)

我已经在 tclsh 和 jimsh 中尝试了以下顺序:

% set VAR1 1
1
% set VAR2 2
2
% info vars  
.... tcl_pkgPath VAR1 tcl_patchLevel VAR2 argc ...
% set pattern $V*
$V*
% set vars_pattern [string range $pattern 1 end]
V*
% puts [lsort [info vars $vars_pattern]]
VAR1 VAR2
% 

这很好。

但是一旦我将其放入程序中

% proc autocomplete_helper pattern {
    # check for variables auto-completion
    puts "pattern '$pattern'"
    if {[regexp {$\S+$} $pattern match]} {
        set vars_pattern [string range $match 1 end]
        puts "pattern '$vars_pattern'"
        return [lsort [info vars $vars_pattern]]
    }

    puts "other stuff to do"
}
% autocomplete_helper zerazer
pattern 'zerazer'
other stuff to do
% autocomplete_helper $V*
pattern '$V*'
pattern 'V*
% 

你知道为什么这不起作用吗?

这是命名空间问题。

一个过程有它自己的命名空间。当您在 tclsh 提示符下 运行 info vars 时,这是全局 :: 命名空间。

在你的 proc 中做的最简单的事情是将 :: 添加到 info vars

的参数中

return [lsort [info vars ::$vars_pattern]]

return 值将包含 :: 命名空间前缀,因此如果需要请先删除它。

有趣的是,您在自动完成应用程序中看到了这个问题。我写了一个 Tcl 脚本来将我所有的过程、命令、命名空间等转储到 json 文件中,我将这些文件读入 Vim 以用于自定义自动完成插件。我在写那个的时候发现了同样的问题。

info vars 命令对其当前上下文很敏感(很明显;它 returns 当前可见的变量),将内容移动到过程中会改变这一点。 right 修复是在不同的上下文中使用 uplevel 到 运行 命令,或者在 uplevel 1 到 运行调用者的上下文或全局上下文中的 uplevel #0 到 运行(位于堆栈顶部的上下文)。

在这种情况下,我们需要小心一点,因为模式中可能包含元字符(很奇怪但合法)并且upleveleval-喜欢; list 命令将确保我们得到一个格式正确的命令。在明显的地方将此行放入您的程序中(其他一切不变)

# The double quotes around #0 are to fool the highlighter used on Stack Overflow
return [lsort [uplevel "#0" [list info vars $vars_pattern]]]

有了它,我可以做到:

% autocomplete_helper {$e*}
pattern '$e*'
pattern 'e*'
env errorCode errorInfo

这对我来说很合适。