Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save otaon/9bb14bb9249a1e38e90b66c45eda391b to your computer and use it in GitHub Desktop.
Save otaon/9bb14bb9249a1e38e90b66c45eda391b to your computer and use it in GitHub Desktop.
vim と slimv と roswell と swank で common lisp を書く環境を作る

本記事の位置づけ

下記を実現するための手順書。

  • roswell(lisp実行環境構築ツール)を導入する
  • slimv(VimにおけるSLIME)を導入する
  • roswellとslimvでcommon lispをコーディング、実行するための設定をする

手順一覧

下記の順番に環境構築する。

  1. roswellを導入する
  2. slimvを導入する

1. roswellを導入する

roswellとは?(require, ASDF, Quicklispとの違い)

roswellとは、Common Lispの実行環境を構築するためのユーティリティ。 内部ではquicklispを使っており、そのquicklispの内部ではASDFを使っている。 これらは混同されがちなので、下記にこれらについて他サイト様の説明を引用しながら軽く説明する。

provide, require(非推奨)

すでに使うべきではない機能であり、大体のプロジェクトではASDFを使用している。

ANSI Common Lispに存在するライブラリ管理システムです。
(require :hoge)でファイルを読み込み、そのファイルで(provide :hoge)されていれば、2回目以降の(require :hoge)では何も行われません。

これは無駄なロードを防ぐための仕組みです。
しかし、REQUIREがどこのファイルを読みにいくかは処理系の実装に依存しています。
処理系ポータブルなコードを書くには非常に不便です。

ASDF : Another System Definition Facility

ASDFは、Common Lispのソースコードをsystemとしてまとめ、ビルドし、ロードするための「モジュール管理プログラム」。

ASDFは,ローカルに存在するライブラリを,依存関係に基づいてロードします.
実際には,ロードする前にコンパイルまで行ってくれます.
依存関係を定義するファイルは.asdファイルで,通常プロジェクトトップに置かれます.

Lisp標準のrequire関数で外部ファイルをロードする際,ほとんどの処理系がASDFを用いてファイルをロードするため,ASDF自体はLisp標準規格に含まれませんが,処理系と共に予めインストールされていることが多いです.

Quicklisp

Quicklispは依存しているライブラリをウェブ上のリポジトリからダウンロード・インストールしてくれるツール。

Roswellは何かと言うと,Quicklispのようなインストーラです.
Quicklispとの違いは,ライブラリだけでなくLisp処理系のインストールもできる点です.
RoswellでインストールされたLisp処理系を使うと,Roswellでインストールしたライブラリを何の設定もなしにrequireでロードできます.
したがって,RoswellさえあればQuicklispは必要ありません.
また,Roswellでインストールした処理系とライブラリは,単一のディレクトリ以下に配置されるので,既存の開発環境と共存できます.

ただし、RoswellをインストールしたらQuicklispもインストールされるため、不要と言うのは少し違う。
RoswellがQuicklispを隠蔽する感じだと思う。

上記説明へのリンク

上記の説明の引用先を下記に示す。

roswellを導入する手順

Common Lispとリアル・ワールドを繋ぐ「Roswell」の紹介に導入手順の分かりやすい説明がある。

1. roswell自体をインストールする

基本的にはroswellのgitwikiを参照しながら導入できる。 これによると、Macの場合はHomebrewを使用すれば簡単に導入できる。 roswellをインストールすると、バイナリ版SBCLとQuicklispがインストールされる。

$ brew install roswell
# ターミナルを開き直す
$ ros setup
$ ls -a ~/.roswell
.              archives       env            impls          lisp           src
..             config         helper.el      lib            local-projects tmp

roswellでインストールしたlisp実行環境を確認するには下記コマンドを実行。

$ ros list installed
Installed implementations:

Installed versions of clisp:
clisp/2.49

Installed versions of sbcl-bin:
sbcl-bin/1.4.4

インストールされた処理系、バージョンは切替ができ、rosで起動されるCommon Lispを変更できる。

# デフォルトで使用する処理系を確認する(ハイフン--は誤記ではない)
$ ros run -- --version
SBCL 1.2.12

# デフォルトで使用する処理系を変更する
$ ros use sbcl/1.1.8

# デフォルトで使用する処理系が変更された
$ ros run -- --version
SBCL 1.1.8

2. roswellでslimeをインストールする

slimvで使用するため、インストールする。

$ ros install slime

2. slimvを導入する

slimvとは?

slimvは、lisp記述・実行を支援してくれるvimプラグイン。 チュートリアルがそこそこ整っているので、最初に一通り実施してショートカットなどを覚えた方が良い。

ここで、slimvの仕組み(イメージ)について把握したほうが良い。 slimvの仕組みは、(多分)下記のとおり。

ユーザ --> slimv --> swank --> roswell(lisp実行環境)

ユーザがファイルやインタプリタ画面に対して操作したら、それをslimvがswankサーバに送り、lisp実行環境で処理される、といった具合だと思う。

slimvを導入する手順

1. slimvプラグインをインストールする

vimプラグインなので、インストール方法は色々あるが、ここではVundleを使用する。 Vundleの使い方は、また別の記事で説明する(多分)。

" これを.vimrcに記述して保存する
Plugin 'kovisoft/slimv'
" vimを開いて下記コマンドを実行してプラグインをインストールする
:VundleInstall

