Jacky Liu
unread,Nov 11, 2009, 12:25:23 PM11/11/09Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to vim...@googlegroups.com
Alright。这是第一次用邮件方式发帖,因为要粘个附件。如果搞砸了不要见怪,请管理员删除就好了。
附件里的 Vim Script 代码可以帮你 debug 自己写的 Vim 脚本,也可以帮你 hack 别人写的脚本。里面一共有三个函数和两个自定义命令。把这段代码贴到你想研究的脚本最后,一起运行,然后你就可以使用这两个命令了。其中一个命令可以显示脚本内任意一个变量(函数内部变量除外)当前的值,不论变量的类型和内部结构如何。另一个命令让你可以调用脚本内的任意一个函数,然后把返回值以相似的格式显示出来。这两个命令是:
:DumpValue
:ExeFunCall
举例来说,如果你正在研究的脚本里有个变量:s:myVar,你想看它当前的值,就执行:
:DumpValue s:myVar
假设如果执行成功,消息会提示你变量的值已经转换为字串形式放入 "a 寄存器,你可以贴到一个文本文件里去查看。
如果脚本里有个函数 s:MyFun(argA, argB),你想用指定的参数来调用它来看看返回值如何,可以先定义临时变量来存放要传给它的参数:
:let g:toargA= 'xxx'
:let g:toargB= 'yyy'
,注意一定要是 g: 开头的全局变量才可以。这里假设两个参数都是 string 类型,其他类型也可以。然后执行:
:ExeFunCall s:MyFun(g:toargA,g:toargB)
注意 ExeFunCall 的参数中间不能有空格。如果执行成功,消息会提示你返回值已经转换为字串形式放入 "b 寄存器,同样可以贴到一个文本文件里去查看。
对于 number,float,string 类型也可以不用定义变量,直接传递:
:ExeFunCall s:MyFun(123,123.456)
:ExeFunCall s:MyFun(''string1'',''string2'') 或者:
:ExeFunCall s:MyFun(\"string1\",\"string2\")
对 string 类型需要加 quote,因为 string 会先以 Vim Script 的方式被解释一遍。
被 Dump 出来的值会以如下格式显示:
s:myVar : 123 (number)
s:myVar : 123.45 (float)
s:myVar : 'str_value' (string)
s:myVar --> function('name') (FuncRef)
s:myVar[3] (List)
[0] : 123
[1] : 123.45
[2] : 'str_value'
s:myVar{3} (Dict)
key_0 : 123
key_1 : 123.45
key_2 : 'str_value'
也就是说,对 number,float 类型直接显示,string 类型两边加上单引号,FuncRef 中间是 --> ,对 List 和 Dict 会以缩进的方式显示里面的每一项。当然,成员仍可以是 Dict 或 List,级数不限。
目前我正在用这段代码来 “黑” 一个比较流行的插件:NERD_tree.vim。这个插件写的很好(我认为),我执行下面的命令:
ExeFunCall s:Bookmark.New(''bm01'',''/usr/home/bluegene8210'')
新建了一个 Bookmark 类的对象,得到的返回值是:
returned{24}
AddBookmark --> function('2')
BookmarkExistsFor --> function('4')
BookmarkFor --> function('5')
BookmarkNames --> function('6')
Bookmarks --> function('3')
CacheBookmarks --> function('7')
ClearAll --> function('9')
GetNodeForName --> function('12')
InvalidBookmarks --> function('13')
New --> function('15')
Sort --> function('17')
ToRoot --> function('20')
Write --> function('22')
activate --> function('1')
compareTo --> function('8')
delete --> function('10')
getNode --> function('11')
mustExist --> function('14')
name : 'bm02'
path : '/usr/home/mememe'
setPath --> function('16')
str --> function('18')
toRoot --> function('19')
validate --> function('21')
可以看到,绝大部分都是成员函数,只有两个 string 类型的数据成员。
有趣的是,ExeFunCall 命令也可以用来调用这段代码自身的一个函数:s:StoreDataStructure(objName, objValue, objLevel)。这个函数的第一个参数是 string,表示变量名。第二个参数是个变量,类型不限。第三个参数是 number,表示变量的等级。这个函数是嵌套的,所以可以用来处理内部结构复杂的变量。执行下面的命令:
:let g:myVar=['x', 'y', 'z']
:ExeFunCall s:StoreDataStructure(''g:myVar'',g:myVar,0)
之后,得到的结果是:
returned[4]
[0] : 'g:myVar[3]'
[1] : ' [0] : 'x''
[2] : ' [1] : 'y''
[3] : ' [2] : 'z''
这段代码是为了 “黑” 别人的脚本而临时写的,很可能有缺陷。比如变量的值为空的时候,这些情况都没仔细考虑。写完后自己觉得思路比较有趣,就贴在这里。
还有,一次只能运行一个加了这段代码的脚本。别忘了最后把这段去掉。