1. 程式人生 > >用Vim打造Perl的IDE

用Vim打造Perl的IDE

使用Eclipse EPIC外掛寫perl程式有一段時間了,覺得它的自動完成和跳轉功能比較弱(可能是因為我不太會使用的原因),決定試試vim,先在Windows 7上安裝個vim (我安裝的是7.4版本的)學習一下。

本文的配置都是在gVim下實驗過的,沒有試過terminal下的Vim。

Vim相關的文件和帖子中經常提到的一些東西的解釋:

1. $HOME 及 ~ ,這兩個基本上是一樣的,是你的home目錄。$VIM是Vim程式的安裝目錄, $VIMRUNTIME 一般是Vim程式(比如Windows上是vim.exe,gvim.exe)所在的目錄,比如在我的Windows 7上上查到的$VIMRUNTIME是C:\Program Files (x86)\Vim\vim74。 runtimepath和$VIMRUNTIME不是相同的東西,可以在Vim的命令列模式下通過 set rtp檢視runtimepath裡面含了那些路徑。

2.Vim的模式。Vim有多種模式,包括Normal Mode, Insert Mode, Visual Mode,Command-line mode等

3. 在Vim命令列模式下可以通過用echo命令顯示一個變數的值,比如 echo $HOME

4. Vim命令列模式下鍵入命令時,可以用tab鍵進行自動補全

5. Vim配置檔案,Windows上一般是指 $HOME/_vimrc,linux/unix/Max OS一般是 $HOME/.vimrc

6.Vim的個人檔案目錄,Windows上一般是 $HOME/vimfiles,linux/unix/Max OS一般是 $HOME/.vim

7. 很多plugin的說明中提到了 ,這個預設情況下值得是 \

8. 如果你看到像<C-v>字樣的指示,指的是CTRL和v鍵同時按下。

9. 有時侯字母的大小寫代表的是不同的意思,比如F是指Shift+f,和小寫的f是不一樣的

10. Vim配置檔案檔案中的註釋符號是單個雙引號

注意事項:

Vim預設的 Keycodes and maps 超時時間似乎比較短,導致我多次誤認為安裝上的外掛沒有正常工作,在配置檔案中做了如下設定,好了許多

" Keycodes and maps timeout in 1/2 sec...

set timeout timeoutlen=500 ttimeoutlen=500

VIM配置檔案

Windows上配置檔案一般是 _vimrc,linux/unix/Mac OS一般是 .vimrc 。

Linux/Unix/Mac OS上將按以下順序在不同位置尋找配置檔案

1)$VIM/.vimrc

2)$HOME/.vimrc

Windows上,VIM將按以下順序在不同位置尋找配置檔案

1)$VIM/_vimrc

2)$HOME/_vimrc

Note: $HOME目錄下有配置檔案的話,$VIM目錄中的配置檔案不起作用。

我的配置過程:

在Windows的cmd命令列下沒有查到$HOME和$VIM這兩個環境變數,但是在powershell下可以看到$HOME變數是有值的。

雖然在cmd或powershell下查不到$VIM變數,但是開啟vim,鍵入echo $VIM命令,可以看到$VIM是C:\Program Files (x86)\Vim,鍵入echo $HOME命令,可以看到$HOME是C:\Users\xxx (此處xxx是使用者名稱)。

剛安裝好Vim後,到$HOME目錄檢視,沒有_vimrc檔案,沒有vimfiles目錄, 到$VIM目錄下檢視,有_vimrc配置檔案,這個配置檔案裡面又通過source命令引用了$VIMRUNTIME/mswin.vim 和$VIMRUNTIME/vimrc_example.vim。

  • 建立自己的配置檔案及個人目錄

在$HOME目錄中新建一個_vimrc檔案用來做自己的自定義配置檔案,然後在$HOME目錄中新建一個vimfiles目錄用來存放Vim 各種plugin的檔案。

Pathogen這個Vim外掛是用來管理Vim的runtimepath的,這也使在個人目錄中安裝外掛變得非常容易,因為Vim啟動的時候會掃描runtimepath下的plugin,syntax等目錄載入runtime檔案。

如前所述,可以在Vim的命令列模式下通過 set rtp 這個命令檢視runtimepath裡面含了那些路徑。

安裝配置步驟:

從github上,點那個”Donwload Zip“按鈕,下載 pathogen.vim

在$HOME\vimfiles目錄下新建下面兩個資料夾

autoload

bundle

把pathogen.vim放到autoload目錄中,然後把下面一行新增到$HOME\_vimrc檔案中的第一行

execute pathogen#infect()

