REPL,即read-eval-print loop,最早出现在Lisp中,Emacs的
Slime模式编写lisp非常方便。在Slime中流程是这样:
- 编写小段代码
- <C-c><C-c>运行小代码
- 查看結果,继续编写小段代码
整个过程不用在编辑器和解释器之间来回切换。在vim下也是可以做到这样,虽然可能实现并不怎么完美。
ConqueTerm可以在vim在模拟Terminal,运行:ConqueTermSplit ipython就可以分割一个窗口并在其中执行ipython解释器。在另一个窗口中选中一段python代码,按<F9>就可以执行选中代码,这已经很接近于Emacs的Slime,但有几个缺点:
- 对python代码不能自动执行,需要手动再按一个回车,因为ConqueTerm会将选中代码的多余回车给删掉。
- 执行之后,自动选中了ConqueTerm窗口,我们希望光标仍然在代码窗口。
对于第一个问题,似乎只能通过修改ConqueTerm插件源代码来解决,只需要注释掉autoload/conque_term.vim中函数conque_term#send_selected中的format yanked text,另外还将paste_selection改成了paste方法:
" send selected text from another buffer
function! conque_term#send_selected(type) "{{{
let reg_save = @@
" save user's sb settings
let sb_save = &switchbuf
set switchbuf=usetab
" yank current selection
sil exe "normal! `<" . a:type . "`>y"
" format yanked text
"let @@ = substitute(@@, '^[\r\n]*', '', '')
"let @@ = substitute(@@, '[\r\n]*$', '', '')
" execute yanked text
sil exe ":sb " . g:ConqueTerm_BufName
sil exe 'python ' . g:ConqueTerm_Var . '.paste()'
" reset original values
let @@ = reg_save
sil exe 'set switchbuf=' . sb_save
" scroll buffer left
startinsert!
normal 0zH
endfunction "}}}
对于第二个问题,则可以定义键映射来完成,在.vimrc中定义:
" ConqueTerm
"let g:ConqueTerm_TERM = 'xterm'
noremap ,tb :ConqueTermSplit bash<CR>
noremap ,tp :ConqueTermSplit ipython<CR>
vnoremap <C-c><C-c> :<C-u>call conque_term#send_selected(visualmode())<CR><Esc><C-w>p
noremap <C-c><C-c> V:call conque_term#send_selected(visualmode())<CR><Esc><C-w>p
这样按<C-c><C-c>将默认将当前行给ConqueTerm执行。
现在大致工作流程是这样:
- 打开vim编辑python文件
- :ConqueTermSplit ipython打开python解释器(或者用,tp)
- 选中代码,按<C-c><C-c>就可以直接在ConqueTerm中看到执行結果了。
编辑ruby,groovy等也是一样的,只需要将ipython换成相应解释器就行了。