2. slimv用の設定を.vimrcに記載する

.vimrcを設定する。(macの場合なので、linuxなどの場合は適宜修正が必要。) 自分の場合はプラグインごとに設定ファイルを分けているので、その設定ファイル08slimv.vimを別に示す。 また、タグファイルの格納場所として、$HOME直下に.tagsディレクトリを作成する。

補足
brew などでインストールした素のclispを使用する場合は、(多分)slimv_swank_cmdを設定する必要はない。 roswellを使用する場合はswankサーバをroswellのものにするため、slimv_swank_cmdの設定が必要となる。

#!/usr/bin/env osascript
------------------------------------------------------------
-- 参考サイト
-- https://maku77.github.io/mac/applescript/terminal.html
------------------------------------------------------------
------------------------------------------------------------
-- roswell実行スクリプト
------------------------------------------------------------
-- -- roswellが用意したswank起動スクリプトを使用する
-- "ros run --load $HOME/.roswell/lisp/slime/2018.03.28/start-swank.lisp"
-- -- slimvが用意したswank起動スクリプトを使用する
-- "ros run --load $HOME/.vim/bundle/slimv/slime/start-swank.lisp"
------------------------------------------------------------
-- スクリプトのエントリポイント
------------------------------------------------------------
on run
set cmd to "ros run --load $HOME/.roswell/lisp/slime/2018.03.28/start-swank.lisp"
my newTab(cmd)
end run
------------------------------------------------------------
-- 新規ウィンドウでスクリプト実行
------------------------------------------------------------
-- 新しいタブを開いてコマンドを実行する
on newTab(command)
-- Open a new tab and wait a little
tell application "System Events"
keystroke "t" using command down
delay 0.5
end tell
-- Run the command in the new tab
tell application "Terminal"
do script command in front window
end tell
end newTab
------------------------------------------------------------
-- 新規タブでスクリプト実行
------------------------------------------------------------
on newWindow(command)
tell application "Terminal"
do script command
end tell
end newWindow
" 開き括弧を入力すると自動的に閉じ括弧を挿入する(デフォルト1)
let g:paredit_mode=1
" 括弧内で改行すると追加でもう一つ改行を挿入する。サブフォーム入力支援用。(デフォルト1)
let g:paredit_electric_return = 0
" connected swank serverの際、対話窓が縦分割の右側に出てくる
let g:slimv_repl_split=4
let g:slimv_repl_name='REPL'
" 評価する画面ではCtrl-Returnをすることで評価されるようにする
let g:slimv_repl_simple_eval=0
let g:slimv_lisp='/usr/local/bin/ros run'
let g:slimv_impl='sbcl'
"let g:slimv_preferred='clisp'
" ====================================================================
" swank起動コマンド設定
" --------------------------------------------------------------------
" linuxのとき
"" roswell ver.
"let g:slimv_swank_cmd = '! xterm -e ros --load ~/.roswell/lisp/slime/$DATE/start-swank.lisp &'
"" roswell ver. (swankを直接起動)
"let g:slimv_swank_cmd = "!ros -e '(ql:quickload :swank) (swank:create-server)' wait &"
" --------------------------------------------------------------------
" macOSのとき
" roswell ver. (同じターミナルの新規タブでslimvが用意したswank起動)
let g:slimv_swank_cmd = '!osascript $HOME/.vim/myconfig/config_plugins/08slimv-roswell.scpt'
"" roswell ver.
"let g:slimv_swank_cmd = '!osascript -e "tell application \"Terminal\" to do script \
"\"ros run --load $HOME/.roswell/lisp/slime/2018.03.28/start-swank.lisp\""'
"" roswell ver. (swankはslimvが用意したもの)
"let g:slimv_swank_cmd = '!osascript -e "tell application \"Terminal\" to do script \
"\"ros run --load '.$HOME.'/.vim/bundle/slimv/slime/start-swank.lisp\""'
""clisp ver. (frame-call関数がインプリメントされないのでslime debuggerがまともに動かない)
"let g:slimv_swank_cmd = '!osascript -e "tell application \"Terminal\" to do script \
"\"clisp --load '.$HOME.'/.vim/bundle/slimv/slime/start-swank.lisp\""'
" ====================================================================
" swankサーバのポート設定
let g:swank_port = 4005
" 括弧をカラフルに表示する
let g:lisp_rainbow=1
" asdf用のファイルタイプをlispに設定する
autocmd BufNewFile,BufRead *.asd set filetype=lisp
" 現在のファイルだけを対象としてタグファイルを作成
function! s:generate_lisp_tags()
let g:slimv_ctags='ctags -a -f '.$HOME.'/.tags/lisp.tags '.expand('%:p').' --language-force=Lisp'
call SlimvGenerateTags()
endfunction
command! -nargs=0 GenerateLispTags call <SID>generate_lisp_tags()
" 再帰的にタグファイルを作成
function! s:generate_lisp_tags_recursive()
let g:slimv_ctags='ctags -a -f '.$HOME.'/.tags/lisp.tags -R '.expand('%:p:h').' --language-force=Lisp'
call SlimvGenerateTags()
endfunction
command! -nargs=0 GenerateLispTagsRecursive call <SID>generate_lisp_tags_recursive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment