在上一篇文章想法验证:超轻量级全功能纯文本界面 REPL 类语言 IDE: Vim+Tmux+Slimv中咱们对于在 tmux
中新建窗口运行 swank
服务端的想法通过了手工验证, 证实了咱们的想法是可行的, 本文则完成实际的配置, 把全部的配置信息都写入到配置文件中.html
若是你看过上一篇文章而且照着作了, 那你的 slimv
已经安装好了. 若是没有安装的话能够按照下面的操做来安装:git
咱们继续经过 pathogen
来管理 slimv
插件, 也就是说, 只要进入 .vim/bundle/
目录下, 把 slimv
用 git
克隆进去, 暂时不作配置, 由于咱们要手动进行试验, 安装命令以下:express
cd ~/.vim/bundle/ git clone
安装就这么简单, 若是对于 pathogen
的安装有不清楚的地方能够看看本系列第一篇文章里的描述超轻量级纯文本界面 REPL 类语言 IDE.小程序
接下来就是数据配置了.vim
主要是对 vim
的配置, 由于咱们要从vim
中启动 slimv
和 swank
, 只要在你原来的 .vimrc
配置文件中加入以下内容便可:浏览器
"Set mapleader let mapleader = "," " slimv for clisp let g:slimv_swank_cmd = '! tmux new-window -d -n REPL-CLISP "clisp -i ~/.vim/bundle/slimv/slime/start-swank.lisp"'
上面的配置调用了 clisp
, sbcl
和 ccl
的配置分别为:sass
" slimv for sbcl let g:slimv_swank_cmd = '! tmux new-window -d -n REPL-SBCL "sbcl --load ~/.vim/bundle/slimv/slime/start-swank.lisp"'
" slimv for ccl let g:slimv_swank_cmd = '! tmux new-window -d -n REPL-CCL "ccl -l ~/.vim/bundle/slimv/slime/start-swank.lisp"'
在 Win32
下不使用 tmux
, 直接按照官方配置文档的配置方法配置就能够了, 须要正确指定两个目录, 一个是 Common Lisp
安装目录, 一个是 slimv
安装目录bash
c:/Program Files/Lisp Cabinet/bin/ccl/
c:/Program Files/Lisp Cabinet/site/lisp/slime
配置命令以下:服务器
let g:slimv_swank_cmd = '!start "c:/Program Files/Lisp Cabinet/bin/ccl/wx86cl.exe" -l "c:/Program Files/Lisp Cabinet/site/lisp/slime/start-swank.lisp"'
还有一个好消息就是咱们对 slimv
的数据配置跟原来的 vim-slime
的配置不冲突, 因此这两个插件的功能你能够同时使用, 只要经过不一样的快捷键调用便可.网络
官网的文档里给出了以下快捷键:
---- *slimv-keyboard* 有两套快捷键可供选择, 默认快捷键绑定第一套, 设置变量为: g:slimv_keybindings=1 第二套设置变量为: g:slimv_keybindings=2 注意前导键 <leader> 默认设置为逗号(,), 固然你能够改成其余键, 设置全局变量为: g:slimv_leader 在图形界面下每一个菜单项都会列出对应的快捷键, 不过咱们是文本界面, 就没有这个福利了. vim 定义了快捷键序列的超时值, 若是你以为本身手速慢, 来不及在规定的超时时间内输完长长的快捷键序列, 那么你也能够本身设置一下相关的超时时间, 直接设置 vim 里对应的这几个参数好了: timeout ttimeout timeoutlen ttimeoutlen 下面就是具体的快捷键了, Set#1 表明第一套, Set#2 表明第二套, Command 表明该快捷键对应的命令. Set#1 Set#2 Command --------------------------------------------------- ,, ,, Slimv 菜单 编辑命令 (Insert 模式): <C-X>0 关闭形式 <Tab> 自动补全输入的符号 <Space> 函数参数列表 编辑命令 (Normal 模式): ,) ,tc 关闭形式 ,( ,(t 括号自动成对开关 求值命令: ["x],d ["x],ed 求值 Defun (当前顶层) [放到寄存器 register x] ["x],e ["x],ee 求值当前表达式 (当前子形式) [放到寄存器 reg. x] ["x],r ["x],er 求值区域 (visual 选择) [或者来自 register x 的文本] ,b ,eb 求值缓冲区内全部内容 ,v ,ei 交互求值 (evaluates in frame when in SLDB) ,u ,eu 未定义函数求值 调试命令: ,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 编译命令: ,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] 交叉引用命令: ,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 性能测量命令: ,p ,pp Toggle Profile ,B ,pb Profile by Substring ,U ,pa Unprofile All ,? ,ps Show Profiled ,o ,pr Profile Report ,x ,px Profile Reset 文档命令: ,s ,ds Describe Symbol ,A ,da Apropos ,h ,dh Hyperspec ,] ,dt Generate Tags Repl 命令: ,c ,rc Connect to Server ,y ,ri Interrupt Lisp Process Set#1 Set#2 Command --------------------------------------------------- ,\ ,\ REPL 菜单 (独立菜单, 仅在 REPL 缓冲区有效) REPL 菜单命令: ,. ,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
这些命令确实丰富, 基本上调试程序是够用了, 实在不够用的话也能够在 REPL
区本身手动输入相关的调试命令, 稍微麻烦一些而已.
剩下的部分咱们用一个实例研演示一下这个超轻量级全功能纯文本界面的 REPL
开发环境有哪些功能, 主要参考自 slimv
的官方教程一, 二, 三:
Slimv Tutorial - Part One Slimv Tutorial - Part Two Slimv Tutorial - Part Three
首先要说说 paredit
这个插件的效果, 它默认是打开的, 最简单就是自动为你补全括号, 好比你输入一个左括号 (
, 它会自动补全一个右括号 )
, 控制开关在这里, .vimrc
中增长:
let g:paredit_mode=0
它还有个功能叫 electric return
, 当你输入回车时, 会插入新行, 控制开关以下:
let g:paredit_electric_return=0
其次是 Common Lisp
中的几个快捷键, 在 REPL
区使用:
*
, **
, ***
:
能够获得 REPL
区上一次对象求值结果
+
, ++
, +++
:
能够获得 REPL
区上一次求值的形式(表达式)
效果以下:
90 CL-USER> (+ 123 345) 91 468 92 CL-USER> * 93 468 94 CL-USER> ** 95 468 96 CL-USER> *** 97 468 98 CL-USER> + 99 *** 100 CL-USER> ++ 101 *** 102 CL-USER> (+ 123 345) 103 468 104 CL-USER> + 105 (+ 123 345) 106 CL-USER> ++ 107 (+ 123 345) 108 CL-USER> REPL =============
另外也支持历史命令查看: 能够在 Insert
模式下使用上下键
先在 ~/.vimrc
配置文件中打开 rainbow-parentheses
, 用下面这条语句:
let g:lisp_rainbow=1
这样你在编辑 lisp
文件时就会发现你的不一样层次的括号对会呈现不一样的颜色, 同一层次的括号对会使用相同的颜色, 效果是这样:
用 vim
创建一个新文件, 命令以下:
vi ~/code-staff/morse.lisp
下面这是一个典型的显示界面, 上半部分是 REPL
区, 下半部分是编辑区:
3 CL-USER> ~ ~ ~ REPL 1 (defpackage :morse 2 (:use :common-lisp) 3 ) 4 5 (in-package :) ~ ~ ~/code-staff/morse.lisp [+] (in-package PACKAGE-NAME) [0] 1:bash 2:vim* 3:bash 4:bash 5:bash- 6:REPL-CLISP "Air.local" 19:45 31- 8-15
最下面一行[0] 1:bash 2:vim* 3:bash 4:bash 5:bash- 6:REPL-CLISP "Air.local" 19:45 31- 8-15
是 tmux
的显示信息; 倒数第二行 (in-package PACKAGE-NAME)
是把光标放在编辑区的 in-package
上时 vim
给出的函数参数信息提示; 倒数第三行 ~/code-staff/morse.lisp [+]
是 vim
状态栏显示的编辑区信息.
截图以下:
把光标移动到 defpackage
上, 进入命令模式:
输入 ,s
, 就能够查看 defpackage
的详细的信息;
输入 ,h
打开默认浏览器, 查看 HyperSpec
中对 defpackage
的定义;
输入 ,A
在 REPL
区调用 (apropos "defpackage")
;
输入 ,]
增长标签(须要事先安装好 ctags
插件)
执行 ,A
的结果:
10 CL-USER> (apropos "defpackage") 11 DEFPACKAGE macro 12 COMMON-LISP::DEFPACKAGE-MODERNIZE 13 COMMON-LISP::DEFPACKAGE-RECORD-SYMNAME 14 ; No value 15 CL-USER>
执行 ,s
的结果:
~/code-staff/morse.lisp [+] DEFPACKAGE is the symbol DEFPACKAGE, lies in #<PACKAGE COMMON-LISP>, is accessible in 19 packages CLOS, COMMON-LISP, COMMON-LISP-USER, EXPORTING, EXT, POSIX, PXREF, REGEXP, SCREEN, SWANK, SWANK-LOADER, SWANK-MONITOR, SWANK-REPL, SWANK/BACKEND, SWANK/CLISP, SWANK/GRAY, SWANK/MATCH, SWANK/RPC, SYSTEM, names a macro, has 1 property SYSTEM::DOCHTTP/1.1 404 Not FoundHTTP/1.1 200 OK . ANSI-CL Documentation is at "http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/mac_defpackage.html"HTTP/1.1 301 Moved PermanentlyHTTP/1.1 200 OK CLISP Documentation is at "http://clisp.cons.org/impnotes/pack-intro.html#defpack" For more information, evaluate (SYMBOL-PLIST 'DEFPACKAGE). #<PACKAGE COMMON-LISP> is the package named COMMON-LISP. It has 2 nicknames LISP, CL. It imports the external symbols of 1 package CLOS and exports 978 symbols to 18 packages SWANK-REPL, SWANK, SWANK/RPC, SWANK/MATCH, SWANK/GRAY, SWANK/CLISP, SWANK-MONITOR, PXREF, SWANK/BACKEND, SWANK-LOADER, REGEXP, POSIX, EXPORTING, SCREEN, CLOS, COMMON-LISP-USER, EXT, SYSTEM. #<MACRO #<COMPILED-FUNCTION DEFPACKAGE> (&WHOLE SYSTEM::WHOLE-FORM SYSTEM::PACKNAME &REST SYSTEM::OPTIONS)> is a macro expander. Argument list: (&WHOLE SYSTEM::WHOLE-FORM SYSTEM::PACKNAME &REST SYSTEM::OPTIONS) For more information, evaluate (DISASSEMBLE (MACRO-FUNCTION 'DEFPACKAGE)). Documentation: SYSTEM::IMPNOTES: "pack-intro.html#defpack" CLHS: "Body/mac_defpackage.html" SYSTEM::FILE: ((SYSTEM::DEFUN/DEFMACRO #P"/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_tarballs_ports_lang_clisp/clisp/work/clisp-2.49/s rc/defpackage.fas" 11 202)) Press ENTER or type command to continue
如今开始调试咱们的小程序, 先求值第一个形式, 把光标放在 (defpackage ...)
形式体内任何地方, 而后输入 ,d
, 咱们的这个形式体就被发送到 REPL
而且完成求值, 这个命令会求值顶层的形式, 结果以下:
15 CL-USER> (defpackage :morse 16 (:use :common-lisp) 17 ) 18 #<PACKAGE MORSE> 19 CL-USER>
如今再把光标移到 (in-package ...)
内而且输入 ,e
, 这个命令将会在 REPL
缓冲区求值当前的 S-表达式
, 结果以下:
19 CL-USER> (in-package :morse) 20 #<PACKAGE MORSE> 21 CL-USER>
咱们能够在 REPL
输入 (find-package :morse)
来检查是否生效, 还能够输入 ,g
把当前包设置为 :morse
而且进入该包, 这个改变会经过 REPL
提示符的变化(变为 morse
)以及变量 *package*
反映出来:
30 #<PACKAGE MORSE> 31 CL-USER> 32 MORSE>*package* 33 #<PACKAGE MORSE> 34 MORSE>
如今让咱们加入莫尔斯码映射函数, 在咱们输入 defparameter
和 空格
后, 函数参数列表会出如今状态栏. 这个功能对于全部用户定义的函数也有效, 不只仅是那些内建函数.
5 (in-package :morse) 6 (defparameter ) ~ ~ ~/code-staff/morse.lisp [+] (defparameter &WHOLE WHOLE-FORM SYMBOL INITIAL-VALUE &OPTIONAL DOCSTRING) [0] 1:bash 2:vim* 3:bash 4:bash 5:bash- 6:REPL-CLISP
如今开始填充莫尔斯映射表, 能够从网络上搜索到, 这里能够对代码进行自动缩进, 选择好区域后按 =
(貌似这里个人表现跟教程的不太一致,先写, 后面再找缘由)
5 (in-package :morse) 6 (defparameter *morse-mapping* 7 '((#\A ".-") 8 (#\B "-...") 9 (#\C "-.-.") 10 (#\, "--..--") 11 (#\? "..--..") 12 ) 13 ) 14 15 (defun character-to-morse (character) 16 (assoc character *morse-mapping* :test #'char-equal) 17 ) 18 ~
而后咱们意识到咱们只须要返回值的第二部分, 因此咱们须要把 cdr
放在 (assoc ...)
前面,可是由于有 paredit
的缘故,咱们没法输入一个单独的左括号 (
, 由于它会自动输入成对的括号 ()
, 把光标移到最前面的左括号, 也就是这个 (assoc
, 而后按下 ,w
或 ,W
(在咱们的环境下大写 W
有效, 小写无效), 它会在 S-表达式
外面用一对新括号把表达式括起来(paredit wrap
), 如今咱们就能够输入 cdr
了:
13 (defun character-to-morse (character) 14 (cdr (assoc character *morse-mapping* :test #'char-equal)))
paredit wrap
的相反操做是 splice
, 经过按下 ,s
, 它会删除掉最外层的括号, 还有一些相似的命令:
,o
切分S-表达式 Split S-expression,J
加入S-表达式 Join S-expression,I
提高子形式 Raise subform,<
括号左移 Move left,>
括号右移 Move right如今编译咱们的代码, 输入 ,D
, 咱们还能够编译和加载整个代码源文件:
,F
编译整个文件,L
编译而且加载整个文件结果以下:
42 MORSE> 43 44 Compilation finished. (No warnings) [0.003131000092253089 secs] 45 46 MORSE> 47 48 Compilation finished. (No warnings) [0.002271000063046813 secs] 49 50 MORSE> ;; Compiling file /Users/admin/code-staff/morse.lisp ... 51 ;; Wrote file /Users/admin/code-staff/morse.fas 52 0 errors, 0 warnings 53 MORSE> 54 55 Compilation finished. (No warnings) [0.03273700177669525 secs] 56 57 MORSE>
如今是时候测试一下咱们的 character-to-morse
函数了, 输入 C-w w
从代码编辑区切换到 REPL
缓冲区, 输入 char
接着按下 Tab
键, 你将会看到弹出一个可能的自动完成列表, 截图以下:
若是你继续输入更多字符, 弹出菜单中的选项会自动缩小范围匹配, 截图以下:
默认调用的方法是模糊补全 fuzzy completion
, 所以你甚至能够输入 ctm
再按 Tab
(ctm 是 character-to-morse 的首字母)
这种补全方法在 REPL
缓冲区也不受限制, 在代码编辑区它以一样的方式工做, 直到 slimv
链接到 swank
服务器上.
顺便说一句, 还有另外一种 vim
的自动补全, 经过按 C-p
和 C-n
, 这种补全方式会在当前缓冲区查找相同的单词前缀, 这种方式对于补全那些不是符号名的单词比较有用, 好比注释或者字符串里的某些文本.
Ctrl p
向前查找Ctrl n
向后查找咱们选择了正确的补全完成函数调用:
98 MORSE> (character-to-morse #\a) 99 (".-") 100 MORSE> (character-to-morse #\b) 101 ("-...") 102 MORSE> (character-to-morse #\c) 103 ("-.-.") 104 MORSE>
咱们获得的是一个列表, 里面包含一个字符串, 可是咱们须要的结果是一个字符串, 咱们意识到咱们应该用 second
来代替函数中的 cdr
, 所以咱们相应地修改代码而且按下 ,d
从新求值这个 defun
13 (defun character-to-morse (character) 14 (second (assoc character *morse-mapping* :test #'char-equal)))
切换回 REPL
缓冲区, 在 Insert
模式下按下 向上
箭头来从新调用最后一条命令, 而后输入回车求值:
104 MORSE> (defun character-to-morse (character) 105 (second (assoc character *morse-mapping* :test #'char-equal))) 106 CHARACTER-TO-MORSE 107 MORSE> (character-to-morse #\c) 108 "-.-." 109 MORSE>
好极了, character-to-morse
如今返回了做为参数输入的字符的莫尔斯代码串.
截图不完整, 后面补