搞定,隨後要安裝的plugin只用解壓到$HOME\vimfiles\bundle目錄下即可

下載snipMate並解壓到$HOME\bundle目錄下,然後在Vim的命令列模式下執行helptags $HOME\vimfiles\bundle\snipMate\doc,這樣就可以在Vim的命令列模式下執行help snipMate來檢視它的幫助檔案了。

本文接下來提到的Vim外掛的安裝如沒有特殊說明,則安裝方法和這個一樣。

snipMate簡介

snipMate.vim aims to be an unobtrusive, concise vim script that implements some of TextMate's snippets features in Vim. A snippet is a piece of often-typed text that you can insert into your document using a trigger word followed by a . For instance, in a C file using the default installation of snipMate.vim, if you type "for" in insert mode, it will expand a typical for loop in C: for (i = 0; i < count; i++) { }

用法舉例:

開啟一個.pl檔案,輸入for然後按tab鍵,就會自動生成下面的程式碼

for (my $var = 0; $var < count; $var++) {
    # body...
}

不知道這個具體能起到什麼作用,但是還是從github上下載下來按照上面的方法安裝了一下。

perl-help外掛的一個好處是它可以讓你在在Vim中開啟perl文件並在Vim中進行檢視,比通過在Vim命令列下用!perldoc開啟一個Windows的命令列視窗檢視perl文件方便

這個外掛的說明文件最好看Github上的。

這個外掛的簡單描述:

extended % matching for HTML, LaTeX, and many other languages 

which extends the shift + F5 (%) parenthesis matching in Vim to match HTML tags and if/then/else statements and other constructs.

這個外掛的簡單描述:

Surround.vim is all about "surroundings": parentheses, brackets, quotes, XML tags, and more. The plugin provides mappings to easily delete, change and add such surroundings in pairs.

具體用法可以看它自帶的文件或者下面這篇博文

這個外掛的簡單描述:

provides insert mode auto-completion for quotes, parens, brackets, etc

接下來要安裝的taglist依賴這個,Vim自身的自動完成(auto completion)功能也會用到用它或其他工具生成的Tags檔案。

簡單描述:

Ctags generates an index (or tag) file of language objects found in source files that allows these items to be quickly and easily located by a text editor or other utility. A tag signifies a language object for which an index entry is available (or, alternatively, the index entry created for that object).

The “Exuberant ctags” program is a ctags clone that is considerably more capable than Unix ctags. It produces an extended tags file format that makes the tag searching and matching process more flexible and powerful.

安裝:

下載ctags58.zip (Source and binary for Windows 98/NT/2000/XP),開啟這個檔案,把其中的ctags.exe 解壓出來,在C:\Program Files (x86)下新建一個ctags目錄,把ctags.exe拷貝到這個目錄下,然後把C:\Program Files (x86)\ctags加入到windows的PATH環境變數中

對Perl程式的變數沒有生成tags,通過下面的命令確認了ctags的確不支援生成Perl變數的tags,

 ctags --list-kinds=perl

 c constants

 f formats

 l labels

 p packages

 s subroutines

 d subroutine declarations [off]

不過 C:\Program Files (x86)\Vim\vim74\tools下有個pltags.pl工具,可以用來對perl的程式檔案生成tags,包括perl程式檔案中的變數。

CPAN上有一個 Vim::Tag 可以用來生成 perl tags for vim,不過我沒有使用過。

Github上還有一個 https://github.com/kberov/ctags, Extended Rules to support Modern Perl in Exuberant Ctags,我沒有試過。

配置Ctags:

編輯vim配置檔案

新增兩行: 

set tags=tags;

set autochdir

這裡第一個命令裡的分號是必不可少的。這個命令讓Vim先在當前目錄裡尋找tags檔案,如果沒有找到tags檔案,或者沒有找到對應的目標,就到父目錄中查詢,一直向上遞迴。因為tags檔案中記錄的路徑總是相對於tags檔案所在的路徑,所以要使用第二個設定項來改變vim的當前目錄。如果你想直接使用絕對路徑,這樣也是可以的:

set tags=/absolute/path/to/tags (把/absolute/path/to/tags換成你要設定的絕對路徑)

在使用過程中我用Ctags生成的tags檔案似乎不能正常跳轉,而使用pltags.pl工具生成的tags檔案可以正常使用,不知道哪裡弄錯了。

用法舉例:

游標移動到一個function名字上,按CTRL+],跳到該function定義的地方,接這按CTRL+t 就會跳回來。

簡單描述:

The "Tag List" plugin is a source code browser plugin for Vim and provides an overview of the structure of source code files and allows 

you to efficiently browse through source code files for different programming languages.  

