Vim 下使用 Slimv(類似Slime) 輕鬆除錯 Common Lisp
Vim 下使用 Slimv(類似Slime) 輕鬆除錯 Common Lisp
目錄
- 前情回顧
- 安裝slimv
- 資料配置
- 預設快捷鍵
- 實戰演練
前情回顧
在上一篇文章想法驗證:超輕量級全功能純文字介面 REPL 類語言 IDE: Vim+Tmux+Slimv中我們對於在 tmux
中新建視窗執行 swank
服務端的想法經過了手工驗證, 證明了我們的想法是可行的, 本文則完成實際的配置, 把所有的配置資訊都寫入到配置檔案中.
安裝slimv
如果你看過上一篇文章並且照著做了, 那你的 slimv
已經安裝好了. 如果沒有安裝的話可以按照下面的操作來安裝:
我們繼續通過 pathogen
來管理 slimv
外掛, 也就是說, 只要進入 .vim/bundle/
目錄下, 把 slimv
用 git
克隆進去, 暫時不做配置, 因為我們要手動進行試驗, 安裝命令如下:
cd ~/.vim/bundle/
git clone
安裝就這麼簡單, 如果對於 pathogen
的安裝有不清楚的地方可以看看本系列第一篇文章裡的描述超輕量級純文字介面 REPL 類語言 IDE.
接下來就是資料配置了.
資料配置
Linux 和 OSX 平臺下的配置
主要是對 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
還有 ecl
的配置命令:
" 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"'
" slimv for ecl
let g:slimv_swank_cmd = '! tmux new-window -d -n REPL-ECL "ecl -load ~/.vim/bundle/slimv/slime/start-swank.lisp"'
Win32 平臺下的配置
在 Win32
下不使用 tmux
, 直接按照官方配置文件的配置方法配置就可以了, 需要正確指定兩個目錄, 一個是 Common Lisp
安裝目錄, 一個是 slimv
安裝目錄
- Common Lisp 安裝目錄:
c:/Program Files/Lisp Cabinet/bin/ccl/
- Slimv 安裝目錄:
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
注意前導鍵 預設設定為逗號(,), 當然你可以改為其他鍵, 設定全域性變數為:
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
實戰演練
REPL 區基本操作
首先要說說 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/src/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
現在返回了作為引數輸入的字元的莫爾斯程式碼串.
截圖不完整, 後面補
相關文章
- .NET中使用DebuggerDisplay輕鬆定製除錯除錯
- Mac計算機上如何輕鬆查詢和刪除類似照片Mac計算機
- 十個vim快捷鍵,讓你的使用更輕鬆
- VSCode for Mac 搭建 Common Lisp 開發環境VSCodeMacLisp開發環境
- 【譯】在除錯時輕鬆導航程式碼委託除錯
- 輕鬆學會原始碼編譯Vim 8.0原始碼編譯
- 輕鬆兩步,搭建斷點除錯 PHP 原始碼環境斷點除錯PHP原始碼
- 寫了一個 SRE 除錯工具,類似一個小木馬除錯
- 從命令列輕鬆將文字片段上傳到類似 Pastebin 的服務中命令列AST
- 有了這個視覺化外掛,刷題除錯更輕鬆視覺化除錯
- 超輕巧modbus除錯助手使用說明除錯
- MySql輕鬆入門系列——第二站 使用visual studio 對mysql進行原始碼級除錯MySql原始碼除錯
- Common Lisp物件系統是現存最好的物件系統? - mendhekarLisp物件
- 輕鬆使用Aspire rabbitmq frameworkMQFramework
- 輕鬆學Pytorch-使用ResNet50實現影像分類PyTorch
- JS輕應用熱更新 - 無需連線輕鬆進行嵌入式裝置開發除錯JS除錯
- 請教:vim選中多個單詞,類似 vscode 的ctrl+dVSCode
- windows下搭建lisp環境WindowsLisp
- Mac 下使用 clion 除錯 PHP 核心原始碼Mac除錯PHP原始碼
- Python 程式碼除錯—使用 pdb 除錯Python除錯
- Chrome瀏覽器除錯移動端網頁,測試人員也可以輕鬆debugChrome瀏覽器除錯網頁
- 還在被大媽靈魂拷問?使用Python輕鬆完成垃圾分類!Python
- 輕鬆玩轉Python檔案操作:移動、刪除Python
- Downie 4:輕鬆下載,暢享影片
- 輕鬆使用 Linux Equinox 桌面環境LinuxUI
- 使用 `useAppConfig` :輕鬆管理應用配置APP
- vscode使用chrome除錯報錯VSCodeChrome除錯
- 輕輕鬆鬆實現本地和雲主機之間的檔案上傳下載
- 使用VuePress搭建一個類似element的文件Vue
- Linux下的除錯工具Linux除錯
- Windows 下如何除錯 PowerShellWindows除錯
- iOS 輕鬆使用 App 資料統計iOSAPP
- 輕鬆在 Go 中使用 Dot 解析域名Go
- 使用 Eloquent 輕鬆搜尋多個模型模型
- linux 下vim中關於刪除某段,某行,或全部刪除的命令Linux
- 【轉】Lisp 已死,Lisp 萬歲!Lisp
- win10下使用doskey在cmd中建立類似於linux中alias的巨集Win10Linux
- 20 行程式碼:Serverless 架構下用 Python 輕鬆搞定影像分類和預測行程Server架構Python
- 使用KubernetesIngress來實現類似Istio條件路由路由