在 Tcl Tk 中删除插入后自动完成具有现有值的条目

Autocomplete in entry with existing value after an insertion is deleted in Tcl Tk

我使用了 tcl tk wiki 中现有代码的帮助,在条目小部件中实现了自动完成功能。 http://wiki.tcl.tk/13267(相关部分引用如下):

proc autocomplete {win action validation value valuelist} {
   if {$action == 1 & $value != {} & [set pop [lsearch -inline $valuelist $value*]] != {}} {
     $win delete 0 end;  $win insert end $pop
     $win selection range [string length $value] end
     $win icursor [string length $value]
   } else {
     $win selection clear
   }
   after idle [list $win configure -validate $validation]
   return 1
 }

Applied to an entry like this:

entry .test -validate all -validatecommand {autocomplete %W %d %v %P $fruitlist}

所以现在如果我的数据列表中有这样的数据:

test of result
test again
rule and result

然后我输入“te”或“t”,我会在条目中自动获得“test again”建议。但是当我从 'te' 中删除 e 时,我没有得到任何更多的建议,就像我之前只输入 't' 时得到的建议,除非我输入另一个字母。

有什么方法可以让我删除某些字母后条目中保留的字母自动完成吗?

自动完成代码只在插入后做一些重要的事情,因为它检查回调中的 action 以查看它是否是 1,这表示插入。您需要扩展代码,以便它在操作为 0 时也执行某些操作,即在删除之后。不幸的是,当您尝试执行此操作时,最简单的扩展会出错,因为当您删除它刚刚插入的自动完成文本时,回调会立即为您恢复它!最基本的解决方法是检查实际删除的文本是否为一个字符长;如果不是,则可能是删除了一个选择,不应触发完成。

这是我的更新版本。它还修复了 Wiki 页面上指出的一个错误,该错误在单词列表中包含全局特殊字符。

proc autocomplete {win action validation delta value valuelist} {
    after idle [list $win configure -validate $validation]
    if {$value ne "" && ($action == 1 || ($action == 0 && [string length $delta] == 1))} {
        set pattern [string map {\ \\ \[ \\[ \] \\] * \* ? \?} $value]*
        set pop [lsearch -inline $valuelist $pattern]
        if {$pop ne {}} {
            $win delete 0 end
            $win insert end $pop
            $win selection range [string length $value] end
            $win icursor [string length $value]
            return 1
        }
    }
    $win selection clear
    return 1
}

添加了一个额外的参数 (delta) 以支持确定删除了多少文本,它需要绑定到验证回调脚本中的 %S 替换,例如,如下所示:

entry .test -validate all -validatecommand {autocomplete %W %d %v %S %P $fruitlist}

一个更正确的自动完成修复是维护一个状态模型来确定被删除的文本是通过自动完成插入的上一个操作,还是通过不同的用户操作完成的,因此允许禁用自动完成仅当删除的是自动完成的文本时才删除。但这真的复杂。