因為taglist需要呼叫ctags工具來生成tag檔案,所以我們之前安裝Ctags的時候要把Ctags的安裝路徑放到Windows的PATH變數中去,如果沒有,也可以通過在Vim中設定Tlist_Ctags_Cmd這個變數的值來指定Ctags程式的位置

taglist預設情況下不會顯示Perl程式裡面的變數,不過如果有需要,可以通過修改taglist.vim來實現。

下面是在網上看到的一段關於對C++設定的話,供參考

--------------------------------

There is a variable s:tlist_def_cpp_settings in Taglist plugin (.vim/plugin/taglist.vim) that defines which elements are shown by default.

I extended it to:

let s:tlist_def_cpp_settings = 'c++;n:namespace;v:variable;d:macro;t:typedef;' . \ 'c:class;g:enum;s:struct;u:union;f:function;m:member;' . \ 'p:prototype'

According to taglist manual you can also define tlist_cpp_settings in your .vimrc with similar value. For other languages different variables exist.

--------------------------------

taglist常用的幾項_vimrc設定:

“禁止自動改變當前Vim視窗的大小

let Tlist_Inc_Winwidth=0

“把列表放在螢幕的右側

let Tlist_Use_Right_Window=1

“讓當前不被編輯的檔案的列表自動摺疊起來, 這樣可以節約一些螢幕空間

let Tlist_File_Fold_Auto_Close=1

啟用taglist

在Vim的命令列模式下如果Tlist命令即可


Vim的 Auto Complete

Vim的自動完成的方法:

Command        Type of Completion
<C-n>               Generic keywords
<C-x><C-n>    Current buffer keywords
<C-x><C-i>     Included file keywords
<C-x><C-]>     tags file keywords
<C-x><C-k>    Dictionary lookup
<C-x><C-l>    Whole line completion
<C-x><C-f>    Filename completion
<C-x><C-o>  Omni-completion
In insert mode, type the first couple of characters of a word, then press:
Ctrl-N to insert the next matching word; or Ctrl-P to insert the previous matching word.
This is particularly useful when entering the names of variables in a program.

The 'complete' option controls where the keywords are searched (include files, tag files, buffers, and more).
The 'completeopt' option controls how the completion occurs (for example, whether a menu is shown).

Vim Omni completion

Omni completion using a tags file will complete the names of defined constants, functions, classes and other names from included and other external files.

When generating a tags file, Exuberant Ctags should be used
Omni completion is not usually enabled by default. To turn on omni completion, add the following to your vimrc:
filetype plugin on
set omnifunc=MyCompleteFunction

Now you would just have to create a function called MyCompleteFunction that gives you the completions. This setting is only available to the currently active buffer, and you will have to set it for all buffers where you want to use it. Setting omnifunc is normally done in a file type plugin such that it is bound to a single file type.

看了一下perl的 type plugin,沒有找到類似syntaxcomplete#Complete樣子的語句,感覺是不支援Omni-completion. Github上有一個perlomni外掛,不過我沒有試

  • 安裝neocomplcache:

neocomplcache的簡單描述:

neocomplcache : Ultimate auto completion system for Vim

neocomplcache is the abbreviation of "neo-completion with cache". It provides keyword completion system by maintaining a cache of keywords in the current buffer. 

具有使用快取,自動補全時效率高、生成的關鍵詞列表準確等優點。

設定:

安裝後,在_vimrc檔案中新增下面的配置

let g:neocomplcache_enable_at_startup = 1

使用:

輸入兩個字母后會自動彈出補全的選單,它似乎是不會去搜索tag檔案的,

Ctrl-N to insert the next matching word; or Ctrl-P to insert the previous matching word.

注意:

開啟檔案第一次進入insert mode,第一次編輯時,會有停頓,可能是neocomplcache在生成關鍵詞列表的緣故。

檔案瀏覽器

netrw.vim是Vim自帶的檔案瀏覽器, 如果希望在vim中檢視到檔案的目錄結構,

:Ex 開啟目錄瀏覽器netrw

:Sex 水平分割當前視窗,並在一個視窗中開啟目錄瀏覽器

:Vex 垂直分割當前視窗,並在一個視窗中開啟目錄瀏覽器
或者

:e some/directory 編輯一個目錄,這樣就打開了該目錄結構

不過,我比較喜歡NERD tree這個外掛的顯示方式,就在vim配置檔案中新增下面一行禁用netrw
let loaded_netrwPlugin = 1

簡單描述:

The NERD tree : A tree explorer plugin for navigating the filesystem 

用法:

