首页 > 解决方案 > info vars 命令在 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*
% 

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

标签: tcl

解决方案


info vars命令对其当前上下文(很明显;它返回当前可见的变量)敏感,并将事物移动到过程中会改变它。对此的正确解决方法是使用uplevel在不同的上下文中运行命令,或者uplevel 1在调用者的上下文uplevel #0中运行,或者在全局上下文(堆栈顶部的上下文)中运行。

在这种情况下,我们需要小心一点,因为模式中可能包含元字符(这很奇怪但合法)并且upleveleval-like; 该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

这对我来说是正确的。


推荐阅读