linux中vim配置大全

vim是linux最常用的一种编辑器,但是需要配置其一些特性,更方便的为我们编程服务。

set nocompatible   "不要使用vi的键盘模式,而是vim自己的
set syntax=on   " 语法高亮
set noeb  or noerrorbells "关闭错误信息响铃

setconfirm    " 在处理未保存或只读文件的时候,弹出确认
setautoindent   自动缩进
set cindent
set tabstop=4 " Tab键的宽度
set softtabstop=4  " 统一缩进为4
set shiftwidth=4
set noexpandtab " 不要用空格代替制表符
set smarttab  " 在行和段开始处使用制表符
set number  " 显示行号
set history=1000 " 历史记录数
set nobackup   "禁止生成临时文件
set noswapfile
set ignorecase   "搜索忽略大小写
set hlsearch  "搜索逐字符高亮
set incsearch
set gdefault "行内替换
set enc=utf-8  "编码设置
set fencs=utf-8,ucs-bom,shift-jis,gb18030,gbk,gb2312,cp936
set langmenu=zh_CN.UTF-8  "语言设置
set helplang=cn
" 我的状态行显示的内容(包括文件类型和解码)
set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\[TYPE=%Y]\ [POS=%l,%v][%p%%]\ %{strftime("%d/%m/%y\ -\%H:%M")}
"set statusline=[%F]%y%r%m%*%=[Line:%l/%L,Column:%c][%p%%]
set laststatus=2" 总是显示状态行
setruler          " 在编辑过程中,在右下角显示光标位置的状态行
set cmdheight=2  " 命令行(在状态行下)的高度,默认为1,这里是2
filetype on   " 侦测文件类型
filetype plugin on   "载入文件类型插件
filetype indent on  " 为特定文件类型载入相关缩进文件
set viminfo+=!   " 保存全局变量
setiskeyword+=_,$,@,%,#,-   " 带有如下符号的单词不要被换行分割
set linespace=0   "字符间插入的像素行数目
set wildmenu   "增强模式中的命令行自动完成操作
set backspace=2   "使回格键(backspace)正常处理indent, eol, start等
setwhichwrap+=<,>,h,l    " 允许backspace和光标键跨越行边界
" 可以在buffer的任何地方使用鼠标(类似office中在工作区双击鼠标定位)

setautochdir              " 自动切换当前目录为当前文件所在的目录
setbackupcopy=yes         " 设置备份时的行为为覆盖
set ignorecasesmartcase    "搜索时忽略大小写,但在有一个或以上大写字母时仍大小写敏感
setnowrapscan             " 禁止在搜索到文件两端时重新搜索
setincsearch              " 输入搜索内容时就显示搜索结果
sethlsearch               " 搜索时高亮显示被找到的文本
set mouse=a
set selection=exclusive
set selectmode=mouse,key
set report=0   " 通过使用: commands命令,告诉我们文件的哪一行被改变过
setshortmess=atI   " 启动的时候不显示那个援助索马里儿童的提示
set fillchars=vert:\ ,stl:\,stlnc:\     " 在被分割的窗口间显示空白,便于阅读
setshowmatch    " 高亮显示匹配的括号
set nocursorline " 不突出显示当前行

set matchtime=5  " 匹配括号高亮的时间(单位是十分之一秒)
set scrolloff=3  " 光标移动到buffer的顶部和底部时保持3行距离
set smartindent   "为C程序提供自动缩进

