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
到 运行(位于堆栈顶部的上下文)。
在这种情况下,我们需要小心一点,因为模式中可能包含元字符(很奇怪但合法)并且uplevel
是eval
-喜欢; 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
这对我来说很合适。
我正在尝试使用 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
到 运行(位于堆栈顶部的上下文)。
在这种情况下,我们需要小心一点,因为模式中可能包含元字符(很奇怪但合法)并且uplevel
是eval
-喜欢; 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
这对我来说很合适。