以前写过一篇文章超轻量级纯文本界面 REPL 类语言 IDE, 介绍了在纯粹文本界面下如何用 Vim + Tmux + vim-slime
搭建一个超轻量级的 REPL
类语言开发环境, 配置步骤很简单, 初学者使用起来也很容易上手, 不过用过几回后发现缺憾: 这个开发环境是否是太简陋了点? 也就是比语言自带的 REPL
稍微多了个编辑区的功能, 尤为是使用过 Emacs + Slime
环境的朋友, 多么但愿能在 vi
下用到相似的功能啊!vim
好消息是, 如今 slimv
出现了--(其实它早就出现了,只不过刚刚进入本文做者视野), 它整合了 slime
的大多数功能, 能够用于 vim
环境. 不过初步阅读文档后发现, 帮助文档里介绍的 Linux
环境下的例子都要用到 XWindows
下的 XTerm
或者 KDE
下的 konsole
, 这有点背离咱们但愿使用纯文本界面的初衷, 毕竟咱们的目标是打造一款在流畅运行在树莓派上的超轻量级开发环境, 并不但愿启动笨重庞大的视窗系统来浪费资源.sass
怎么办? 先进行理论分析, 看看 slimv
的原理, 它其实跟 Emaca
下的 slime
同样, 使用 XTerm
的目的是为了启动一个 swank
服务端, 可是 swank
服务端是不须要视窗系统的, 能够直接在纯文本界面下用脚原本启动, 只要保持 slimv
和 swank
版本一致, 端口号使用 slimv
默认值, 那么咱们在纯文本界面下启动的 swank
服务端照样能够为 slimv
提供链接服务. 并且, Emacs + slime + Common Lisp
是能够运行于纯文本界面的, 说明从理论上讲, slimv
也应该具有这个能力.网络
先试验一下, 由于 slimv
中服务端的程序是这个 ~/.vim/bundle/slimv/slime/start-swank.lisp
因此咱们能够用任意一个 Common Lisp
实现来执行这个脚本, 这里咱们先试试 CLISP
, 命令为:app
clisp -i ~/.vim/bundle/slimv/slime/start-swank.lisp
刷过一堆信息, 最后显示:ide
;; Swank started at port: 4005.
很好,说明咱们经过命令行成功地启动了 swank
服务端函数
这个服务端口能够经过 slimv
或者 telnet
登陆上去, 先说说 telnet
怎么连, 另外开一个终端窗口, 输入学习
telnet 127.0.0.1 4005
就会显示链接成功:测试
Air:slime admin$ telnet 127.0.0.1 4005 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'.
而后第一个启动 CLISP
的终端窗口就会出现一个 REPL
提示符 CL-USER
, 变为以下界面:ui
;; Swank started at port: 4005. CL-USER>
这里其实就是通过 swank
包装的 REPL
接口, 是能够直接输入表达式求值的lua
CL-USER> (+ 12 34) (+ 12 34) 46 CL-USER>
好玩吧, :)
好了, 言归正传, 继续咱们的试验.
在 slimv
的文档中, 默认使用了 XTerm
来启动 swank
, 可是通过上面的理论分析和动手试验, 咱们清楚地了解到 swank
服务端并不须要一个图形界面下的程序来启动, 那么咱们但愿把 swank
服务端启动在一个 tmux
的窗口中, 这样咱们使用 vim + tmux
的组合时能够很方便地经过快捷键来切换, 固然, 也能够启动在同一个 tmux
窗口的不一样面板内, 可是鉴于咱们屏幕面积有限, 并且通常状况下不须要太多关注这个 swank
服务端的状态, 因此仍是另外启动一个新窗口好了.
这里由于以前对 tmux
主要是使用一些快捷键, 具体经过脚本如何调用的知识基本没查过, 因此稍微花了点时间去研究, 最终经过网络学习到了如何在 tmux
的窗口里启动程序, 其实就是一句脚本的正确格式,
tmux new-window -d -n REPL9 "clisp -i ~/.vim/bundle/slimv/slime/start-swank.lisp"
这行命令告诉 tmux
新建一个窗口(参数 new-window
), 后台运行(参数 -d
), 名字叫REPL9(参数 -n REPL9
), 而后在这个窗口内执行双引号里的命令(参数 "clisp -i ~/.vim/bundle/slimv/slime/start-swank.lisp"
)
很好, 在显示一大堆信息后 swank
服务端成功启动了, 执行结果
;; Swank started at port: 4005.
那咱们试着从 vim
中用 slimv
链接一下, 用 vim
打开一个测试用的 test.lisp 文件, 进入命令状态, 按下快捷键 逗号 小写英文字母c
,c
因而在 vim
的编辑窗口上方新开了一个 REPL
窗口, 显示以下:
24 CLISP 2.49 (2010-07-07) (built on air.local [192.168.0.2]) Port: 4005 Pid: 68955 25 ; SWANK 2014-10-10 26 CL-USER>
再去看看 swank 服务端, 显示以下:
;; Swank started at port: 4005. CL-USER> ;; Loading file /Users/admin/.vim/bundle/slimv/slime/contrib/swank-asdf.lisp ... ;; Loading file /Users/admin/.slime/fasl/2014-10-10/clisp-2.49-unix-unknown/contrib/swank-repl.fas ... WARNING: The generic function #<STANDARD-GENERIC-FUNCTION THREAD-FOR-EVALUATION> is being modified, but has already been called. WARNING: Replacing method #<STANDARD-METHOD (#<STRUCTURE-CLASS MULTITHREADED-CONNECTION> (EQL :FIND-EXISTING))> in #<STANDARD-GENERIC-FUNCTION THREAD-FOR-EVALUATION> ;; Loaded file /Users/admin/.slime/fasl/2014-10-10/clisp-2.49-unix-unknown/contrib/swank-repl.fas
很显然, 链接成功了! 试着在 REPL
区对表达式求值:
注意, 由于 vim
区分命令模式和编辑模式, 而咱们的 REPL
区其实就是一个 vim
编辑缓冲区(相似于 Emacs
下的 buffer
的概念), 所以, 若是咱们想要在 REPL
区输入什么表达式, 须要先切换到插入模式(按 i
), 而后再输入要求值的表达式,显示以下:
26 CL-USER> (+ 123 345) 27 468 28 CL-USER>
很好, 成功了,很是漂亮, 先切换回命令状态(快捷键 Esc
), 再切换回代码编辑区(C-w w
), 试试看能不能把代码编辑区的代码片断经过快捷键发送到 REPL
区求值, 把光标挪到一个表达式上, 而后按下快捷键: 逗号 小写英文字母e
(,e
), 很好, 发送过去了,求值成功了!
28 CL-USER> (print "hh") 29 "hh" 30 CL-USER> REPL ----------------------- 1 (+ 1 2) 2 3 (format t "hello") 4 5 (print "hh") 6 7 (make-hash-table) 8 9 (defun hello () 10 (print "hello,world") 11 )
上半部分是 REPL
区,下半部分是代码编辑区
再试试对函数定义的求值, 快捷键 逗号 小写英文字母d
(,d
), 继续成功,以下:
30 CL-USER> (defun hello () 31 (print "hello,world") 32 ) 33 HELLO 34 CL-USER> REPL ------------------------- 1 (+ 1 2) 2 3 (format t "hello") 4 5 (print "hh") 6 7 (make-hash-table) 8 (defun hello () 9 (print "hello,world") 10 )
slimv
号称是世界上对 slime
函数支持最全面的 vim
实现, 没有之一, 那么咱们看看它究竟支持哪些 slime
的函数:
注意:
slimv
默认设置vim
的<leader>
键为逗号
(,
), 因此你的.vimrc
中就不要对<leader>
另外定义了.
---- *slimv-keyboard* The default keybindings (|g:slimv_keybindings|=1) and another easy to remember built-in keybinding set (|g:slimv_keybindings|=2) for Slimv are the following. Please note that the leading ',' key below refers to <Leader>, which is set by Slimv to ',' by default (see |g:slimv_leader|). In the graphical menu the currently active keyboard shortcuts are displayed beside the menu item names, so one can refer to the GUI menu as a quick reference for the keymappings. Vim defines timeout values for mapped key sequences. If you find that Vim does not allow you enough time between pressing ',' and the last key(s) of the sequence, then you may want to fine tune these Vim options: |timeout|, |ttimeout|, |timeoutlen|, |ttimeoutlen|. Set#1 Set#2 Command --------------------------------------------------- ,, ,, Slimv Menu Edit commands (Insert mode): <C-X>0 Close Form <Tab> Complete Symbol <Space> Function Arglist Edit commands (Normal mode): ,) ,tc Close Form ,( ,(t Paredit Toggle Evaluation commands: ["x],d ["x],ed Eval Defun (current top level form) [put in register x] ["x],e ["x],ee Eval Current Expression (current subform) [put in reg. x] ["x],r ["x],er Eval Region (visual selection) [or text from register x] ,b ,eb Eval Buffer ,v ,ei Interactive Eval (evaluates in frame when in SLDB) ,u ,eu Undefine Function Debug commands: ,1 ,m1 Macroexpand-1 ,m ,ma Macroexpand All ,t ,dt Toggle Trace ,T ,du Untrace All ,B ,db Set Breakpoint ,l ,dd Disassemble ,i ,di Inspect (inspects in frame when in SLDB) ,a ,da Abort ,q ,dq Quit to Toplevel ,n ,dc Continue ,H ,dl List Threads ,K ,dk Kill Thread ,G ,dg Debug Thread Compile commands: ,D ,cd Compile Defun ,L ,cl Compile and Load File ,F ,cf Compile File ["x],R ["x],cr Compile Region [or text from register x] Cross Reference commands ,xc ,xc Who Calls ,xr ,xr Who References ,xs ,xs Who Sets ,xb ,xb Who Binds ,xm ,xm Who Macroexpands ,xp ,xp Who Specializes ,xl ,xl List Callers ,xe ,xe List Callees Profile commands: ,p ,pp Toggle Profile ,B ,pb Profile by Substring ,U ,pa Unprofile All ,? ,ps Show Profiled ,o ,pr Profile Report ,x ,px Profile Reset Documentation commands: ,s ,ds Describe Symbol ,A ,da Apropos ,h ,dh Hyperspec ,] ,dt Generate Tags Repl commands: ,c ,rc Connect to Server ,y ,ri Interrupt Lisp Process Set#1 Set#2 Command --------------------------------------------------- ,\ ,\ REPL Menu (separate menu, valid only for the REPL buffer) REPL menu commands: ,. ,rs Send Input ,/ ,ro Close and Send Input ,g ,rp Set Package <C-C> <C-C> Interrupt Lisp Process ,<Up> ,rp Previous Input ,<Down> ,rn Next Input ,- ,- Clear REPL Note: Some mappings accept an optional "x prefix (where x is a register name) similarly to Vim's p (put) and y (yank) commands. These commands may additionally use the given Vim register to store or retrieve text. Commands "Eval Defun" and "Eval Current Expression" also store the form being evaluated in the given register. When using uppercase register name, the current form is appended to the contents of the register. Commands "Eval Region" and "Compile Region" use the contents of the given register (instead of the selected region) for evaluation or compilation. This feature may be used for remembering and recalling a test form used for testing parts of the code.
洋洋洒洒真是很多, 稍微试验几个, 发现确实支持, 简直太好了, 看来咱们想在纯文本界面的 vim
下使用全功能的 slime
大有但愿!
目前为止, 咱们已经完美验证了原先的想法: 在纯文本界面下用 tmux
启动 swank
服务端, 并经过 slimv
链接到 swank
, 而后对新建的 REPL
区进行求值试验, 一切都很完美, 剩下的就工做是把咱们的验证成果转化为配置文件, 让它们应用起来!
明天继续...