開啟Gvim, 用命令 :NERDTree path/to/your/desired/directory  這會在左側垂直分割出來一個視窗顯示目錄結構

Nerd Tree plugin can be activated by the :NERDTree vim command.

Here are the basics of how to use the plugin:

Use the natural vim navigation keys hjkl to navigate the files.

Press o to open the file in a new buffer or open/close directory.

Press t to open the file in a new tab.

Press i to open the file in a new horizontal split.

Press s to open the file in a new vertical split.

Press p to go to parent directory.

Press r to refresh the current directory.

All other keyboard shortcuts can be found by pressing ?. It will open a special help screen with the shortcut listings. Press ? again to get back to file tree.

To close the plugin execute the :NERDTreeClose command.

Mojolicious Wiki上提到的, Mojolicious templates syntax。

到Github上下載,解壓到pathogen管理的bundle目錄,之後把mojo.vim目錄下的的snippets目錄中的epl.snippets拷貝到snipMate外掛目錄下的snippets目錄中,之後把mojo.vim目錄下的的snippets目錄刪除,不然會導致snipMate不能正常工作。

The NERD Commenter : A plugin that allows for easy commenting of code for many filetypes. 

可以從github下載最新版

使用說明:

n\cc : 為游標以下 n 行添加註釋

n\cu : 為游標以下 n 行取消註釋

n\cm : 為游標以下 n 行新增塊註釋

注:

其中 \ 是Vim 預設的 <leader> 值,可通過在 .vimrc 檔案中新增  nmap ,cc <leader>cc  =  修改對映為 , 鍵。就可在Normal Mode中使用   n,cc   n,cu  n,cm 快捷鍵設定註釋了。

簡單描述:

True Sublime Text style multiple selections for Vim

用這個外掛可以實現多行同時編輯

可在正常、插入和視覺化三種模式下工作。

使用舉例:

按下<C-n>選中游標下的單詞

繼續按下<C-n>兩次選中另外兩個相同的單詞

按下c進行修改

鍵入修改內容

按下 <Esc> 退出

我沒有安裝Supertab,因為不知道如何讓它和snipMate和諧相處。

學習資源:

http://slideshare.net 搜尋Vim

Youtube

參考文章:

Perl最佳實踐附錄中下面關於vim設定的部分

Vim相關的書籍

Hacking Vim

Learning the Vi and Vim Editors (7th Edition) 這個有中文版的

practical vim

vim 101 hacks

我的配置檔案設定:

禁用了Normal Mode中使用上下左右方向鍵,強制自己熟悉hjkl這四個鍵

用分號來代替冒號,這樣從Normal模式進入Command-line模式少按一下SHIFT鍵

參考了$VIMRUNTIME/mswin.vim 和$VIMRUNTIME/vimrc_example.vim,設定了Windows風格的拷貝粘帖快捷鍵(CTRL-C,CTRL-V),這樣即可以在Vim內用這兩個快捷鍵做複製(到系統粘帖板)貼上(待粘帖的內容是從系統粘帖板取的),暫考慮到用系統粘帖板進行復制剪下的時候不多,就沒有設定剪下(CTRL-X)快捷鍵。

把CTRL+S設定成insert mode下的Save快捷鍵。

通過下面的設定,不讓自動完成功能搜尋C:\Perl\lib目錄,不然的話,會很慢。
set complete-=i

設定colorscheme為desert,似乎這個是多數人的選擇。可以到$VIMRUNTIME\colors下檢視VIM自帶的各種colorscheme的名稱,網上也可以下載到很多其他的colorscheme,blackboard.vim這個colorscheme似乎不錯。

execute pathogen#infect()
filetype plugin indent on

" CTRL-C is Copy, to system clipboard
vnoremap <C-C> "+y
" CTRL-V is Paste, from system clipboard
vnoremap <C-V> "+gP
cmap <C-V>		<C-R>+
" Pasting blockwise and linewise selections is not possible in Insert and
" Visual mode without the +virtualedit feature.  They are pasted as if they
" were characterwise instead.
" Uses the paste.vim autoload script.
" Use CTRL-G u to have CTRL-Z only undo the paste.

exe 'inoremap <script> <C-V> <C-G>u' . paste#paste_cmd['i']
exe 'vnoremap <script> <C-V> ' . paste#paste_cmd['v']
" Use CTRL-Q to do what CTRL-V used to do, Henry: tested, CTRL-V still enter
" into block visual mode
noremap <C-Q>		<C-V>
" For CTRL-V to work autoselect must be off.
" On Unix we have two selections, autoselect can be used.
if !has("unix")
  set guioptions-=a
endif

