2
22
2011
3

Vim7.3 的 Python3 支持修正补丁

Vim 7.3 增加了对 Python3 的支持,但其有不少 bug,从不能正确地向缓冲区中添加中文文本,到 buffer 对象不支持 slice 操作,vim.error 不是 BaseException 的子类而是一个 str,以及各种中文乱码/UnicodeDecodeError,让我这个 Python3 的坚定支持者非常郁闷,于是趁假期把 Vim 好好修理了一番。

此次修正历时两周,涉及 src/if_{py_both.h,python.c,python3.c},共 3 files changed, 308 insertions(+), 265 deletions(-),修正的具体项目为

  • 向缓冲区添加文本时正确处理编码
  • buffer 对象支持 slice 赋值
  • vim.error 不再是字符串
  • py3file 让 Python 检测文件编码
  • 向 Python 传递缓冲区字符串时使用正确的编码(这解决了 gundo 在非 UTF-8 编码时的解码出错)
  • py3 命令输入使用 'encoding' 解码后再以 UTF-8 编码(这解决了在 'encoding' 非 UTF-8 时含中文的 py3 命令的 SyntaxError)
  • 向标准输出写文本时使用正确的编码(这样 print() 之类不会输出乱码)

以上数据要感谢git工具。

目前我在 Ubuntu Linux 10.10 32bit 和 Windows XP SP3 (使用 MinGW 编译)上测试没有问题,有兴趣的请帮忙再测试下。下载地址

另外,附上 gundo 的 Python 2 & 3 兼容版以及使用 Python3 支持的 Python 补全插件 python3complete.vim(放到 ~/.vim/autoload 下)。


PS:Python3.2 发布了,增加了一些很好的新特性,比如argparse模块,str.format_map方法等等。


2011年3月3日更新:给 Vim 编译 Python3.2 支持也有些艰难,参见这篇文章

2011年4月19日更新:今天解决了内存泄漏的问题,补丁已更新。另外,本补丁将在陈列室维护。

2011年6月19日更新:此补丁已被官方采纳。

Category: Vim | Tags: C代码 python vim
1
19
2011
3

Vim 的 Ruby 支持终于不 crash 了!

Vim7.3 的 Ruby 支持 bug 无限,刚开始是编译了 Perl 支持在调用 Ruby 时就 crash。我不编译 Perl 支持,不 crash 了,但是 lusty-explorer 还是得修改后才能用,因为$curbuf.number恒为零,后来才知道编译时加上--disable-largefile选项就可以没有这个问题

今天,101号补丁的发布终于解决了这些问题!

Category: Vim | Tags: vim
1
6
2011
14

编译了 Vim7.3.98 for Win32

vim_dev邮件列表看到Bram又发布了好些补丁,想起不久前看到梧桐在找支持Ruby的Vim二进制文件,所以我又编译了下Vim。上次编译Win版时Lua好不容易弄好了,Ruby却不能用。有些相关的补丁发出来了,这次也尝试下,欣喜地发现这个bug已经解决了~

对了,我尝试过使用Make_cyg.mak在Cygwin环境下编译,结果失败了,好像是gcc不支持这么编译了,所以还是用的MinGW。

文件放dbank网盘了,外链地址。因为有些涉及到文档什么的补丁,所以runtime文件也打包传了上去。另外说下,dbank虽然上传文件速度很快,但操作界面的时候,网速却极慢(用HttpFox看过了,不是JS导致的慢)。

注:支持的Python版本是2.7,Ruby是1.9.2,Lua还是静态编译的,5.2。


2011年3月29日更新:

把自己编译的 Windows 版 Vim 放这里了,会不时更新。

Category: Vim | Tags: vim windows
1
1
2011
47

让Vim在图形界面与终端中的Alt组合键相同

首先祝大家新年快乐!


一直都感觉Vim下快捷键不够用,于是在某一天,我开始使用Alt开头的组合键,然后发现了问题——

在很多终端中,Alt 组合键发送的是 Esc 前缀键码,而图形界面中则是置位最高位。举例来说,Alt-x在图形界面下向Vim发送的是ø(在Vim插入模式下使用Ctrl-V Alt-x可以看到),其编码为0xf1,而x的编码为0x78,区别在于前者二进制编码的最高位是 1,而后者是 0。

而在gnome-terminal、konsole中则是另外一番景象。Alt-x和快速地按Esc x的效果是一样的,仅有xterm 和 rxvt 等终端可选地支持像图形界面的那样处理(参见Vim手册:help :map-alt-keys)。而且,使用置位最高位的终端将导致shell中的Alt-f之类的键绑定失效。

