首先每个 “用户自定义工具” 使用一个独立的 shell脚本来描述(Windows下是.cmd的批处理文件),我们将首先编写 vimmake可以使用的 gcc编译工具脚本, "~/.vim/vimmake.gcc":
#! /bin/sh
gcc "$VIM_FILEPATH" -o "$VIM_FILEDIR/$VIM_FILENOEXT"
就这么短短的两行,当你把它设置成 0755的权限时,就可以在 Vim中通过下面语句运行了:
:VimTool gcc
命令 “:VimTool {name} ” 命令会在 Vim里面直接调用 ~/.vim/ 目录下,名为 "vimmake.{name}" 的脚本来完成各种类似编译或者执行的任务,所以用":VimTool gcc" 就可以运行前面定义的名为 vimmake.gcc 的工具脚本来编译当前的源代码了。
现在编辑 "~/.vim/" 下面名为 "vimmake.run" 的脚本,以便用":VimTool run" 来运行当前代码:
#! /bin/sh
"$VIM_FILEDIR/$VIM_FILENOEXT"
记得将 vimmake.run 的模式设置成 0755,如今有了两个可以直接在 Vim里通过 VimTool命令启动的工具(gcc 和 run),接下来我们需要设置 run 这个工具的模式为默认运行模式,而 gcc 为 quickfix模式(输出会被捕获并重定向到 quickfix窗口),现在打开 .vimrc 添加一行:
let g:vimmake_mode = { 'gcc':'quickfix', 'run':'normal' }
而如果我们能够使用到较新版本的 vim(7.4.1829或者更高),我们就可以使用异步方式在后台启动 gcc,并且将后台进程的输出实时重定向到界面下端的 quickfix 窗口:
let g:vimmake_mode = { 'gcc':'async', 'run':'normal' }
在这之后,将 'gcc'的运行模式设置成 'async' 后,':VimTool gcc' 就可以以异步的方式运行名为 vimmake.gcc 的脚本然后在后台执行编译任务了,就像传统 IDE编译任务一样。
以往使用 Vim 的 :make 之类的命令编译项目时,往往无法异步,编译任务一运行,你就无法编辑了,只有等到编译结束,才能返回编辑状态,大项目时,不得不另外开一个终端来进行编译,这是很痛苦的事情,有了异步任务以后,你能在同一个屏幕下编辑并且实时在 quickfix窗口查看编译的进度。
vimmake 可以让你在不需要掌握晦涩的 VimScript 和繁琐的异步编程接口的情况下,直接方便的使用vim 异步功能来完成各种长时间编译任务。同时为了加快你的:编译-编辑-编译 工作流的流畅度,我们需要配置一两个热键来调用 :VimTool 命令:
noremap <F7> :VimTool gcc<cr>
noremap <F5> :VimTool run<cr>
inoremap <F7> <ESC>:VimTool gcc<cr>
inoremap <F5> <ESC>:VimTool run<cr>
在 .vimrc里面加入上面的几行代码,你就可以方便的按 F7编译当前文件,F5运行之了。和GEdit
类似,VimTool命令在运行具体工具脚本前会设置若干环境变量来记录当前编辑的文件名,路径,当前vim工作目录等一系列信息,然后在工具脚本里面可以直接取出这些值来调用需要的外部工具链:
如上图,后台运行工具脚本进行编译,并且编译器的输出会被实时显示到下面的 quickfix窗口,选中错误的那行输出,会直接跳转,知乎不能插入 gif录屏动画,可以点击这里查看动画演示:
https://raw.githubusercontent.com/skywind3000/vimmake/master/images/screen1.gif
命令解释:VimTool - 执行用户自定义工具
下面这条命令会运行名为 "~/.vim/vimmake.{name}" 的脚本:
:VimTool {name}
在 Windows下的话,会运行名为: "C:\Users\yourname\.vim\vimmake.{name}.cmd" 的批处理。
{name} 后面还可以跟随一个名为 {target} 的参数:
:VimTool {name} {target}
{target} 的内容会作为环境变量:$VIM_TARGET 传入到 vimmake.{name} 的脚本中。工具脚本可以使用这个值作为 make target 当作第一个参数传给 make程序。“:VimTool" 命令在调用每个工具脚本前,会初始化下面一些系统环境变量供脚本使用:
$VIM_FILEPATH File name of current buffer with full path
$VIM_FILENAME File name of current buffer without path
$VIM_FILEDIR Full path of current buffer without the file name
$VIM_FILEEXT File extension of current buffer
$VIM_FILENOEXT File name of current buffer without path and extension
$VIM_CWD Current directory
$VIM_RELDIR File path relativize to current directory
$VIM_RELNAME File name relativize to current directory
$VIM_CWORD Current word under cursor in the buffer
$VIM_GUI Is it running in gui ?
$VIM_VERSION Value of v:version
$VIM_MODE Execute via 0:bang(!), 1:makeprg, 2:system(), ...
$VIM_SCRIPT Home path of tool scripts
$VIM_TARGET Target given after name as ":VimTool {name} {target}"
$VIM_COLUMNS How many columns in vim's screen
$VIM_LINES How many lines in vim's screen
命令解释:VimStop
停止当前后台任务(如果使用async模式运行的话),VimStop! 可以发送-9号信号强制杀死后台进程,一般很少用。
参数配置:
g:vimmake_mode 是一个字典,你可以在 .vimrc中这样初始化不同工具的运行模式:
let g:vimmake_mode = {}
let g:vimmake_mode['gcc'] = 'async'
let g:vimmake_mode['run'] = 'normal'
运行模式可以有下面几种:
normal 默认模式,运行工具并等待结束后返回vim(win下弹出窗口运行,不必等待)
quickfix 运行工具并等待结束后返回vim,把结果输出到 quickfix
bg 在后台运行工具,并且忽略任何输出。
async 异步任务方式在后台运行工具,并且把输出实时显示在 quickfix中
let g:vimmake_path = '/home/myname/github/config/tools'
这样 :VimTool {name} 就会在新的路径下 运行 vimmake.{name} 这个脚本了,如此,你可以方便的把你的一系列工具脚本放到你的 github 仓库中,并且在不同的地方愉快的同步了。
如果设置成1,那么 VimTool 运行工具脚本前会保存当前正在编辑的文件。
当异步任务执行完后, g:vimmake_build_post 中保存的 VimScript 会被自动执行,可以被用来调用外部工具,比如在编译结束后调用 afplay来播放一个wav文件:
let g:vimmake_build_post = "silent call system('afplay ~/.vim/notify.wav &')"
这样当你眼镜盯着代码看的时候就不必当心编译结束了你还不知道,afplay是 mac os x 下命令行播放 wav文件的程序,Windows下你可以使用:
https://github.com/skywind3000/support/blob/master/tools/playwav.exe
这个工具来播放音效,比如:
let g:vimmake_build_post = 'silent !start playwav.exe "C:/Windows/Media/Windows Error.wav" 200'
#! /bin/sh
cd "$VIM_FILEDIR"
case "$VIM_FILEEXT" in
\.c|\.cpp|\.cc|\.cxx)
"$VIM_FILEDIR/$VIM_FILENOEXT"
;;
\.py|\.pyw)
python "$VIM_FILENAME"
;;
\.pl)
perl "$VIM_FILENAME"
;;
\.lua)
lua "$VIM_FILENAME"
;;
\.js)
node "$VIM_FILENAME"
;;
\.php)
php "$VIM_FILENAME"
;;
*)
echo "unexpected file type: $VIM_FILEEXT"
;;
esac
#! /bin/sh
make $VIM_TARGET
#! /bin/sh
WIDTH=`expr $VIM_COLUMNS - 10`
man -S 3:2:1 -P cat "$VIM_CWORD" | fold -w $WIDTH
#! /bin/sh
go build "$VIM_FILEPATH"
noremap <F7> :VimTool gcc<cr>
noremap <F5> :VimTool run<cr>
noremap <F8> :VimTool go<cr>
inoremap <F7> <ESC>:VimTool gcc<cr>
inoremap <F5> <ESC>:VimTool run<cr>
inoremap <F8> <ESC>:VimTool go<cr>
noremap <F10> :silent call vimmake#Toggle_Quickfix()<cr>
inoremap <F10> <ESC>:silent call vimmake#Toggle_Quickfix()<cr>
@ECHO OFF
if "%VIM_FILENAME%" == "" GOTO ERROR_NO_FILE
CD /D "%VIM_FILEDIR%"
if "%VIM_FILEEXT%" == ".c" GOTO RUN_MAIN
if "%VIM_FILEEXT%" == ".cpp" GOTO RUN_MAIN
if "%VIM_FILEEXT%" == ".cc" GOTO RUN_MAIN
if "%VIM_FILEEXT%" == ".cxx" GOTO RUN_MAIN
if "%VIM_FILEEXT%" == ".py" GOTO RUN_PY
if "%VIM_FILEEXT%" == ".pyw" GOTO RUN_PY
if "%VIM_FILEEXT%" == ".bat" GOTO RUN_CMD
if "%VIM_FILEEXT%" == ".cmd" GOTO RUN_CMD
if "%VIM_FILEEXT%" == ".js" GOTO RUN_NODE
echo unsupported file type %VIM_FILEEXT%
GOTO END
:RUN_MAIN
"%VIM_FILENOEXT%"
GOTO END
:RUN_PY
python "%VIM_FILENAME%"
GOTO END
:RUN_CMD
cmd /C "%VIM_FILENAME%"
GOTO END
:RUN_NODE
node.exe "%VIM_FILENAME%"
GOTO END
:ERROR_NO_FILE
echo missing filename
GOTO END
:END
@ECHO OFF
if "%VIM_FILENAME%" == "" GOTO ERROR_NO_FILE
d:\dev\mingw32\bin\gcc -Wall -O3 -std=c++11 "%VIM_FILEPATH%" -o "%VIM_FILEDIR%/%VIM_FILENOEXT%" -lwinmm -lstdc++ -lgdi32 -lws2_32 -msse3 -static
GOTO END
:ERROR_NO_FILE
echo missing file name
:END
异步任务有三种状态: running, success 和 failure。可以编辑 .vimrc 在 quickfix的 statusline上面显示编译的状态:
augroup QuickfixStatus
au! BufWinEnter quickfix setlocal
\ statusline=%t\ [%{g:vimmake_build_status}]\ %{exists('w:quickfix_title')?\ '\ '.w:quickfix_title\ :\ ''}\ %=%-15(%l,%c%V%)\ %P
augroup END
全局变量 g:vimmake_build_status 用来实时表示异步任务状态:
这样你就可以在 quickfix 窗口的 statusline上实时查看编译进度了,返回值不用特异处理,调用完 gcc后正常结束你的工具脚本即可,bash 或者批处理会自动继承上一次外部进程的返回值作为自己进程结束的返回值,gcc在成功后会自动返回0,失败自动返回非零,这样会正确的影响到我们的 g:vimmake_build_status 变量。
#! /usr/bin/python
import sys, os
VIM_FILEDIR=os.environ.get('VIM_FILEDIR', '')
VIM_FILENAME=os.environ.get('VIM_FILENOEXT', '')
cmd = "cd \"%s\"; %s/%s; read -n1 -rsp press\ any\ key\ to\ continue\ ..."
cmd = cmd%(VIM_FILEDIR, VIM_FILEDIR, VIM_FILENAME)
cmd = cmd.replace('\\', '\\\\').replace('"', "\\\"").replace("'", "\\\'")
cmd = 'bash -c \"%s\"'%cmd
cmdline = 'gnome-terminal --command=\'%s\''%cmd
os.system(cmdline)
let g:vimmake_mode['1']='bg'
使用 VIM 多年,VIMRC 改了又改,我想,除了下面这句,没有什么配置是必备的。
set nocompatible
Vundle, the plug-in manager for Vim http:// github.com/gmarik/vundl e使用 Vundle 安装插件只需两步
Bundle 'HTML5-Syntax-File'
:BundleInstall