setfoldenable             " 开始折叠
setfoldmethod=syntax      " 设置语法折叠
setfoldcolumn=0           " 设置折叠区域的宽度
setlocalfoldlevel=1       " 设置折叠层数为
" setfoldclose=all          " 设置为自动关闭折叠
" colorschemecolorzone      " 设定配色方案
colorschememolokai        " 设定配色方案
" 只在下列文件类型被侦测到的时候显示行号,普通文本文件不显示
if has("autocmd")
   autocmd FileTypexml,html,c,cs,java,perl,shell,bash,cpp,python,vim,php,ruby setnumber
   autocmd FileType xml,html vmap<C-o><ESC>'<i<!--<ESC>o<ESC>'>o-->
   autocmd FileType java,c,cpp,csvmap <C-o><ESC>'<o
   autocmd FileTypehtml,text,php,vim,c,java,xml,bash,shell,perl,python setlocaltextwidth=100
   autocmd Filetype html,xml,xslsource $VIMRUNTIME/plugin/closetag.vim
   autocmd BufReadPost *
     \ if line("'"") > 0&& line("'"") <=line("$") |
     \   exe "normal g`"" |
     \ endif
endif " has("autocmd")

" F5编译和运行C程序,F6编译和运行C++程序
" 请注意,下述代码在windows下使用会报错
" 需要去掉./这两个字符

" C的编译和运行
map <F5> :callCompileRunGcc()<CR>
func! CompileRunGcc()
exec "w"
exec "!gcc % -o %<"
exec "! ./%<"
endfunc

" C++的编译和运行
map <F6> :callCompileRunGpp()<CR>
func! CompileRunGpp()
exec "w"
exec "!g++ % -o %<"
exec "! ./%<"
endfunc

" 能够漂亮地显示.NFO文件
set encoding=utf-8
function! SetFileEncodings(encodings)
    letb:myfileencodingsbak=&fileencodings
    let&fileencodings=a:encodings
endfunction
function! RestoreFileEncodings()
    let&fileencodings=b:myfileencodingsbak
    unletb:myfileencodingsbak
endfunction

au BufReadPre *.nfo call SetFileEncodings('cp437')|setambiwidth=single
au BufReadPost *.nfo call RestoreFileEncodings()

" 高亮显示普通txt文件(需要txt.vim脚本)
au BufRead,BufNewFile *  setfiletype txt

" 用空格键来开关折叠
set foldenable
set foldmethod=manual
nnoremap <space>@=((foldclosed(line('.')) < 0) ? 'zc' :'zo')<CR>

" minibufexpl插件的一般设置
let g:miniBufExplMapWindowNavVim = 1
let g:miniBufExplMapWindowNavArrows = 1
let g:miniBufExplMapCTabSwitchBufs = 1
let g:miniBufExplModSelTarget = 1 

 

" 显示Tab符
set listchars=tab:\|\,trail:.,extends:>,precedes:<
set list


"设置代码折叠方式为 手工  indent
set foldmethod=indent
"设置代码块折叠后显示的行数
set foldexpr=1

if has("gui_running")
    setguioptions-=m " 隐藏菜单栏
    setguioptions-=T " 隐藏工具栏
    setguioptions-=L " 隐藏左侧滚动条
    setguioptions-=r " 隐藏右侧滚动条
    setguioptions-=b " 隐藏底部滚动条
    setshowtabline=0 " 隐藏Tab栏
endif

"编辑vim配置文件
if has('unix')
    setfileformats=unix,dos,mac
    nmap<Leader>e :tabnew$HOME/.vimrc<CR>
    let$VIMFILES = $HOME.'/.vim'
else
    setfileformats=dos,unix,mac
    nmap<Leader>e :tabnew$VIM/_vimrc<CR>
    let$VIMFILES = $VIM.'/vimfiles'
endif

" Alt-Space is System menu
if has("gui")
  noremap <M-Space>:simalt ~<CR>
  inoremap <M-Space><C-O>:simalt~<CR>
  cnoremap <M-Space><C-C>:simalt~<CR>
endif

" 设定doc文档目录
let helptags=$VIMFILES.'/doc'
set helplang=cn
"set nobomb

" {{{ 编码字体设置
set termencoding=chinese
set fileencodings=ucs-bom,utf-8,default,chinese,big5
set ambiwidth=double
set guifont=YaHei\ Consolas\ Hybrid:h12
" }}}

" {{{全文搜索选中的文字
:vmap <silent><leader>fy/<C-R>=escape(@",'\\/.*$^~[]')<CR><CR>
:vmap <silent><leader>Fy?<C-R>=escape(@",'\\/.*$^~[]')<CR><CR>
" }}}

" 删除所有行未尾空格
nmap <F12> :%s/[\t\r]\+$//g<CR>

" Buffers操作快捷方式!
nmap <S-L>:bnext<CR>
nmap <S-H>:bprevious<CR>

" Tab操作快捷方式!
nmap <S-J>:tabnext<CR>
nmap <S-K>:tabprev<CR>

" 插入模式下左右移动光标
imap <c-l><esc>la
imap <c-h><esc>ha

"窗口分割时,进行切换的按键热键需要连接两次,比如从下方窗口移动
"光标到上方窗口,需要<c-w><c-w>k,非常麻烦,现在重映射为<c-k>,切换的
"时候会变得非常方便.
nmap <C-h><C-w>h
nmap <C-j><C-w>j
nmap <C-k><C-w>k
nmap <C-l><C-w>l

" 选中状态下 Ctrl+c 复制
vmap <C-c> "+y

" win下的全屏组件,需gvimfullscreen.dll的支持
if !has('unix')
    function!ToggleFullScreen()
       let s:IsFullScreen=libcallnr("gvimfullscreen.dll","ToggleFullScreen", 27 + 29*256 + 30*256*256)
   endfunction
    map<F11><Esc>:callToggleFullScreen()<CR>
endif

"一些不错的映射转换语法(如果在一个文件中混合了不同语言时有用)
nmap <leader>1 :setfiletype=xhtml<CR>
nmap <leader>2 :setfiletype=css<CR>
nmap <leader>3 :setfiletype=javascript<CR>
nmap <leader>4 :setfiletype=php<CR>

" Python 文件的一般设置,比如不要 tab 等
"autocmd FileType python set tabstop=4 shiftwidth=4 expandtab

" 设置字典 ~/.vim/dict/文件的路径
autocmd filetype javascript setdictionary=$VIMFILES/dict/javascript.dict
autocmd filetype css set dictionary=$VIMFILES/dict/css.dict
autocmd filetype php set dictionary=$VIMFILES/dict/php.dict


" {{{ plugin - vimExplorer.vim 文件管理器
" :VE打开文件管理器      tab: 在树、列表窗口切换 
" Enter:树窗口开关目录    u:列表中在预览窗口打开文件
" ;r 打开Renamer插件
let g:VEConf_systemEncoding='cp936'
"}}}


" {{{ plugin - renamer.vim 文件重命名
" :Renamer 将当前文件所在文件夹下的内容显示在一个新窗口
" :Ren 开始重命名
"}}}


" {{{ plugin - bufexplorer.vim Buffers切换
" \be 全屏方式查看全部打开的文件列表
" \bv 左右方式查看   \bs 上下方式查看
"}}}


" {{{ plugin - bookmarking.vim 设置标记(标签)
" <F9>设置标记   <F4>向下跳转标记  <S-F4> 向上跳转标记
"map<F3>  :ToggleBookmark<CR>
"map<F4>  :NextBookmark<CR>
"map <S-F4>:PreviousBookmark<CR>
"}}}


" {{{ plugin - matchit.vim 对%命令进行扩展使得能在嵌套标签和语句之间跳转
" %正向匹配     g% 反向匹配
" [%定位块首    ]% 定位块尾
"}}}


" {{{ plugin - mark.vim 给各种tags标记不同的颜色,便于观看调式的插件。
"这样,当我输入“,hl”时,就会把光标下的单词高亮,在此单词上按“,hh”会清除该单词的高亮。如果在高亮单词外输入“,hh”,会清除所有的高亮。
"你也可以使用virsual模式选中一段文本,然后按“,hl”,会高亮你所选中的文本;或者你可以用“,hr”来输入一个正则表达式,这会高亮所有符合这个正则表达式的文本。
nmap <silent><leader>hl<Plug>MarkSet
nmap <silent><leader>hh<Plug>MarkClear
nmap <silent><leader>hr<Plug>MarkRegex
vmap <silent><leader>hl<Plug>MarkSet
vmap <silent><leader>hh<Plug>MarkClear
vmap <silent><leader>hr<Plug>MarkRegex
"你可以在高亮文本上使用“,#”或“,*”来上下搜索高亮文本。在使用了“,#”或“,*”后,就可以直接输入“#”或“*”来继续查找该高亮文本,直到你又用“#”或“*”查找了其它文本。
" <silent>*当前MarkWord的下一个    <silent># 当前MarkWord的上一个
" <silent>/所有MarkWords的下一个   <silent>? 所有MarkWords的上一个
"}}}


" {{{ plugin – winmove.vim 窗口移动
let g:wm_move_left  ="<A-h>"
let g:wm_move_right = "<A-l>"
letg:wm_move_up   = "<A-k>"
let g:wm_move_down  ="<A-j>"
"}}}


" {{{ plugin – ZenCoding.vim 很酷的插件,HTML代码生成
" 插件最新版:http://github.com/mattn/zencoding-vim
" 常用命令可看:http://nootn.com/blog/Tool/23/
" }}}


" {{{ plugin - auto_mkdir.vim 自动创建目录
" }}}


" {{{ plugin - mru.vim 记录最近打开的文件
let MRU_File = $VIMFILES.'/_vim_mru_files'
let MRU_Max_Entries = 1000
let MRU_Add_Menu = 0
nmap <leader>f:MRU<CR>
" }}}


" {{{ plugin - surround.vim 快速替换、清除包围符号、标签
"  Oldtext                 Command    New text ~
"  "Hello*world!"          ds"        Hello world!
" [123+4*56]/2             cs])       (123+456)/2
"  "Look ma, I'm*HTML!"    cs"<q>     <q>Look ma, I'mHTML!</q>
"  if *x>3{                ysW(       if ( x>3 ) {
"  my $str =*whee!;        vlllls'    my $str = 'whee!';
"  "Hello*world!"          ds"        Hello world!
" (123+4*56)/2             ds)        123+456/2
" <div>Yo!*</div>          dst        Yo!
"  Hellow*orld!            ysiw)      Hello (world)!
" }}}


" {{{ plugin - NERD_commenter.vim 注释代码用的,
" <leader>ca 在可选的注释方式之间切换,比如C/C++的块注释和行注释//
" <leader>cc 注释当前行
" <leader>cs 以”性感”的方式注释
" <leader>cA在当前行尾添加注释符,并进入Insert模式
" <leader>cu 取消注释
" <leader>cm 添加块注释
" }}}


" {{{ plugin - jsbeautify.vim 优化js代码,并不是简单的缩进,而是整个优化
" 开始优化整个文件
nmap <silent><leader>js :callg:Jsbeautify()<cr>
" }}}


" {{{ plugin -yankring.vim 寄存器可视操作
map <leader>y:YRShow<CR>
"map <leader>yc:YRClear<CR>
" }}}


set diffexpr=MyDiff()
function! MyDiff()
  let opt = '-a --binary '
  if &diffopt =~ 'icase' | let opt= opt . '-i ' | endif
  if &diffopt =~ 'iwhite' | letopt = opt . '-b ' | endif
  let arg1 = v:fname_in
  if arg1 =~ ' ' | let arg1 = '"' . arg1 . '"' |endif
  let arg2 = v:fname_new
  if arg2 =~ ' ' | let arg2 = '"' . arg2 . '"' |endif
  let arg3 = v:fname_out
  if arg3 =~ ' ' | let arg3 = '"' . arg3 . '"' |endif
  let eq = ''
  if $VIMRUNTIME =~ ' '
    if&sh =~ '\<cmd'
     let cmd = '""' . $VIMRUNTIME . '\diff"'
     let eq = '"'
    else
     let cmd = substitute($VIMRUNTIME, ' ', '" ', '') . '\diff"'
    endif
  else
    let cmd =$VIMRUNTIME . '\diff'
  endif
  silent execute '!' . cmd . ' ' . opt . arg1 . '' . arg2 . ' > ' . arg3 . eq
endfunction

 

"分割窗口时保持相等的宽/高
set equalalways
 
 "匹配括号的规则,增加针对html的<>
set matchpairs=(:),{:},[:],<:>
"让退格,空格,上下箭头遇到行首行尾时自动移到下一行(包括insert模式)
set whichwrap=b,s,<,>,[,]
"取消自动备份
set nobackup
"保存关闭文件之前保留一个备份
set writebackup
 
"js语法高亮脚本的设置
let g:javascript_enable_domhtmlcss=1
 
"设置自定义的<leader>快捷键
let mapleader=","
let g:mapleader=","
 
""""""""""""""""""""""""""""""
" bufExplorer插件的设置
""""""""""""""""""""""""""""""
let g:bufExplorerSortBy='mru'
letg:bufExplorerSplitRight=0    
letg:bufExplorerSplitVertical=1   .
let g:bufExplorerSplitVertSize = 30
let g:bufExplorerUseCurrentWindow=1
autocmd BufWinEnter
Buf List

setl nonumber
 
""""""""""""""""""""""""""""""
" winManager插件的设置
""""""""""""""""""""""""""""""
let g:winManagerWindowLayout ="BufExplorer,FileExplorer|TagList"
let g:winManagerWidth = 30
let g:defaultExplorer = 0
nmap <silent><leader>wm:WMToggle<cr>
 
""""""""""""""""""""""""""""""
" netrw插件的快捷键
""""""""""""""""""""""""""""""
let g:netrw_winsize = 30
nmap <silent><leader>fe:Sexplore!<cr>
 
""""""""""""""""""""""""""""""
" NERDTree插件的快捷键
""""""""""""""""""""""""""""""
nmap <silent><leader>nt:NERDTree<cr>
 
 
"把常用的ctrl快捷键映射到苹果键上(只保留cmd+c/cmd+v/cmd+z原有的功能)
map <D-y><C-y>
map <D-e><C-e>
map <D-f><C-f>
map <D-b><C-b>
map <D-u><C-u>
map <D-d><C-d>
map <D-w><C-w>
map <D-r><C-r>
map <D-o><C-o>
map <D-i><C-i>
map <D-g><C-g>
map <D-p><C-p>
map <D-n><C-n>
map <D-a><C-a>
cmap <D-d><C-d>
2009.6.7更新:最新的vimrc和其他脚本已经上传到google code的项目仓库里了


=================步骤二的分割线===================


然后在个人配置目录里添加语法高亮脚本(~/.vim/syntax/),其中html和css可以直接把vim7自带的脚本复制出来($VIMRUNTIME/syntax/),js的脚本则推荐用这个:

JavaScript syntax : Better JavaScrirpt syntax support

包含更多的关键字以及自动折叠代码的功能,也能在html文件内支持js语法高亮,需要注意的是如果要支持dom方法的关键字,需要在.vimrc里设置一个全局变量javascript_enable_domhtmlcss

我还用了这里的html.vim。


=================步骤三的分割线===================


接下来就可以对照着syntax脚本,给每个语法组设置颜色,配色脚本需要放到~/.vim/colors/里,然后在.vimrc里用colorscheme命令选定。colors脚本只需要一个,因为syntax脚本末尾都会把自定义的语法组链接到标准语法组,比如:

HiLink javaScriptDocComment  Comment
所以只需要定义一套针对标准语法组的配色方案,再通过修改syntax脚本里来调整相应语言的配色。我尝试过针对不同文件类型使用不同的配色方案,发现相当麻烦,需要在切换/打开/关闭缓冲区和窗口的时候都用colorscheme重置配色:

autocmd BufNewFile,BufRead,BufEnter,WinEnter,FileType*.html,*.htm colorscheme delek
而且colorscheme会影响整个窗口(一个vim进程实例),如果在窗口内同时分割显示了几个文件,即使文件类型不同,也会同时改变颜色……

我平时最喜欢TextMate的Blackboard主题(大概是因为里面有橙色罢XD),在Aptana上也仿制过(配置文件:yytextmate.col),这次是直接在vim的slate主题基础上修改出来的,比vim.org上面那个blackboard.vim要更完善~

我的colors脚本:yytextmate.vim
我调整过的syntax脚本:javascript.vim, html.vim


=================步骤四的分割线===================


按照由外向内的顺序,现在该折腾功能了,首先是缩进插件,vim也自带有智能缩进功能,需要开启autoindent和smartindent参数,但是在编辑js代码的时候效果很不好,对于python这种靠缩进活命的语言就更不能忍了,因此至少需要装以下三个插件:

IndentAnything : Write indentations or enhance existingindentations without writing code
Javascript Indentation : Indentation for Javascript
indent/python.vim : An alternative indentation script forpython

第一个放到~/.vim/plugin/里,后两个放在~/.vim/indent/里


=================步骤五的分割线===================


接下来终于要来实现TextMate最重要的功能了,TextMate之所以被称作地上最贵麦上最强的编辑器,就是因为支持大量可以通过tab或其他快捷键发动的强力Bundles,这些Bundles可以分为两种类型,一种是针对编辑器的内容执行指令(称作command),比如直接执行shell脚本,压缩js代码,对html转义,格式化JSON,编译swf等等,而指令界面是vim的核心,不但可以直接执行shell命令,也可以通过设置键位映射和宏,把复杂的操作绑定成简单的快捷键,因此这类功能原本就是vim的强项。

另一种类型的Bundles主要用来帮助程序员快速开发,通过简短的缩写+tab键直接生成所需的代码模板(称作snippet),然后依然用tab在模板中需要改动的位置之间跳转,整个过程不需要鼠标定位,非常高效,是一种比大型IDE里常见的”codehinting”更实用的智能补全功能。

snipMate : TextMate-style snippets for Vim

上面这个非常“新”的插件让vim也具备了同样的功能,而且几乎是跟TextMate完全兼容的移植,比如这是从TextMate里取出的snippet源码:

${1:class_name}.prototype.${2:method_name} =function(${3:first_argument}) {
    ${0://body...}
};
${}标签是代码插入后可以通过tab跳转的“可编辑”位置,其中的序号表示跳转顺序,冒号后的字符是默认内容。这段代码只要在前面加上snippetproto就可以直接放进~/.vim/snippets/javascript.snippets里,通过proto触发

把常见的程序结构抽象成snippet可以节省很多重复输入,比如这是我定义的一个module模式:

snippet module
   
    var${1:classname} = (function(){
       var $1Object = {
           ${2:privateMethod1}: function(){
              
           },
           ${3:privateMethod2}: function(){
              
           }
       };
       return function(opt){
           var publicObj = {
               options: {},
               $2: $1Object.$2,
               $3: $1Object.$3${4:,}
           };
           $.extend(publicObj.options, opt);
           return publicObj;
       };
    })();
修改过程中会看到$1,$2,$3自动更新成你键入的名字。

我修改过的完整javascript.snippets:http://code.google.com/p/yy-vimscript/source/browse/trunk/snippets/javascript.snippets

实际上还有一个比较老牌的插件也致力于实现同样的snippet功能:

snippetsEmu : An attempt to emulate TextMate’s snippetexpansion

但是它支持的模板语法比TextMate差很多,跟上面相同的prototype模板要通过这种形式定义:

let st = g:snip_start_tag
let et = g:snip_end_tag
let cd = g:snip_elem_delim
 
exec "Snippet proto".st."className".et.".prototype.".st."methodName".et." =function(".st.et.")<CR>{<CR>".st.et."<CR>};<CR>".st.et
缩进容易出错,不支持用序号设定跳转顺序,安装过程也比snipMate繁复,所以被我毫不留恋的淘汰了……

为了实现更广泛的智能补全,还需要一个必装插件:

SuperTab continued. : Do all your insert-mode completion withTab.

SuperTab让任意字符都可以通过tab补全,比较取巧的是,它会在缓冲区的上下文中寻找匹配的词来补全,因此不需要附带很庞大的API数据。


=================步骤六的分割线===================


下一步需要增强的是文件/项目管理,vim虽然自带一个FileExplorer(直接编辑一个目录时会调用它,比如:e.),还有上面提到过的wildmenu的强力辅助,但是与常见的GUI编辑器和IDE相比,仍然不太直观,因此以下插件值得一装:

The NERD tree : A tree explorer plugin for navigating thefilesystem
我最喜欢的文件导航工具,设置了快捷键,nt直接在侧面打开

bufexplorer : Buffer Explorer / Browser
缓冲区导航

winmanager : A windows style IDE for Vim 6.0
把bufexploer和FileExplorer集成在左侧,类似IDE的效果,这个功能不足以让我放弃NERDTree……而且这个插件似乎很久没更新了,连支持Vim7的版本都没有,但是很多人喜欢,所以也推荐一下……

TaskList.vim : Eclipse like task list
实现Eclipse的任务列表

project.tar.gz : Organize/Navigate projects of files
项目导航工具,不过没有Eclipse好用,需要写配置脚本,跟TextMate那种拖来拖去的drawer就更不能比了……


=================步骤七的分割线===================


最后推荐的插件都是开发工具:

vcscommand.vim : CVS/SVN/SVK/git integration plugin
SVN/git管理工具,这个是必备罢。没有GUI菜单,不过快捷键也很方便,而且VimDiff是很棒的比较工具

javaScriptLint.vim : Displays JavaScript Lint warnings in thequickfix error window
看仔细啦~这个不是道格拉斯老爷子的JSLint,那个东西虽然强大(以前没觉得,最近在《代码之美》里看到道格拉斯老爷子描述了“递归下降分析”+“运算符优先级技术”的动态语言解释器,才知道原来JSLint和JSONparser只是老爷子晒技术的承载体……),但是由于把规范约束在一个JS的安全子集上,适用面不广,设置起来也麻烦,在实际开发工作中未必实用。而这个Lint就很中规中矩,当然也没自己折腾解释器啦,直接用了Mozilla的js引擎,安装也很方便,提供一个conf文件可以设置警告条件。这个vim插件装上后,保存js文件时都会自动校验代码并显示一个提示信息窗口。

matchit : extended % matching for HTML, LaTeX, and many otherlanguages
vim里的%命令可以在嵌套字符之间跳转(比如括号和引号,我在上面的.vimrc文件里增加了html的<>),这个插件将它的功能扩展到嵌套标签和语句

首先要补充一些MacVim的配置,其实写上篇文章的时候我还在用已经过时的基于Carbon界面的vim forosx,更接近传统的unix版本,但是好久没更新,只支持vim6.0,soureforge上有一个7.2的版本,bug诸多,其中的乱码和字体抗锯齿的问题让我完全无法忍。而MacVim是基于Cocoa开发,支持到7.2,还含有很多讨好mac用户的设计,比如对标签的良好支持,华丽的界面(背景颜色支持透明度,字体抗锯齿更漂亮,几乎跟TextMate的效果没区别)……非常后悔以前没仔细试用这个版本!目前为止只发现行高linespace的设置会无法生效,不过这个bug在最新的快照版里已经修正了。

插播一个道歉:由于spam太多,我前段时间在wordpress黑名单里加了一个很苛刻的条件,把所有评论都挡到待审核列表里去了,好像还直接删了一部分……咳……

我在.vimrc里增加了一些专门针对MacVim的设置:

if has("gui_macvim")
  "取消默认的快捷键
  let macvim_skip_cmd_opt_movement = 1
  let macvim_hig_shift_movement = 1
 
  "设置背景透明度
  set transparency=2
  "隐藏工具条
  set guioptions-=T "egmrt
 
  "绑定自己需要的cmd快捷键
  macmFile.Save                             key=<D-s>
  macm File.Save\As\.\.\.                   key=<D-S>
  macmEdit.Undo                             key=<D-z> action=undo:
  macmEdit.Redo                             key=<D-Z> action=redo:
  macmEdit.Cut                              key=<D-x> action=cut:
  macmEdit.Copy                             key=<D-c> action=copy:
  macmEdit.Paste                            key=<D-v> action=paste:
  macm Edit.Select\All                      key=<D-A> action=selectAll:
endif
之所以要取消MacVim默认的一些快捷键是因为它们都占用了cmd苹果键,而我习惯用这个键来替代ctrl在vim里的作用(在mbp的键盘上就算我想用ctrl也不方便……),不过其中有几个快捷键是非常非常有价值的,比如保存(省去了输入:w的麻烦),全选(否则要摁六下:ggVG),复制粘贴剪切(否则为了使用剪贴板,比如猛摁这种玩意:”+y,还不能在插入模式下使用),幸好它们的快捷键都不跟vim其他操作冲突,所以自己设置。为了完全删除MacVim默认的cmd快捷键,还需要打开app中自带的vimrc文件(可以这样编辑::tabe$VIM/vimrc ),删除末尾那些macm开头的代码。


MacVim的安装包里包含一个mvim,是像gvim一样的脚本,用来在命令行中调用GUI版的vim,但是mvim默认会在新窗口打开文件,我相信多数人都喜欢在当前窗口的新标签页里打开罢,需要在命令后加–remote-tab参数,不过这篇文章里给出了直接修改脚本的方法,把mvim底部从#Last step: fire up vim开始的部分删掉,改成:

tabs=true
 
# Last step:  fire up vim.
if [ "$gui" ]; then
if $tabs && [[ `$binary--serverlist` = "VIM" ]]; then
    exec"$binary" -g $opts --remote-tab-silent ${1:+"$@"}
else
exec "$binary" -g $opts ${1:+"$@"}
fi
else
exec "$binary" $opts ${1:+"$@"}
fi
P.S. 上面给出的那个blog不能直接打开,也许是需要翻墙,不过我顺便介绍一个很方便的利用google网页快照的方法~用谷歌翻译打开这个网址 XD


刚安装好的MacVim打开gb编码的文件仍然把中文显示成乱码(好无奈,GBK编码是土豆网的历史遗留问题,页面里的script标签也几乎都没加charset=”utf-8″,所以大部分js文件都只好用gb18030的编码,textmate正是因为不支持gb编码才被我降为二等公民的,其实我有正版cdkey……),我在.vimrc里加上了encoding似乎能解决这个问题:

set encoding=utf-8
set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936
解释一下:对于编码,vim里有三个设置选项,encoding是设置vim以何种编码显示文件(缩写enc),fileencoding是当前文件实际的编码(缩写fenc),而fileencodings指示vim如何解码(缩写fencs),因此vim在打开一个文件时实际上会先根据fileencodings里的列表反复测试,直到成功解码,转换成encoding指定的编码,然后正常显示,转码的过程是用iconv实现的(所以windows上用vim还要配置iconv的dll路径和参数……麻烦),保存的时候会根据fileencoding来保存,跟是否显示为乱码没有关系。

所以如果想转换一个文件的编码,比如从utf-8转换到gb18030,可以在编辑器中直接输入两个命令:

:set enc=gb18030
:set fenc=gb18030
然后保存就ok了~其实如果不用继续编辑的话,第一行都可以省去,因为它的目的只是让编辑器用gb18030来显示当前文件,避免乱码,但是并不影响文件保存时的编码和正确性。

以前我都是依赖mac上的Coda来转换编码(确实最方便)……vim又成功了抢了它的饭碗……


MacVim还有一个问题是会显示一个很宅很不人性的标签栏名称,比如我编辑/usr/local/bin/mvim这个文件,标签栏上写的是“/u/l/b/mvim”,如果目录结构再深一点就看不到真正的文件名了,在.vimrc里加入下面这行可以让标签栏只显示文件名:

set guitablabel=%t


上次的.vimrc里还增加了两处很重要的设置,主要是受这位老爷写的《vim使用进阶》的启发,首先是让.vimrc每次编辑保存后自动生效,避免重启:

autocmd! bufwritepost .vimrc source ~/.vimrc
autocmd实际上是vim脚本的事件机制,表示在某个事件触发后自动执行的命令


接下来要实现的是保存和恢复编辑器的当前状态,类似Eclipse的Workspace,不过vim的session更强大,几乎可以还原一切状态……Easwy老爷介绍的命令比较繁琐,缺乏“一键恢复”的***……身为一个习惯使用“高级语言”的程序员,在这种时候就抑制不住继续封装和提高抽象层的欲望……所以自定义了以下两个命令:

function! GetMySession(spath, ssname)
if a:ssname == 0
let a:sname = ""
else
let a:sname = "-".a:ssname
endif
execute "source $".a:spath."/session".a:sname.".vim"
execute "rviminfo $".a:spath."/session".a:sname.".viminfo"
execute "echo "Load Success\:$".a:spath."/session".a:sname.".vim""
endfunction
 
function! SetMySession(spath, ssname)
if a:ssname == 0
let a:sname = ""
else
let a:sname = "-".a:ssname
endif
execute "cd $".a:spath
execute "mksession! $".a:spath."/session".a:sname.".vim"
execute "wviminfo! $".a:spath."/session".a:sname.".viminfo"
execute "echo "Save Success\:$".a:spath."/session".a:sname.".vim""
endfunction
 
" load session from certain path
command! -nargs=+ LOAD callGetMySession(<f-args>)
 
" load session from certain path
command! -nargs=+ SAVE callSetMySession(<f-args>)
为了用最简单的方法选择路径,使用时需要先在终端的初始化脚本(比如~/.bashrc,在我的OSX系统里通常用~/.profile)里添加相应的环境变量,比如我常用的三个路径:

export TUISVN="/Users/dexteryy/Sites/Tudou/ui/ui/"
export TUIDEV="/Volumes/ui.tudou.com/"
export MYWEB="/Users/dexteryy/Sites/www/"
当我在MYWEB的路径下做项目的时候,如果需要保存当前状态,只要输入:SAVE MYWEB0就行了,这里的0是因为考虑到在同一个工作目录里可能需要使用到不同文件组合的工作区,提供的一个简单的版本号,这段命令执行后会在/Users/dexteryy/Sites/www/目录里生成两个文件:session.viminfo和session.vim,如果版本号是大于0的整数,比如2,文件名会是session2.viminfo和session2.viminfo

需要恢复的时候只要输入命令::LOAD MYWEB 0 就行叻~

喔对了,为了能在VIM命令里使用bash中定义的变量,你需要在MacVim的preferences里把“Launch Vimprocesses in a loginshell”勾选,熟悉Mac应用的同学应该都能想到这个设置会记录在/Library/Preferences/或~/Library/Preferences/里的某个配置文件里,MacVim对应的是~/Library/Preferences/org.vim.MacVim.plist,所以你也可以直接用这个命令在终端里修改:

defaults write org.vim.MacVim MMLoginShell 1
如果使用的是Gvim或windows版本的vim,也可以直接把路径变量写在.vimrc里,比如:

let g:TUISVN="/Users/dexteryy/Sites/Tudou/ui/ui/"
然后修改上面的两个函数GetMySession和SetMySession,把a:spath前面的$都删掉…………因为VIM里的变量只能由大写字母开头……

完整的.vimrc在这里…………呃好罢我发现google code真是备份和维护配置脚本的好地方XD


最后继续讨论一下插件~

首先是Taglist,这是一个能让vim具备类似Aptana的OutlineView的功能,还能像JAVA的IDE那样通过类名和方法名直接跳转到相应的源码,它借助了一个叫ctags的工具,可以解析源码生成标签文件(在同一个名录下,叫tags),详细的介绍请参考Easwy老爷的文章,记得务必安装最新版的ExuberantCtags……我是用MacPorts装的:sudo port install ctags

ExuberantCtags号称支持34种语言,包括javascript,但是它对javascript的理解非常OUT……比如现在定义JS方法几乎主要依靠匿名函数了,ctags却无法识别这种形式……

已经有人在尝试自己添加匹配规则,我自己也写了一大坨:

--langdef=js
--langmap=js:.js
--regex-js=/[ \t.]([A-Z][A-Z0-9._$]+)[ \t]*=[\t]*[0-9"'
{]/\1/n,constant/−−regex−js=/([A−Za−z0−9.$]+)[\t]∗=[\t]∗{/\1/o,object/−−regex−js=/[′"]∗([A−Za−z0−9$]+)[′"]∗[\t]∗:[\t]∗{/\1/o,object/−−regex−js=/([A−Za−z0−9.$]+)\[["′]([A−Za−z0−9$]+)["′]
[ \t]*=[\t]*\{/\1\.\2/o,object/
--regex-js=/([A-Za-z0-9._$]+)\.prototype[ \t.=]/\1/c,class/
--regex-js=/([A-Za-z0-9._$]+)[ \t]*=[\t]*function\(/\1/c,class/
--regex-js=/['"]*([A-Za-z0-9_$]+)['"]*:[\t]*function\(/\1/c,class/
--regex-js=/var[ \t]*([A-Za-z$][A-Za-z0-9_$()]+)[ \t]*=[\t]*function[ \t]*/\1/f,function/−−regex−js=/function[\t]+([A−Za−z$][A−Za−z0−9$]+)[\t]∗\(([)])

/\1/f,function/
--regex-js=/['"]*([A-Za-z$][A-Za-z0-9_$]+)['"]*:[ \t]*function[\t]*\(/\1/m,method/
--regex-js=/([A-Za-z$][A-Za-z0-9_$]+)[ \t]*=[ \t]*function[\t]*\(/\1/m,method/
--regex-js=/([A-Za-z0-9_$]+)\[["']([A-Za-z0-9_$]+)["']\][ \t]*=[\t]*function[ \t]*\(/\2/m,method/
--regex-js=/([A-Za-z0-9._$]+)[ \t]*=[ \t]*\[/\1/a,array/
--regex-js=/['"]*([A-Za-z$][A-Za-z0-9_$]+)['"]*:[\t]*\[/\1/a,array/
--regex-js=/([A-Za-z0-9._$]+)\[["']([A-Za-z0-9_$]+)["']\][ \t]*=[\t]*\[/\1\.\2/a,array/
匹配以下语法形式,其中粗体部分是标签名称:

var MY_CONSTANT = 250; //constant
ns.myobject = {}; //object
myobject: {}, //object
ns["myobject"] = {}; //object, 生成的tag是”ns.myobject“
ns.myclass.prototype.myfunc = function(){}; //class
ns.myclass = (function(){return {};}); //class
ns["myclass"] = (function(){return {};}); //class,生成的tag是”ns.myclass“
var myfunc = function(){}; //function, 必须有var, _开头的忽略
function myfunc(){}; //function
myfunc: function(){} //method
ns.myfunc = function(){}; //method
ns["myfunc"] = function(){}; //method, 生成的tag是”ns.myfunc“
ns.myarray = []; //array
myarray: [], //array
ns["myarray"] = []; //array, 生成的tag是”ns.myarray“
使用方法是建一个~/.ctags文件,把上面那段代码放进去就行。为了在taglist窗口里显示类别(比如class和method),还需要在.vimrc里设置一个变量:

let g:tlist_javascript_settings ='javascript;f:function;c:class;o:object;m:method;s:string;a:array;n:constant'


另一个要强烈推荐的插件是NERD Commenter,从名字能看出跟上次推荐的NERDTree是同一个强者写的,功能是针对各种文件类型快速的添加和删除注释,除了单行,多行,还提供“sexily”的注释……比如js里添加文档内容时常用的那种(如果首行写成/**,在aptana里会认作scriptdoc格式)

不过这个插件默认使用了大量,c开头的快捷键……而,在vim里一般都用作自定义的键(的默认值是\,很显然小拇指没食指方便……),我没有找到相关的设置选项……所以直接修改了插件脚本……


全部评论

相关推荐

10-11 17:45
门头沟学院 Java
走吗:别怕 我以前也是这么认为 虽然一面就挂 但是颇有收获!
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务