想法驗證:超輕量級全功能純文本界面 REPL 類語言 IDE: Vim+Tmux+Slimv

想法驗證:超輕量級全功能純文本界面 REPL 類語言 IDE: Vim+Tmux+Slimv

前言

以前寫過一篇文章超輕量級純文本界面 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 服務端是不須要視窗系統的, 能夠直接在純文本界面下用腳原本啓動, 只要保持 slimvswank 版本一致, 端口號使用 slimv 默認值, 那麼咱們在純文本界面下啓動的 swank 服務端照樣能夠爲 slimv 提供鏈接服務. 並且, Emacs + slime + Common Lisp 是能夠運行於純文本界面的, 說明從理論上講, slimv 也應該具有這個能力.網絡

試驗1: 純手工啓動 swank.lisp 並鏈接

先試驗一下, 由於 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>

好玩吧, :)

好了, 言歸正傳, 繼續咱們的試驗.

試驗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 區進行求值試驗, 一切都很完美, 剩下的就工做是把咱們的驗證成果轉化爲配置文件, 讓它們應用起來!

明天繼續...

相關文章
相關標籤/搜索