Tcl变量更新后通过中键粘贴到Vi编辑器仍显示旧值的解决方法
解决Tcl选择区更新后Vi中粘贴旧值的问题
问题根源
你遇到的问题源于Tcl的列表值传递特性:当用[list selproc $myVar]注册选择区回调时,$myVar的当前值(Hello)会被直接嵌入到回调列表中,生成的实际回调是{selproc Hello}。后续更新myVar为AAA时,已注册的回调参数不会同步更新,所以Vi请求选择内容时,依然会调用selproc Hello ...,返回旧值。
解决方案
方案1:让回调直接访问全局变量
修改处理过程,使其每次调用时动态获取myVar的最新值,而非依赖注册时传入的固定参数:
# 重新定义selProc,直接读取全局变量myVar proc selProc {offset count} { global myVar return [string range $myVar $offset [expr {$offset + $count -1}]] } # 初始化变量并注册选择区回调 set myVar Hello # 明确指定PRIMARY选择区(X11中鼠标中键对应此选择区) selection handle -selection PRIMARY . selProc selection own . PRIMARY
更新变量时,只需修改myVar并重新声明选择区所有权(触发客户端重新获取内容):
set myVar AAA selection own . PRIMARY
方案2:使用匿名函数捕获变量(Tcl 8.5+)
如果不想依赖全局变量,可以用apply创建匿名函数,确保每次调用都能获取最新的myVar值:
set myVar Hello # 注册匿名回调,动态读取当前myVar的值 selection handle -selection PRIMARY . [apply {{offset count} { global myVar return [string range $myVar $offset [expr {$offset + $count -1}]] }}] selection own . PRIMARY
更新操作同样只需:
set myVar AAA selection own . PRIMARY
关键注意事项
- 明确指定
-selection PRIMARY:X11系统中,鼠标中键粘贴对应的是PRIMARY选择区,而非CLIPBOARD(后者通常对应Ctrl+C/V),避免选择区类型混淆。 selection own的作用:向X服务器声明当前窗口拥有该选择区,强制客户端(如Vi)重新请求选择内容,而非使用本地缓存的旧值。
内容的提问来源于stack exchange,提问作者Cha Cha
相关产品推荐
相关产品推荐

