Vim 经验与技巧
教程
准备工作
请先在你的 vimrc 里定义变量 $VIMFILES 。比如说 Windows 下,我把 vimfiles 放在了 Vim 安装目录的 vimfiles
目录下:
if has("win32") let $VIMFILES = $VIM.'/vimfiles' let $V = $VIM.'/_vimrc' else let $VIMFILES = $HOME.'/.vim' let $V = $HOME.'/.vimrc' endif
你知道吗?
Vim7.3 的持久撤销
Vim 7.3 提供 持久撤销 (Persistent Undo) 功能,即使文件关闭后,再次打开时仍然可以撤销文件关闭之前的编辑历史。要使用这一功能,在 vimrc 中添加
" 重启后撤销历史可用 persistent undo set undofile set undodir=$VIMFILES/\_undodir set undolevels=1000 "maximum number of changes that can be undone
set undofile - 开启本功能。开启之后会默认在文件当前目录下建立一个 filename.ext.un~ 的文件,自然是会给我们带来麻烦的。所以配置一个 undodir 集中放置所有undofile。
$VIMFILES/\_undodir - $VIMFILES 是我们之前在 vimrc 中定义的环境变量, windows 下是 $VIM/vimfiles/ 。请注意,为了和其他目录区分,undodir前面有下划线 _undodir 。因为有下划线,前面的反斜杠又不可少了。而且这个目录必须自己手动建立。如果不存在,Vim 是不会帮你自动建立的。
颤抖吧!IDE!
编辑状态的保存
大部分IDE都提供记录文件关闭前的状态的功能,个别考虑比较全面的还可以记住软件关闭前都打开了哪些文件。这些功能Vim都能做到。
记录文件状态(包括独立于该文件的键盘映射、代码折叠状态等):
autocmd BufWinLeave * if expand('%') != '' && &buftype == '' | mkview | endif autocmd BufRead * if expand('%') != '' && &buftype == '' | silent loadview | syntax on | endif
那些 if 判断是为了避免进入新建文件的缓冲区时,出现文件名不存在的错误。
如果参数为空,记录/载入 Vim 关闭时的状态。
一般来说,上面的代码就够用了。最大的缺陷可能就是时间长了 $VIMFILES/views 目录下就会有很多垃圾文件,有些文件你可能一辈子也不会打开了,但它们的状态文件仍然存在。你可以写一段删除过老文件的脚本,在 Linux 下就像这样:
function! RemoveOldViewFiles exe 'find '.$VIMFILES.'/view* -mtime +90 -exec rm {} \;' endfunction nmap <leader>.cl :call RemoveOldViewFiles<cr>
删除 90 天以前的文件。
至于类似于“恢复工作区”这样的功能,则可以通过session文件来实现:
编辑你的 vimrc :
" Session files Vim关闭时保存会话状态 set sessionoptions+=unix set sessionoptions-=blank "set sessionoptions-=options autocmd VimEnter * call LoadSession() autocmd VimLeave * call MakeSession() function! MakeSession() if !has('gui_running') hi clear endif if bufname('') == '' exe 'bdelete '.bufnr('') endif let l:count = 0 let l:i = 0 while l:i <= bufnr('$') if buflisted(count) let l:count += 1 endif let l:i+=1 endwhile if l:count >= 4 mksession! ~/.last_session.vim endif endfunction function! LoadSession() "if exists('g:SessionLoaded') "return "endif if expand('%') == '' && filereadable($HOME.'/.last_session.vim') && !&diff silent so ~/.last_session.vim endif let l:buftotal = bufnr('$') let l:i = 0 let l:crtpath = getcwd() while l:i <= l:buftotal " 列表中还未载入的buffer,如果不在当前工作目录,会被删除 if !bufloaded(l:i) && buflisted(l:i) && expand('%:p') !~ l:crtpath exe 'bdelete '.l:i echo expand('%:p') .' !~ '. l:crtpath endif let l:i += 1 endwhile endfunction
这段代码应该很好读懂,我就不解释了~ 有什么问题,请留言!
介绍 Vim 中的批量查找替换
1. vimgrep 命令
试用 :vimgrep word *
可以在当前目录的任意文件下查找“word”,并生成 quickfix 列表。试用 :cl
可以查看所有匹配结果。使用 :cn
到下一个, :cp
到上一个。
使用 :vimgrep /pattern/gj *.php
可以在当前目录的php文件中按搜索模式 pattern 查找。标志位 g 代表每次匹配都加入匹配结果列表,否则每行只匹配一次。标志位 j 表示只更新 quickfix 列表,否则 vim 会跳到第一个匹配上。
更多说明,请 :h vimgrep
或者 点这里。
2. arguments 参数列表 参数列表就是一系列文件列表。在上面链接的文章已有介绍,不细讲。
在 Vim 中启用 JSLint
明爷(gracecode.com)曾介绍过如何在Vim中使用JSLint,他写这篇文章时还没有诞生我今天要介绍的插件:jslint.vim。
事实证明,这个插件是很好用的。不过最初安装时要花点功夫。Linux下按照README的说明来,应该不会遇到什么问题,我这里讲一下在Windows下的注意事项。
1. 这个插件只能装在系统用户目录下($HOME
),即你在Vim里执行 :cd ~
所到的目录。(Win7下是 C:\Users\Username )
要突破上面的限制,修改 ftplugin/javascript/jslint.vim
第16行定义 install_dir 的部分:
if has("win32") let s:install_dir = '"' . expand($VIMFILES."/ftplugin/javascript") . '"' else
2. 对于带中文的JS文件,容易出现行定位错误的问题。原因和小明那篇文章里说的一样。我们同样在关键地方添加 iconv 转一下字符即可。
修改定义 b:jslint_output
的地方:
let b:jslint_output = system(s:cmd, iconv(join(s:jslintrc + getline(b:firstline, b:lastline), "\n") . "\n", &enc, "gbk"))
这么简单的问题,我折腾了两个小时。之前以为是换行符的问题。唉...
试试 Google Closure Linter
JSLint 默认的规则在有些情况下不太实用,比如说jQuery就会无视一些JSLint的错误。基于 Google 的编码风格,有一个 *Closure Linter*,我们可以试着把它集成到 Vim 中。
我修改了上面的 Vim 插件,有需要的可以点击这里下载。
gjslint 唯一的遗憾就是“字数过多”这个限制太严格了,对于我们宽屏用户来说,80个字符远远不够啊。暂时没有找到解决办法。
Vim Tips
插件与配置
- 在Vimwiki中,可以用 %title 自定义输出的 HTML 的 title ,但是最好写在文件最末尾,不然如果同时使用了 %toc (自动目录), 就会产生嵌套错误。这个bug将来可能会修正,但保持习惯是没错的。
-
把 _vimrc 和 vimfiles 拷到 msysgit 的安装目录下(
C:\Program Files\Git\share\vim
),可以让 Git Bash 里的 vim 也符合你平时的操作习惯。 - NERDTree Explorer 里带星号的文件代表这个文件是可执行文件
编辑
- 除了普通模式,可视模式,插入模式,你是否还知道有一个替换模式?正如在普通编辑器里按 Insert 键所切换入的那样,输入的文本会逐字替换光标下的字符。
-
要在 Vim 里跨行匹配,可以用
\_.
匹配包括换行符在内的任意字符。 -
使用
\{-}
实现类似常见 perl 正则里的?
之作用的懒惰匹配,尽量少的匹配前面的匹配元。 -
使用
:s
(替换)命令时,添加标志位 e 可以忽略找不到 pattern 的错误,这在函数或键盘映射命令中非常有用。如,下面的代码可以格式化CSS(虽然并不完美): map <leader>css :%s/;\s*\([a-z*_-}]\)/;\r\1/ge<cr>:%s/\(\w\)\s*{\([^\r]\)/\1\ {\r\2/ge<cr>:%s/:\(\w\)/:\ \1/ge<cr>:%s/}\(\w\\|#\\|\.\)/}\r\1/ge<cr>,=
你可能不知道的快速编辑快捷键:
gv
选中之前选中过的内容
g~{motion}
切换{motion}跨越的文本的大小写
g~~
切换当前行的大小写
gU{motion}
切换为大写
gu{motion}
切换为小写
不小心打开了一个需要 sudo 权限才能保存的文件,但是编辑了一大半才发现?下面的命令可以救急:
:w !sudo tee %
也可以做一个命令映射,安静地保存:
command W w !sudo tee % > /dev/null
使用 Vim Script
-
获取当前buffer的总行数的函数:
line("$")
-
静默执行shell:
:silent !cmd