文档章节

想法验证:超轻量级全功能纯文本界面 REPL 类语言 IDE: Vim+Tmux+Slimv

FreeBlues
 FreeBlues
发布于 2015/08/31 12:35
字数 2427
阅读 384
收藏 2

想法验证:超轻量级全功能纯文本界面 REPL 类语言 IDE: Vim+Tmux+Slimv

前言

之前写过一篇文章超轻量级纯文本界面 REPL 类语言 IDE, 介绍了在纯粹文本界面下如何用 Vim + Tmux + vim-slime 搭建一个超轻量级的 REPL 类语言开发环境, 配置步骤很简单, 初学者使用起来也很容易上手, 不过用过几次后发现缺憾: 这个开发环境是不是太简陋了点? 也就是比语言自带的 REPL 稍微多了个编辑区的功能, 尤其是使用过 Emacs + Slime 环境的朋友, 多么希望能在 vi 下用到类似的功能啊!

好消息是, 现在 slimv 出现了--(其实它早就出现了,只不过刚刚进入本文作者视野), 它整合了 slime 的大多数功能, 可以用于 vim 环境. 不过初步阅读文档后发现, 帮助文档里介绍的 Linux 环境下的例子都要用到 XWindows 下的 XTerm 或者 KDE 下的 konsole, 这有点背离我们希望使用纯文本界面的初衷, 毕竟我们的目标是打造一款在流畅运行在树莓派上的超轻量级开发环境, 并不希望启动笨重庞大的视窗系统来浪费资源.

怎么办? 先进行理论分析, 看看 slimv 的原理, 它其实跟 Emaca 下的 slime 一样, 使用 XTerm 的目的是为了启动一个 swank 服务端, 但是 swank 服务端是不需要视窗系统的, 可以直接在纯文本界面下用脚本来启动, 只要保持 slimvswank 版本一致, 端口号使用 slimv 默认值, 那么我们在纯文本界面下启动的 swank 服务端照样可以为 slimv 提供连接服务. 而且, Emacs + slime + Common Lisp 是可以运行于纯文本界面的, 说明从理论上讲, slimv 也应该具备这个能力.

试验1: 纯手工启动 swank.lisp 并连接

先试验一下, 因为 slimv 中服务端的程序是这个 ~/.vim/bundle/slimv/slime/start-swank.lisp 所以我们可以用任意一个 Common Lisp 实现来执行这个脚本, 这里我们先试试 CLISP, 命令为:

clisp -i ~/.vim/bundle/slimv/slime/start-swank.lisp

刷过一堆信息, 最后显示:

;; 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, 变为如下界面:

;; Swank started at port: 4005.
CL-USER>

这里其实就是经过 swank 包装的 REPL 接口, 是可以直接输入表达式求值的

CL-USER> (+ 12 34)
(+ 12 34)
46
CL-USER>

好玩吧, :)

好了, 言归正传, 继续我们的试验.

试验2: 试验在 tmux 不同的窗口启动 swank

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 函数以及默认快捷键

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 区进行求值试验, 一切都很完美, 剩下的就工作是把我们的验证成果转化为配置文件, 让它们应用起来!

明天继续...

© 著作权归作者所有

FreeBlues
粉丝 99
博文 280
码字总数 493678
作品 0
其它
程序员
私信 提问
Vim 下使用 Slimv(类似Slime) 轻松调试 Common Lisp

Vim 下使用 Slimv(类似Slime) 轻松调试 Common Lisp 目录 - 前情回顾- 安装slimv- 数据配置- 默认快捷键- 实战演练 前情回顾 在上一篇文章想法验证:超轻量级全功能纯文本界面 REPL 类语言 ID...

FreeBlues
2015/09/01
513
0
超轻量级纯文本界面 REPL 类语言 IDE

超轻量级纯文本界面 REPL 类语言 IDE 目录 介绍 特性 实现原理 安装插件 配置方法 使用说明 其他信息 介绍 这是基于 快速定制的一个针对 类编程语言的超轻量级开发环境, 不需要任何 , 运行于...

FreeBlues
2015/08/29
347
2
老猪/ScalaConsole

ScalaConsole Reloaded (V2.0) ScalaConsole 是什么 ScalaConsole是Scala语言REPL的图形界面替代者。 为什么需要 ScalaConsole 命令行REPL的编辑功能有限,只能基于行来进行编辑,如果输入错...

老猪
2015/02/11
0
0
Java9新特性之HTTP2和REPL

对Java 9的炒作将不再局限于模块化(modularity),Java 9正在搜罗大量额外的功能模块,这些功能模块正作为Java增强提案(JEP)提交,并在OpenJDK (Java SE的参考实现项目)中实现。 在这篇文...

rickiyeat
2017/09/23
0
0
Java 9 新功能之 HTTP2 和 REPL

对Java 9的炒作将不再局限于模块化(modularity),Java 9正在搜罗大量额外的功能模块,这些功能模块正作为Java增强提案(JEP)提交,并在OpenJDK (Java SE的参考实现项目)中实现。 在这篇文...

oschina
2015/08/08
9.2K
23

没有更多内容

加载失败,请刷新页面

加载更多

谁说多功能和低价格不能兼得?Aspose系列产品1024购买指南请查收!

你还在为了Word、Excel、PDF、CAD等文档格式转换而发愁吗? 你是否在寻找一款能够在应用程序中文档管理的工具呢? Aspose——支持100多种文件格式创建、编辑、转换和打印! 往下看,找一找哪...

mnrssj
28分钟前
3
0
hbase客户端API

本章介绍用于对HBase表上执行CRUD操作的HBase Java客户端API。 HBase是用Java编写的,并具有Java原生API。因此,它提供了编程访问数据操纵语言(DML)。 HBaseConfiguration类 添加 HBase 的配...

水木星辰
28分钟前
3
0
[插件化开发] 1. 初识OSGI

初识 OSGI 背景 当前product是以solution的方式进行售卖,但是随着公司业务规模的快速夸张,随之而来的是新客户的产品开发,老客户的产品维护,升级以及修改bug,团队的效能明显下降,为了解...

IsaacZhang
29分钟前
4
0
Webstorm 环境使用 nuxt.js 做开发,@ 和 ~ 别名配置

好的IDE + 好的代码提示 = 高效率的开发 webstorm 设置@和~别名,有助于代码查看和跳转. step 0 在项目下创建一个webpack.config.js,内容如下: const path = require('path')module.exp...

皇虫
33分钟前
3
0
Knative 实战:基于 Knative Serverless 技术实现天气服务-下篇

上一期我们介绍了如何基于 Knative Serverless 技术实现天气服务-上篇,首先我们先来回顾一下上篇介绍的内容: 通过高德天气 API 接口,每隔 3 个小时定时发送定时事件,将国内城市未来 3 天...

Mr_zebra
50分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部