Alive extension は VSCode を強力な Common Lisp development platform にします。 target platform 上で動作する Common Lisp の version 以外に dependency はありません。現在は次を support しています。
- Syntax highlighting
- Code completion
- Code formatter
- Jump to definition
- Snippets
- REPL integration
- Interactive Debugger
- REPL history
- Inline evaluation
- Macro expand
- Disassemble
- Inspector
- Hover Text
- Rename function args and let bindings
- Code folding

Prerequisites
VSCode の Alive extension は ANSI Common Lisp と互換性があり、Alive REPL が正常に起動する限り、これらの手順はどの実装でも動くはずです。例ではすべて SBCL を使います。
- VsCode。command line が install されており、 Alive extension が動作しているもの。
- SBCL
VSCode を REPL に接続する

- VSCode 内で、編集したい lisp file を開きます。
- まだない場合は、
hello.lispという新しい file を作成します。
- まだない場合は、
- VSCode 内で、上部 menu の
View/Command Paletteから Command Palette を開き、Alive: Start REPL And Attachを選んで、VSCode REPL に attach された Swank server を動かす SBCL instance を起動します。REPL Connectedと書かれた小さな window が pop up します。REPL Connectedmessage が出ない場合は、上部 menu のView:Outputから VSCode の Output を開き、pulldown でSwank Traceを選びます。この output は実行中の lisp image からの output で、何がうまくいっていないのかを調べる出発点になります。
これで、稼働中の SBCL image の port 4005 で動く Swank server に attach された REPL を持つ VSCode instance ができました。file 内の statement を evaluate でき、それらは実行中の SBCL instance で処理されます。
REPL を disconnect し、SBCL instance を shut down するには、上部 menu の View/Command
Palette から Command Palette を開き、Alive: Detach from REPL を選びます。
すべての操作には keybinding があります。必要に応じて explore し、変更してください。
Recipes
特に明記しない限り、すべての recipe は、VSCode で file を開き、REPL が attach されている状態を前提とします。
expression を evaluate するときは、evaluate したい s-expression の中、または直後のどこかに cursor を置いて、evaluate する expression を選びます。
statement を in-line で evaluate する