Emacs能处理这种不一致,但Vim不能,于是我一直是使用脚本,使得在终端下和图形界面下使用不同的键绑定。这样图形界面下没什么问题,但终端下比较郁闷:因为映射了Esc开头的键,而Esc是用于回到普通模式的,于是每次按Esc想退回到普通模式时都得等一秒('timeoutlen的值)。这个值又不能设小,不然\ww这种需要多次按键的映射就难用了。

前些天,偶然在帮助文档里看到了这个:

					*:set-termcap* *E522*
需要 {option} 的地方,可以使用 "t_xx" 形式来设置终端选项。这些选项覆盖相应的
termcap 值。设置后,可以用于映射。如果 "xx" 包含特殊字符,须用 <t_xx> 形式: >
	:set <t_#4>=^[Ot
也可用来翻译普通键的特殊键码。例如,如果 Alt-b 产生 <esc>b,可用: >
	:set <m-b>=^[b
(这里 ^[ 是真正的 <esc>,用 CTRL-V <esc> 来输入)
这个方法优于映射之处在于它能适用于所有情况。

也就是说,可以在终端下把Alt组合键都设置到Esc开头的键码,这样一是不用每次设置键映射时设置两个,更重要的是,其本质变了:这样的设置不是键映射,而是指定键码!这样会使用'ttimeoutlen'的值来等待后续键码,和映射无关了,我完全可以把它设置得很小。于是写出新的脚本:

 1 " escalt.vim    控制台下让用 <M-x> 也可用
 2 " Author:       lilydjwg <lilydjwgATgmail.com>
 3 " Last Change:  2010年12月15日
 4 " ----------------------------------------------------------
 5 " Load Once:
 6 if &cp || exists("g:loaded_escalt") || has("gui_running")
 7   finish
 8 endif
 9 let s:keepcpo = &cpo
10 let g:loaded_escalt = 1
11 set cpo&vim
12 " ----------------------------------------------------------
13 " Functions:
14 function Escalt_console()
15   for i in range(65, 90) + range(97, 122)
16     exe "set <M-".nr2char(i).">=\<Esc>".nr2char(i)
17   endfor
18   set ttimeoutlen=50
19   if &term =~ 'xterm'
20     set <F1>=^[OP
21     set <F2>=^[OQ
22     set <F3>=^[OR
23     set <F4>=^[OS
24     set <Home>=^[OH
25     set <End>=^[OF
26   endif
27   for i in ["", "c", "i", "x"]
28     exe i . "map Ï1;2P <S-F1>"
29     exe i . "map Ï1;2Q <S-F2>"
30     exe i . "map Ï1;2R <S-F3>"
31     exe i . "map Ï1;2S <S-F4>"
32   endfor
33 endfunction
34 " ----------------------------------------------------------
35 " Call Functions:
36 call Escalt_console()
37 " ----------------------------------------------------------
38 "  Restoration And Modelines:
39 let &cpo= s:keepcpo
40 unlet s:keepcpo
41 " vim:fdm=expr:fde=getline(v\:lnum-1)=~'\\v"\\s*-{20,}'?'>1'\:1

注意到其中对于F1到F4等键进行了特殊的设置。没办法,这几个键特殊,这样设置我觉得是最优的解了。设置'ttybuiltin'也可以,但是经过一些时间的试用后发现有副作用,具体是什么我忘记了。


PS: SyntaxHighlighter 不支持 Vimscript,还好 Vim 有TOhtml命令。

最新脚本在 GitHub 有。直接复制上面高亮过的代码是不行的。

Category: Vim | Tags: linux vim
11
29
2010
0

snipMate表达式扩展补丁

snipMate 是Vim的片断扩展插件之一,介绍网上很多,实在不想Google的话可以看看这里,我就不多言了。

我经常会把一些网站链接连同其标题写到自己的wiki或者邮件中,于是有个这个snippet:

snippet link
	[`@*` `system('getTitle '''.@*.'''')`]${1}

扩展 * 寄存器(也就是X选择区)中的URL,并使用getTitle这个我自己用Python写的程序获取标题。这个snippet大多数情况下工作良好,只是偶尔会使Vim停止响应,只能Ctrl-C中止。今天在扩展 http://larrupingpig.zoka.cc/?p=197 这个URL时又遇到这个问题,实在受不了了,于是自己看源代码。`...`的扩展在这里:

	if stridx(snippet, '`') != -1
		while match(snippet, '`.\{-}`') != -1
			let snippet = substitute(snippet, '`.\{-}`',
						\ substitute(eval(matchstr(snippet, '`\zs.\{-}\ze`')),
						\ "\n\\%$", '', ''), '')
		endw
		let snippet = substitute(snippet, "\r", "\n", 'g')
	endif

问题就出在substitute中的substitute上。:help substitute()可以看到,其第三个参数中有些特殊字符,比如前边那个网页标题中的&,会被特殊对待。

知道问题出在哪儿了,也就有改的办法了,我在Google Code上报告了bug,并提交了补丁。但看看那么多的issue和Github上的Pull Request,我感觉被采纳的可能性好小啊。。。

Category: Vim | Tags: vim
11
26
2010
8

在Win编译带Lua支持的GVIM

虽然已经在Linux下待了这么长时间,可是,还是有很多时候,我不得不面对难用的Windows。而在Linux下一直自己编译Vim的我,今天在得知刘春棍的行动的支持下,终于鼓足了勇气,下载安装MinGW,编译了GVIM。

在Windows下编译GVIM和Linux下不同,不能用./configure来配置,要到src目录下,修改这下面的Make_ming.mak文件,改好后直接make -f Make_ming.mak编译。

Win下编译东西花的时间长就不说了。我编译了好几遍。Python支持没问题,设定好路径就OK,Ruby我是为编译GVIM专门装的,除了静态编译时会报错外,还有个很严重的问题,导致我最后放弃了+ruby。这个后面再说。Lua我下的是最新的5.2版,一个lua5_2_work2_Win32_bin.zip包含了exe和dll文件,另一个lua5_2_work2_Win32_mingw4_lib.zip包含了头文件和一个 .a 文件。我最开始以为和ruby一样只能动态载入,于是设置了DYNAMIC_LUA=yes,结果编译是成功了,但载入失败:

luaL_typerror无法加载

我用cg搜索了下,luaL_typerror被 #define 成了luaL_typeerror,这看来是5.2改的。我手动在if_lua.c里把这个给改了,结果发现,还有其它函数也是类似的情况,比如lua_call等。于是我尝试静态编进去试试,竟然成功了!

然而,喜悦总是短暂的。我以前只知道ruby支持有问题,没想到这次问题更严重了,:edit命令都用不了:

当然,一开始我还不能肯定是ruby支持的问题,但当编译了不带ruby支持的版本后,这个奇异的问题就没有了。

Vim7.3对其他语言的支持的问题真是多啊:Python3的中文支持有问题,ruby的支持也有问题,要支持Lua5.2还得自己改源代码。。。

不管怎么说,Lua静态编译进去了我还是很高兴的。虽然在没装Lua的机器上没那些Lua的库的,但至少在Vimscript外又多了一种可用的语言了。

最后,想下载我编译的 Windows 32 版 vim 的请到这里来。

Category: Vim | Tags: vim windows Lua
9
30
2010
12

colorpicker: 给 Vim 加一个调色板!

作为一名一直喜欢写网页前端的vimmer,自然会使用Vim来编写CSS了。但是,CSS中经常需要调色。虽然相继有一些工具的出现(见可视化的配置Vim(gVim)配色-colorsel.vim),但一直不太理想。编辑CSS的颜色,不仅需要细致的调色,而且需要方便修改,并且支持从屏幕取色是最好不过了!

既然没有现成的,而自己不管怎么说已经入了GTK的门,就自己写了一个简单的工具。本来有个叫gcolor2的调色/取色工具的,可惜它不支持把取到的颜色输出到标准输出,或者任何其它可被其它程序调用的地方(难道这只是某个大牛闲着没事做时写着玩儿的 :-P)。所以,colorpicker与之类似,只有一个标准的GTK调色板。重要的不同之处在于:它可以和其它程序交互。

还是先放个图吧:

就是这样。从图中可以看到,这个标准的调色板除了支持RGB值,还支持HSV,而后者非常适合对色彩进行微调,不像RGB那样只有机器能够理解。左下角有之前颜色和当前颜色的显示(截图时没注意,都是白色。。。)。之前颜色是可以从命令行设置的,这个很有用(请往下看)。也有取色器,在Linux下是可以取到屏幕上任何一点的颜色的。但根据我使用GIMP的经验,好像在Windows上只能取到本程序的颜色。另外还可以看到,图中显示了“透明度”一项。关注Web前端的童鞋都知道,CSS3支持半透明色彩了,所以,本程序也支持输出rgba(79, 0, 159, 0.51)这样的颜色值。

关于程序自身的介绍就到这儿。下面是在Vim里使用的截图:

我需要输入一个颜色值,于是按了我自己定义的Alt-C键,colorpicker启动了。因为是新颜色,加之之前我没使用过,所以“之前颜色”那里显示的是默认的白色。

颜色已经输入了,但我想换一个颜色,怎么办呢?在普通模式下按cac(change a color)就可以了,“之前颜色”会被置为待修改的颜色,方便进行微调。


PS: 在图中可以看到CSS中的颜色值下方背景被高亮成了相应的颜色。这是使用css.vim实现的。

PS2: 这里演示的是修改CSS文件,但实际上是和文件类型无关的。你可以将它用于任何你想用的文件中。

PS3: colorpicker是独立的GTK程序,所以不一定非要和Vim配合工作啦。Emacs什么的一样可以调用,只要有人写出调用代码。

PS4: 程序在哪里下载呢?请移步我的陈列室。Vim调用部分的代码尚未整理,在我的vimrc中,搜索colorpicker就可以了(共两个函数,截图中可以看到函数名。目前(2010年9月30日)它们处于我的vimrc的前50行内)。


2011年4月9日更新

这里 jiazhoulvke 提供了编译好的 Windows 版程序(以及分离出来的 Vim 配置),当然GTK Runtime 环境还是得装,而且还可能遭遇著名的DLL Hell(如果不幸地出现了,那么请把出问题的 DLL 文件从 GTK 的 bin 目录复制到 colorpicker.exe 所在的目录中)。

2014年11月8日更新:

颜色值的高亮显示可以使用 colorizer 插件了哦~

Category: Vim | Tags: gtk css vim C代码
9
28
2010
2

Vim73之ruby $curbuf.number恒为零问题终于解决了!

上回说到Vim7.3在种种优点背后隐藏着种种bug,今天,其中之一终于被解决了!

Command-T 的作者在 vim_use 上的bug报告贴无人回应之后若干天,又在 vim_dev 上发了贴,今天终于有人回应了,指出configure时加上--disable-largefile选项此bug就消失了。我于是迅速地重新编译了下,果然OK了!

Category: Vim | Tags: vim ruby
9
16
2010
9

Vim的hidden选项真是好东西!

我在编辑一些HTML文件。写得觉得差不多了,浏览器里看过还不满足,竟然想到去W3C验证一下。这一验证,差点出大事了!

因为需要使用程序来处理,所以这些HTML文档全部都是合格的XML文件,所以我给它们加上了<?xml version="1.0" encoding="UTF-8"?>。但W3C却告诉我HTML里不能写这个。好吧,我把它们都删掉:

sed -i '/<\?/d'  *.html

我想的是,凡是有<?的行全部删掉。命令执行完后忽然有点不好的感觉,于是ll一下,结果看到了一堆长度为0的HTML文件!我愣了一下,随即欲哭无泪!虽然这些文件在SVN里,但是自我这次开始编辑后我就没提交过!sed也是危险的命令啊!

我只想到火狐里还保留着改动最多的一个页面,赶紧先把它的源代码复制出来。直接“查看源代码”还不管用,因为本地文件是没有缓存的,查看时火狐会去磁盘上找文件。于是打开Firebug,在<html>元素上点右键,复制HTML,然后手工整理。剩下的文件没办法,只有SVN和Vim的*~备份文件了,555……

好吧,我认命。于是我在Vim里打开另一个文件,想趁着还记得改了些什么赶紧重做一遍,却意外地发现打开的文件显示着我sed之前的内容。来不及多想,我赶紧:w保存了,然后想了下,才恍然大悟——

我现在习惯于一直开着一个GVim实例,而又经常只是挂起或者休眠,几天才shutdown一次,所以经常会有100多个buffer。虽然我通常是把hidden选项关闭的,但有时候为方便切换buffer,会去se hidden一下,然后一直忘记再设置回来。这次,不记得什么时候设置了hidden选项,于是,那些被我关闭的buffer都还在内存里!终于知道了hidden在文件已保存的情况下有什么重要作用了!怀着对Vim的感激,我在buffer找到了所有被sed误删的文本,泪流满面~~


2011年3月17日更新:

现在才知道,sed 原来是支持备份的,只要告诉它备份文件的后缀就行了,像这样-i~

另外,Perl 也支持类似的操作,但用的是PCRE,功能强大许多我也熟悉许多。用法是

perl -pin -e 'print /regex/' #相当于 sed -i '/regex/d'
perl -pi -e 's/regex/replacement/g' #相当于 sed -i 's/regex/replacement/g'

 

Category: Vim | Tags: vim 失误 perl sed
9
3
2010
5

Vim7.3: 爱你不容易

Vim7.3b出来后我就急不可耐地体验了把,但因为它的ruby支持中$curbuf.number始终返回零,不仅影响到了Command-T插件,也严重影响了我非常喜欢+常用的LustyExplorer插件——时不时地SEGSEGV一下可不行。

等正式版终于出来后,我又立即下载编译了,结果问题依旧。无奈,我只好自己动手,把LustyExplorer中用到$curbuf.number的地方都换成VIM::evaluate('bufnr("%")')了,但之后还是在调用此插件时经常SEGSEGV,郁闷了,于是换回Vim7.2。

但是Vim7.3真的有些很好的特性啊。此前介绍过的就不重复了,下面说说后来发现的两个我很喜欢的特性。

strwidth()函数

strlen()大家都知道,但它求的是字符串的字节数,而不一定等于字符串的宽度,比如中文就是如此。这会造成无法将内容对齐。于是,用于对齐代码的Align插件在处理CJK字符时(设置let g:Align_xstrlen = 3时)使用了一种很耗时的办法来求字符宽度:将字符串显示在Vim里,然后看它占用了多少虚拟列。

有了Vim7.3的strwidth()等函数就不必这么麻烦了。我去改了相关代码,执行效率提升N倍。

setf补全

setf是设置文件类型的指令。这个我很常用,比如写php文件的HTML部分时为了正确地缩进HTML,我会把文件类型设置成HTML,写PHP部分时还要切回去。写新脚本时由于通常没有文件扩展名,所以Vim无法识别文件类型。这些情况我只好手动:setf xxx了。Vim7.3增加了对此的补全支持,可以少敲点字母了。


所以——

所以为了用上Vim7.3,同时又不放弃LustyExplorer插件,我前不久又开始折腾Vim7.3的源代码,最后连gdb都用上了,在段错误时得到以下backtrace结果:

#0  __memset_sse2 () at ../sysdeps/i386/i686/multiarch/memset-sse2.S:160
#1  0x00d1d6ac in Perl_sv_upgrade () from /usr/lib/libperl.so.5.10
#2  0x00d1ea6a in Perl_sv_magicext () from /usr/lib/libperl.so.5.10
#3  0x00d1fc11 in Perl_sv_magic () from /usr/lib/libperl.so.5.10
#4  0x00d21882 in Perl_sv_setiv () from /usr/lib/libperl.so.5.10
#5  0x08203691 in perl_buf_free (bp=0x847b890) at if_perl.xs:638
#6  0x080742e3 in free_buffer (buf=0x847b890) at buffer.c:613
#7  0x08073fec in close_buffer (win=0x0, buf=0x847b890, action=4)
    at buffer.c:468
#8  0x08074de8 in do_buffer (action=4, start=0, dir=1, count=0, forceit=1)
    at buffer.c:1136
#9  0x0807465e in do_bufdel (command=4, arg=0x84b8aa1 "", addr_count=0, 
    start_bnr=12, end_bnr=1, forceit=1) at buffer.c:834
#10 0x080cbb2c in ex_bunload (eap=0xbfff9f8c) at ex_docmd.c:4939
#11 0x080c817d in do_one_cmd (cmdlinep=0xbfffa140, sourcing=1, 
    cstack=0xbfffa148, fgetline=0, cookie=0x0) at ex_docmd.c:2656
#12 0x080c5a56 in do_cmdline (cmdline=0x837c2d0 "bwipeout!", getline=0, 
    cookie=0x0, flags=11) at ex_docmd.c:1122
#13 0x080c5110 in do_cmdline_cmd (cmd=0x837c2d0 "bwipeout!") at ex_docmd.c:728
#14 0x0820cf98 in vim_command (self=3084803600, str=3084486540) at if_ruby.c:731
#15 0x010619a3 in ?? () from /usr/lib/libruby1.8.so.1.8
---Type  to continue, or q  to quit---

接着我很快发现了问题——明明是个ruby写的插件,最上面怎么调用到Perl了呢?遂关闭+perl特性重新编译,几天已经过去了,Vim7.3依旧运行良好,没有再出现以下烦人的提示了:

Vim: 拦截到致命信号(deadly signal) SEGV
Vim: 结束。
zsh: segmentation fault  vim

现在我一直在关注 ftp://ftp.vim.org/pub/vim/patches/7.3/,期待着这个问题从根本上解决……

Category: Vim | Tags: vim ruby

| Theme: Aeros 2.0 by TheBuckmaker.com