colorscheme desert
" In many terminal emulators the mouse works just fine, thus enable it.
if has('mouse')
  set mouse=a
endif

" Switch syntax highlighting on, when the terminal has colors
" Also switch on highlighting the last used search pattern.
if &t_Co > 2 || has("gui_running")
  syntax on
  set hlsearch
endif

set incsearch "highligh search while typing search pattern

" Convenient command to see the difference between the current buffer and the
" file it was loaded from, thus the changes you made.
" Only define it when not defined already.
if !exists(":DiffOrig")
  command DiffOrig vert new | set bt=nofile | r ++edit # | 0d_ | diffthis
		  \ | wincmd p | diffthis
endif

"always open vertical split window in the right side
set splitright
"always open horizontal split window below
set splitbelow
"STOP using the arrow keys
map <up> <nop>
map <down> <nop>
map <left> <nop>
map <right> <nop>
"replace 'SHIFT+:' with ';'
noremap ; :
" Use Ctrl+hjkl to switch between Window in normal mode
nmap <C-j> <C-w>j
nmap <C-k> <C-w>k
nmap <C-h> <C-w>h
nmap <C-l> <C-w>l
"ctrl+s to save the file in insert mode
imap <C-s> <C-O>:w<cr>
set showmatch
set cursorline
"set cursorcolumn
set number
set ruler
let g:neocomplcache_enable_at_startup=1
let loaded_netrwPlugin=1
"Below is to set the path where to search the tag file
set tags=tags;
set autochdir
"For auto completion, do not scan the included files, otherwise, it is very slow
set complete-=i

" Keycodes and maps timeout in 1/2 sec...
set timeout timeoutlen=500 ttimeoutlen=500

set smarttab "use shiftwidth when inserting 
set autoindent "Preserve current ident on new lines
set textwidth=78 "Wrap at this column
" allow backspacing over everything in insert mode
set backspace=indent,eol,start

set tabstop=4 "Indentation levels every four columns
set expandtab "Convert all tabs typed to spaces
set shiftwidth=4 "Indent/outdent by four columns
set shiftround "Indent/outdent to nearest tabstop
"when filetype is perl, use autocmd to set external program to use for = command
autocmd Filetype perl :set equalprg=perltidy  
"every time a file ending in .pm, .t, or.pl is saved, 
"vim will run the check syntax command on the file, 
"echoing the results to the current windowi
"%:p will pass the full path name of the file to the Unix command 
autocmd BufWritePost *.pm,*.t,*.pl echom system("perl -Ilib -c " . '"' . expand("%:p"). '"' )

下面是我的vimfiles目錄結構

|~vimfiles/
| |~autoload/
| | `-pathogen.vim
| `~bundle/
|   |~delimitMate-2.7/
|   | |+autoload/
|   | |+doc/
|   | `+plugin/
|   |~matchit/
|   | |+doc/
|   | `+plugin/
|   |~mojo.vim/
|   | |+after/
|   | |+ftdetect/
|   | |+syntax/
|   | |+t/
|   | |-Changes
|   | |-LICENSE
|   | |-Makefile
|   | `-README
|   |~neocomplcache-8.0/
|   | |+autoload/
|   | |+doc/
|   | |+plugin/
|   | |+vest/
|   | `-README.md
|   |~nerdcommenter/
|   | |+doc/
|   | `+plugin/
|   |~nerdtree/
|   | |+doc/
|   | |+nerdtree_plugin/
|   | |+plugin/
|   | `+syntax/
|   |~perlhelp/
|   | |+doc/
|   | `+plugin/
|   |~snipMate/
|   | |+after/
|   | |+autoload/
|   | |+doc/
|   | |+ftplugin/
|   | |+plugin/
|   | |+snippets/
|   | `+syntax/
|   |~surround/
|   | |+doc/
|   | `+plugin/
|   |~taglist_46/
|   | |+doc/
|   | `+plugin/
|   |~vim-multiple-cursors/
|   | |+assets/
|   | |+autoload/
|   | |+doc/
|   | |+plugin/
|   | |+spec/
|   | |-CHANGELOG.md
|   | |-Gemfile
|   | |-Gemfile.lock
|   | |-MIT-LICENSE.txt
|   | |-Rakefile
|   | `-README.md
|   `~vim-perl/
|     |+contrib/
|     |+ftdetect/
|     |+ftplugin/
|     |+indent/
|     |+syntax/
|     |+t/
|     |+t_source/
|     |+tools/
|     |-build-corpus.pl
|     |-Changes
|     |-CONTRIBUTING.md
|     |-funcs-from-perlfunc.pl
|     |-Makefile
|     |-README.md
|     `-verify-corpus.pl