- editor window の開いている file に、次を入力します。
(+ 2 2)
- 上部 menu の
View/Command Paletteから Command Palette を開き、Alive: Inline Evalを選びます。 -
=> 4 (3 bits, #x4, #o4, #b100)と書かれた小さな pop up が表示されます。これが result です。statement を in-line で evaluate することは、それを REPL に送ることとまったく同じです。違いは表示方法だけです。
statement を evaluate する

- editor window の開いている file に、次を入力します。
(+ 2 2)
- 上部 menu の
View/Command Paletteから Command Palette を開き、Alive: Send To REPLを選びます。 - expression が REPL に表示され、result も一緒に表示されます。
CL-USER>
(+ 2 2)
4
CL-USER>
file を compile する

- editor window の開いている file に、次を入力します。
(+ 2 2)
- 上部 menu の
View/Command Paletteから Command Palette を開き、Alive: Compileを選びます。 - repl に compile の詳細が表示され、filesystem に fasl file ができます。
CL-USER>
; compiling file "/Users/jason/Desktop/hello.lisp" (written 14 SEP 2021 04:24:37 AM):
; wrote /Users/jason/Desktop/hello.fasl
; compilation finished in 0:00:00.001
Interactive Debugger を使って abort する

- editor window の開いている file に、次を入力します。
(defun divide (x y)
(/ x y))
- まだそうなっていなければ、最後の parenthesis の後に cursor を置きます。上部 menu の
View/Command Paletteから Command Palette を開き、Alive: Inline Evalを選んで、definefunction を image に load します。 - 開いている file に新しい行を追加し、次を入力します。
(divide 1 0)
- まだそうなっていなければ、最後の parenthesis の後に cursor を置きます。上部 menu の
View/Command Paletteから Command Palette を開き、Alive: Inline Evalを選んで、divide function を image 内で実行します。 - Interactive Debugger が pop up します。
Restartssection で、option 2 を選んで Abort します。 - editor とまだ動いている REPL に戻り、何も起きなかったかのように続けられます。
Interactive Debugger を使って runtime に問題を修正する

- editor window の開いている file に、次を入力します。
(defun divide (x y)
(assert (not (zerop y))
(y)
"The second argument can not be zero.")
(/ x y))
- まだそうなっていなければ、最後の parenthesis の後に cursor を置きます。上部 menu の
View/Command Paletteから Command Palette を開き、Alive: Inline Evalを選んで、definefunction を image に load します。 - 開いている file に新しい行を追加し、次を入力します。
(divide 1 0)
- まだそうなっていなければ、最後の parenthesis の後に cursor を置きます。上部 menu の
View/Command Paletteから Command Palette を開き、Alive: Inline Evalを選んで、divide function を image 内で実行します。 - Interactive Debugger が pop up します。
Restartssection で、option 0 の “Retry assertion with new value for Y” を選びます。 - popup menu に
y'と入力します。 - 次の popup menu に
1と入力します。 => 1 (1 bit, #x1, #o1, #b1)と書かれた小さな pop up が表示されるはずです。これは新しい value の result です。debugger へ crash した後、crash の原因になった value を変更させてもらい、悪い0value を入力しなかったかのように proceeding した状態で、editor とまだ動いている REPL に戻っています。
debugger でできることのさらなる idea は error handling page にあります。
macro を expand する

- editor window の開いている file に、次を入力します。
(loop for x in '(a b c d e) do
(print x))
- まだそうなっていなければ、最後の parenthesis の後に cursor を置きます。上部 menu の
View/Command Paletteから Command Palette を開き、Alive: Macro Expandを選んで for-loop macro を expand します。 - 次のようなものが見えるはずです。
(BLOCK NIL
(LET ((X NIL)
(#:LOOP-LIST-559
(SB-KERNEL:THE* (LIST :USE-ANNOTATIONS T
:SOURCE-FORM '(A B C D E))
'(A B C D E))))
(DECLARE (IGNORABLE #:LOOP-LIST-559)
(IGNORABLE X))
(TAGBODY
SB-LOOP::NEXT-LOOP
(SETQ X (CAR #:LOOP-LIST-559))
(SETQ #:LOOP-LIST-559 (CDR #:LOOP-LIST-559))
(PRINT X)
(IF (ENDP #:LOOP-LIST-559)
(GO SB-LOOP::END-LOOP))
(GO SB-LOOP::NEXT-LOOP)
SB-LOOP::END-LOOP)))
function を disassemble する

- editor window の開いている file に、次を入力します。
(defun hello (name)
(format t "Hello, ~A~%" name))
- まだそうなっていなければ、最後の parenthesis の後に cursor を置きます。上部 menu の
View/Command Paletteから Command Palette を開き、Alive: Inline Evalを選んで function を image に load します。 - まだそうなっていなければ、最後の parenthesis の後に cursor を置きます。上部 menu の
View/Command Paletteから Command Palette を開き、Alive: Disassembleを選んで compiled function の machine code を print します。 - 次のように始まります。
; disassembly for HELLO
; Size: 172 bytes. Origin: #x70052478B4 ; HELLO
; 8B4: AC0A40F9 LDR R2, [THREAD, #16] ; binding-stack-pointer
; 8B8: 4C0F00F9 STR R2, [CFP, #24]
; 8BC: AC4642F9 LDR R2, [THREAD, #1160] ; tls: *STANDARD-OUTPUT*
; 8C0: 9F8501F1 CMP R2, #97
; 8C4: 61000054 BNE L0
; 8C8: 4AFDFF58 LDR R0, #x7005247870 ; '*STANDARD-OUTPUT*
; 8CC: 4C1140F8 LDR R2, [R0, #1]
; 8D0: L0: 4C1700F9 STR R2, [CFP, #40]
; 8D4: E0031BAA MOV NL0, CSP
; 8D8: 7A0701F8 STR CFP, [CSP], #16
; 8DC: EAFCFF58 LDR R0, #x7005247878 ; "Hello, "
; 8E0: 4B1740F9 LDR R1, [CFP, #40]
; 8E4: B6FBFF58 LDR LEXENV, #x7005247858 ; #<SB-KERNEL:FDEFN WRITE-STRING>
; 8E8: 970080D2 MOVZ NARGS, #4
; 8EC: FA0300AA MOV CFP, NL0
; 8F0: DE9240F8 LDR LR, [LEXENV, #9]
; 8F4: C0033FD6 BLR LR
; 8F8: 3B039B9A CSEL CSP, OCFP, CSP, EQ
; 8FC: E0031BAA MOV NL0, CSP
; 900: 7A0701F8 STR CFP, [CSP], #16
; 904: 4A2F42A9 LDP R0, R1, [CFP, #32]
; 908: D6FAFF58 LDR LEXENV, #x7005247860 ; #<SB-KERNEL:FDEFN PRINC>
; 90C: 970080D2 MOVZ NARGS, #4
; 910: FA0300AA MOV CFP, NL0
; 914: DE9240F8 LDR LR, [LEXENV, #9]
; 918: C0033FD6 BLR LR
; 91C: 3B039B9A CSEL CSP, OCFP, CSP, EQ
; 920: E0031BAA MOV NL0, CSP
; 924: 7A0701F8 STR CFP, [CSP], #16
; 928: 2A4981D2 MOVZ R0, #2633
; 92C: 4B1740F9 LDR R1, [CFP, #40]
; 930: D6F9FF58 LDR LEXENV, #x7005247868 ; #<SB-KERNEL:FDEFN WRITE-CHAR>
; 934: 970080D2 MOVZ NARGS, #4
; 938: FA0300AA MOV CFP, NL0
; 93C: DE9240F8 LDR LR, [LEXENV, #9]
; 940: C0033FD6 BLR LR
; 944: 3B039B9A CSEL CSP, OCFP, CSP, EQ
; 948: EA031DAA MOV R0, NULL
; 94C: FB031AAA MOV CSP, CFP
; 950: 5A7B40A9 LDP CFP, LR, [CFP]
; 954: BF0300F1 CMP NULL, #0
; 958: C0035FD6 RET
; 95C: E00120D4 BRK #15 ; Invalid argument count trap
Common Lisp system の skeleton を作成する

この recipe は新しい Common Lisp System を作成するため、running REPL は不要です。
- 新しい project 用に
experimentという folder を作成します。 - newly created directory で vscode を開きます。
cd experiment
code .
- 新しい Common Lisp System を作成します。
- VSCode 内で、上部 menu の
View/Command Paletteから Command Palette を開き、system skeleton を生成します:Alive: System Skeleton - 前の command は、次の directory structure を生成しているはずです。
- experiment.asd
- src/
- app.lisp
- test/
- all.lisp
- VSCode 内で、上部 menu の
それらの file の内容は次のとおりです。
experiment.asd:
(in-package :asdf-user)
(defsystem "experiment"
:class :package-inferred-system
:depends-on ("experiment/src/app")
:description ""
:in-order-to ((test-op (load-op "experiment/test/all")))
:perform (test-op (o c) (symbol-call :test/all :test-suite)))
(defsystem "experiment/test"
:depends-on ("experiment/test/all"))
(register-system-packages "experiment/src/app" '(:app))
(register-system-packages "experiment/test/all" '(:test/all))
src/app.lisp:
(defpackage :app
(:use :cl))
(in-package :app)
test/all.lisp:
(defpackage :test/all
(:use :cl
:app)
(:export :test-suite))
(in-package :test/all)
(defun test-suite ()
(format T "Test Suite~%"))
Optional Custom Configurations
Quicklisp と連携するよう VSCode Alive を configure する
quicklisp が install 済みで、init 時に load されるよう configure されていると仮定すると、quicklisp はそのまま動きます。
default context の CLPM と連携するよう VSCode Alive を configure する
CLPM が install 済みで configure 済みであると仮定し、vscode settings を変更 して次のようにします。
- VSCode settings に次を追加します。
"alive.swank.startupCommand":[
"clpm",
"exec",
"--",
"sbcl",
"--eval",
"(asdf:load-system :swank)",
"--eval",
"(swank:create-server)"
],
これは default clpm context で sbcl を起動します。
bundle clpmfile を使う CLPM と連携するよう VSCode Alive を configure する
CLPM が install 済みで configure 済みであり、 home directory の root に swank を dev dependency として含む bundle が configure されていると仮定し、vscode settings を変更して次のようにします。
- VSCode settings に次を追加します。
"alive.swank.startupCommand":[
"clpm",
"bundle",
"exec",
"--",
"sbcl",
"--eval",
"(asdf:load-system :swank)",
"--eval",
"(swank:create-server)"
],
これは bundle の clpm context で sbcl を起動します。
Roswell と連携するよう VSCode Alive を configure する
Roswell が install 済みであると仮定し、 vscode settings を変更して次のようにします。
"alive.swank.startupCommand": [
"ros",
"run",
"--eval",
"(require :asdf)",
"--eval",
"(asdf:load-system :swank)",
"--eval",
"(swank:create-server)"
]
VSCode Alive を Docker container に接続する

これらの手順は、remote connection、wsl connection、github Codespaces でも、それぞれ Remote - SSH、Remote -
WSL、Github Codespaces extension を使って動きます。extension が install されていることを前提とします。この例では、Containers extension が install 済みで configure 済み であることを確認してください。
- sbcl が install された docker image を pull します。この例では latest の clfoundations sbcl を使います。
docker pull clfoundation/sbcl
- docker image 内で bash を run し、起動して動かし続けます。
docker run -it clfoundation/sbcl bash
- VSCode Side Bar で
Remote Explorericon を click します。 - Dev Containers の list で clfoundation/sbcl を右 click し、
Attach to Containerを選びます。 - 開いた新しい VSCode window の VSCode Side Bar で、
Explorerを click します。file がまだ表示されていない場合は、container 内の file を表示するよう伝える必要があるかもしれません。 - container 内の file を表示できたら、VSCode
Side Bar内で右 click し、New Fileを選びます。file 名をhello.lispにします。 - VSCode Site Bar で
Extensionsicon を click します。 Aliveplugin のInstall in Container...button を click します。hello.lispfile を開き、この recipe の冒頭にある “Connect VSCode to a REPL” の手順に従います。- これで、docker container 内の SBCL image で動く Slime server に接続された REPL を持つ VSCode が 動いています。
Page source: ja/vscode-alive.md