κeenのHappy Hacκing Blog | Lispエイリアンの狂想曲

CIMの解説をしてみる コマンド編

先日LTで紹介したCIMが思いの外反響を呼んでる(Githubのstarが15)ので解説でもしてみます。

コマンド編の次は実装編です。これでバグにエンカウントしたときの調査とか完璧ですね。

インストーラ

READMEにあるように

curl https://raw.github.com/KeenS/CIM/master/scripts/cim_installer | /bin/sh

~/.cim/にインストールできます。パスを変えたければ

CIM_HOME=/path/to/cim curl https://raw.github.com/KeenS/CIM/master/scripts/cim_installer | /bin/sh

でOK。Cシェル系なら

env CIM_HOME /path/to/cim curl https://raw.github.com/KeenS/CIM/master/scripts/cim_installer | /bin/sh

でしょうか。

2014-10-20更新
CIM_HOMEの設定方法が間違ってました。正しくは

curl https://raw.github.com/KeenS/CIM/master/scripts/cim_installer | CIM_HOME=/path/to/cim /bin/sh

で、Cシェル系なら

curl https://raw.github.com/KeenS/CIM/master/scripts/cim_installer | env CIM_HOME /path/to/cim /bin/sh

です
更新ここまで

ここではcurlを使ってますがwget -O -とかfetch -o -など標準出力に吐ければなんでも良いです。

あ、でもCIM_HOMEを指定してインストールしたときにバグがある気がしてきました。今から直します。

CIMを使うにはシェルの起動時に初期化が必要ですが、インストーラが初期化ファイルを読みにいく処理を.*rcに書き出してくれます。Bourne Shellは.profileですね。
書き出すファイルは$SHELLを見てます。cshtcshshbashzshに対応してます。

あと~/.emacs.d/eshell/が存在したら~/.emacs.d/eshell/profileにも初期化処理を書き出します。一時期パスが間違ってて~/.emacs.d/profileに書き出してました。ごめんなさい。
vimshell(だっけ?)でも初期化さえしてしまえば使えると思うので誰か初期化処理書いて下さい。

cim

とりあえずhelp見ておきましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ cim help
CIM -- Common Lisp Implementation Manager

Commands currently available
install <impl[-version]> ;; Install the impl.
use <impl[-version]> ;; Use specified impl as `cl' command's backend.
resume [rm] [resume..] ;; Resume suspended installation(s) or give it up.
list <command> ;; List available target of <command>
reinstall <impl[-version]> ;; Reinstall the impl.
clean <impl>|all ;; Clean downloaded archive and src of the impl.
distclean <impl>|all ;; Clean built dists.
uninstall <impl[-version]> ;; Uninstall the impl.
purge <impl>|all ;; Just clean and uninstall the impl.
info ;; Display current state.
get ;; Upgrade cim itself.
version ;; Show the version
help <command> ;; Show help for <command>. If no commands are specified, show this help.

If you want detailed help, type `cim help <command>'.
## `cim install`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ cim help install
Usage:

 cim install <impl[-version]>
 
Description:

Install the given lisp implementation to cim directory.
If version is not specified, install the latest version.
If you want to pass specific options to 'configure' script,
prefix 'flags='.

Examples:

 # install sbcl-1.1.14
 cim install sbcl-1.1.14
  
 # install latest clisp with option.
 flags='--with-libsigsegv-prefix=/usr/local' cim install clisp

To show available lisp implementations, type 'cim list install'.

インストールします。はい。<impl[-version]>ってのはsbclとかclisp-2.48とかですね。バージョンを指定しなかったら最新版になります。cim list installでインストール可能なものを表示しますが載ってない古いバージョンとかもインストールできる筈です。多分。

configureスクリプトに渡すフラグを指定したいときはflags='flag....' cim installとします。ヘルプにあるようにlibsigsegvのパスを指定しないとFreeBSDでclispをインストールできなかったので用意しました。

Allegroはライセンス表示した方が良いのかなーとか考えてます。

cim use

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Usage:

 cim use <impl[-version]> [--default]

Description:

Use <impl> as background for 'cl' command. It also affects bare lisp command.
If version is not given, use latest version.
If --default is given, use the specified implementation at initial state.

Examples:

 # use the latest sbcl
 cim use sbcl
 sbcl --version
 -> SBCL 1.1.14
 # use old sbcl
 cim use sbcl-1.1.10
 sbcl --version
 -> SBCL 1.1.10

 # use ccl-1.9 and set it default
 cim use ccl-1.9 --default

clコマンドのバックエンドの切り替えと処理系のバージョンの両方を切り替えます。処理系の指定の仕方はinstallに同じ。じゃなかった。installに加えて/bin:/usr/bin:/usr/local/binにあるものをxxx-systemとして指定できます。sbcl-systemとか。

例えば

cim use clisp-2.48

ってやるとclコマンドがバックエンドとしてclispのバージョン2.48を使うようになりますし、clispコマンドのバージョンも2.48になります。このclispの部分はリンクを貼り替えてて、一つのシェルで変更すると他のシェルにも影響が及ぶ問題があるのでそのうち直します。これ結構面倒なのでそのうちです。
clisp = clisp-2.48な状態でcim use sbclするとclisp = clisp-2.48なままclのバックエンドがsbclになります。上手く使って下さい。

--defaultを付けると次回からのデフォルト値を指定したものにしつつcim useします。

cim resume

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ cim help resume
Usage:

 cim resume [rm] <impl[-version]> | all

Description:

Resume interrupted installation of <impl>. If <version> is not given, the latest version is used.
If 'rm' is given, remove <impl> from 'resume' list.
If target is 'all', do on all the available target.

Examples:

 # resume the installation of clisp with configure flags
 flags='--with-libsigsegv-path=/usr/local' cim resume clisp

 # remove all the available target.
 cim resume rm all

cim installがエラー終了したりCtrl-Cで中断したりしたやつを再開してくれるコマンドです。cim install sbclを中断したならcim resume sbclで再開できます。cim resume allで中断された全てのインストールを再開します。終了ステータスは再開してもまたエラーで終了したやつの数になります。

cim resume rm sbclだとcim list resumeの結果からsbclを削除できます。resumeはしませんよ。cim resume rm allとかも可能です。

cim list

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ cim help list
Usage:

 cim list <subcommand>

Description:

List available target for subcommand.

Examples:

 # list available lisp implementation to install
 cim list install

 # show available target for list
 cim list list

 # targets for subsubcommands are also available
 cim list resume rm

さっきから出てきてるので分かるかと思いますが、可能なターゲットを表示します。将来的にはzshの補完候補にも使うつもりです。そのときは-b, --batchオプションでhuman readableかmachine readableかを分けようかなと。

cim reinstall

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ cim help reinstall
Usage:

 cim reinstall <impl[-version]> | all
 
Description:

Force install already installed implementaion(s). Downloaded archives are resued if available
If version is not specified, install the latest version.
If target is 'all', do on all the available targets.

Examples:

 # reinstall sbcl-1.1.14
 cim reinstall sbcl-1.1.14
  
 # reinstall all installed lisp impls
 cim reinstall all

To show available lisp implementations, type 'cim list reinstall'.

cim installは既にインストールされているものはインストールできないのですが、reinstallを使えば可能です。ダウンロードしたアーカイブがあればそれを使います。なければダウンロードから始めます。allは察しのようにインストール済のものを全てreinstallします。

cim clean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ cim help clean
Usage:

 cim clean <impl[-version]> | all
 
Description:

Remove donwloaded archives and extracted sources of the given lisp implementations.
If version is not specified, install the latest version.
If target is 'all', do on all the available targets.

Examples:

 # clean sbcl-1.1.14
 cim clean sbcl-1.1.14
  
 # clean all installed lisp impls
 cim clean all

To show available lisp implementations, type 'cim list clean'.

cim installは基本的に不要なものも削除しないので、それが嫌ならcleanを使いましょうというスタンスです。アーカイブとソースを削除します。

cim distclean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$cim help distclean
Usage:

 cim distclean <impl[-version]> | all
 
Description:

Clean built files of the given lisp implementation. It doesn't mean uninstall.
If version is not specified, install the latest version.
If target is 'all', do on all the available targets.

Examples:

 # distclean sbcl-1.1.14
 cim distclean sbcl-1.1.14
  
 # distclean all installed lisp impls
 cim distclean all

To show available lisp implementations, type 'cim list distclean'.

cim cleanより控えめなコマンドです。コンパイルするときにmakeで生成されたファイルを削除します。make clean的な。

cim uninstall

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ cim help uninstall
Usage:

 cim uninstall <impl[-version]> | all
 
Description:

Uninstall the given lisp implementaion(s). It does't remove donwloaded archives and extracted sources.
If version is not specified, install the latest version.
If target is 'all', do on all the available targets.

Examples:

 # uninstall sbcl-1.1.14
 cim uninstall sbcl-1.1.14
  
 # uninstall all installed lisp impls
 cim uninstall all

To show available lisp implementations, type 'cim list uninstall'.

アンインストールします。はい。ただしダウンロードしたアーカイブとソースは削除しません。

cim purge

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ cim help purge
Usage:

 cim purge <impl[-version]> | all

Description:

Uninstall and clean up downloaded files of the given lisp implementation.
This command is equivalent to 'clean' and 'uninstall'.

Examples:

 # purge the latest sbcl
 cim purge sbcl

To show available target for 'purge', type 'cim list purge'

uninstallのアーカイブとソースを削除する版です。

cim info

1
2
3
4
5
6
7
8
9
10
11
12
13
$ cim help info
Usage:

 cim info

Description:

Display information for current cim. It includes environment variables that cim uses, what current and default lisp implementation is, what version of each implementation is used, and where system lisp is.

Example:

 # display info
 cim info

現在の状態を表示します。こんな感じ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ cim info
CIM_ID = 22176
CIM_HOME = /home/kim/.cim

current lisp = sbcl-system
default lisp = sbcl-system

abcl = abcl-1.2.1
alisp = alisp-9.0
ccl = ccl-1.9
clisp = clisp-2.49
ecl = ecl-13.5.1
gcl = gcl-2.6.9
sbcl = sbcl-system

sbcl-system = /usr/local/bin/sbcl
gcl-system = /usr/bin/gcl

CIM_IDってのはcimがそれぞれのシェルの状態を管理するためのIDです。まあ、そのシェルのプロセスIDですね。逆にプロセスIDの取得と環境変数の設定さえできればcimは動かせるのでEmacsでも簡単に動きます。

cim get

1
2
3
4
5
6
7
8
9
10
11
$ cim help get
Usage:
 cim get

Description:

Upgrade to the latest cim.

Examples:

 cim get

cim自身のアップデートです。なんでこんな名前かというとrvmがそうだからです。現状はgithubのKeenS/CIMのmasterからとってきます。stable版ができたらstableに変更しますね。実はブランチを指定してとってくる方法もあったりはします。cim get --branch stableCIM_INSTALL_BRANCH=stable cim getです。まだブランチが無いので意味ないんですけどね。

この辺で気付いたかもしれませんが結構環境変数で制御できるようにデザインされてます。rubyがそんな感じだからです。

cim version

1
2
3
4
5
6
7
8
9
10
11
12
$ cim help version
Usage:

 cim version

Description:

Show current cim's version

Example:

 cim version

めちゃくちゃバグがあるのにversionが1.0.0に見えるの気のせいです。きっと100点中の1点なんですよ。

cim help

1
2
$ cim help help
Help for 'help' is not prepared, sorry.

あー。helpのhelp用意してなかったー。まあ、上で使ったのが全てです。

cl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ cl -h
Usage: cl [switchs] [--] [programfile] [argumensts]

-C DIR set *default-pathname-defaults* DIR.
-d, --debug set debugging flags (push :debug into *features*)
-e, --eval SEXP one line of script. Several -e's are allowed. Omit [programfile]
-f, --load FILE load the FILE
-i EXT edit *argv* files in place and make backup with the extension .EXT
-l LIBRARY quickload the LIBRARY
-L LIBRARY quickload and use-package the LIBRARY
-r, --repl run repl
-q, --no-init do not load $CIM_HOME/init.lisp
--no-rl do not use rlwrap. This is effective only when --repl is specified
--no-right do not display right prompt. This is effective only when --repl is specified
--no-color do not use color. This is effective only when --repl is specified
-h, --help print this help
-v, --version print the version

If neither programfile, -e (--eval) nor -r (--repl) are specified, cl reads scripts from the standard input and then eval them.

まあ、見たら分かりますね。ruby由来のオプションとShelly由来のオプションと私の好みのオプションがあります。clを起動する方法は

  • cl script.lisp
  • cl < script.lisp
  • cl -e sexp
  • cl -r

です。cl script.lispはシェバン(最初の行が#!なもの)を無視します。

また、これも環境変数LISP_IMPLでバックエンドを制御できます。これはShelly由来ですね。

もう一つ、デバッガは起動しません。スクリプトやワンライナーはエラーを吐いて終了して欲しいですし次に述べますがREPLも目的からしてデバッガは相応しくないと思うからです。因みにですが-dオプションをつけてもデバッガは起動しません。理由はオプション解析のほとんどをLispに任せているので起動時のオブションである--disable-debuggerを制御できないからです。需要が高そうならシェルスクリプト内で解析して頑張ってみます。

あ、-c, --compile FILEオプションつけ忘れてた。いつか入れます。(compile-file FILE)で可能でしょうからすぐに入るはずです。

cl -r

一応開発向けではなくて、ちょっと試したいときや初心者が本を片手に動かすときを想定して作ってます。エラーはメッセージのみ表示。ちょっと試したいときはあんまりデバッガを必要としませんしスタックトレースもどうせ深さ1~2なのであまり必要でないからです。なにより初心者にとってデバッガは何をして良いか分かりませんし覚えても処理系毎に操作が違います。その辺を分り易い統一インターフェースを作ることも考えたのですが「それってswank」って結論に至ったのでこのままです。

ql

1
2
3
4
5
6
7
8
9
10
ql -- Command line interface for quicklisp

Commands currently available
deps <system> ;; Install dependencies of <system>.
help [command] ;; Show help.
install[quickload] <system>... ;; Install given system.
list {remote | local} ;; List available/installed systems.
search[system-propos] <keyword> ;; Search quicklisp.
uninstall <system> ;; Uninstall system.
update [system] ;; Update dist info and installed systems.

一番未完成なコマンドです。主な理由は私がquicklispの使い方を分かってないからです。

ql deps

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ ql help deps
Usage:

 ql deps [--path <path>] <system>

Description:

Install dependencies of given system. If path is specified, install dependencies there.
Once you run 'ql --path <path> deps', you don't need to specify '--path' because the path is written out to '.quicklisp-path' in current directory.
You can run 'ql deps' for a local system if '.asd' file is in current directory.
This command is useful when you want to separate quicklisps for local project.

Example:

 ql deps --path ./quicklisp my-project

rubyのbundlerを参考に作りました。Gemfileに対応するQLfileでも読もうかと思いましたが良く考えたら.asdで十分じゃんとの思いに至ったのでカレントパスのasdファイルを読みます。
が、奴は依存システムのバージョンまでは指定できなかった気がするのでやっぱり必要な気がします。

ql deps --path ./ql myappとすると依存システム(+新たなquicklisp本体)を./qlにインストールしてくれます。quicklisp本体のインストールは不要ですがどうやったら回避できるかは今模索中です。
--pathの位置がcim use --defaultと違うのでご注意下さい。これは主に内部で使ってるparse-optionの欠陥に由来します。
一度指定すると.quicklisp-pathにパスを書き出してくれるので次回からは必要なくなります。カレントディレクトリに複数のasdファイルがあってそれぞれでパスを使い分けたいとかはできません。
あと、最大の欠陥として./qlにシステムをインストールしてもそれを読み込みにいくコマンドがないので実用性ゼロです← まあ、clあたりを弄ってカレントパスに.quicklisp-pathがあったら読みにいくようにします。その辺は.lisp-implとかも含めて考えます。

ql help

1
2
$ ql help help
Help for 'help' is not prepared, sorry.

こいつもhelp用意してなかった。まあ、良いや。

ql install

1
2
3
4
5
6
7
8
9
10
11
12
13
$ ql help install
Usage:

 ql install <system>...

Description:

Install given system(s) to $CIM_HOME/quicklisp.

Example:

 # install clack
 ql install clack

なんでこいつがhelpの先頭に居ないんでしょうね。cimに比べて適当ですね。

ql quickloadっていう別名も持ってます。ql helpにはquickloadが本名でinstallがエイリアスって書いてありましたが実装ミスりました。

名前の通りql:quickloadします。systemは複数指定できます。

ql list

1
2
3
4
5
6
7
8
9
10
11
12
$ ql list
Usage:

 ql list {remote | [local]}

Description:

List installed systems. if 'remote' is given, list all the available systems. 'ql list local' is equivalent to 'ql list'.

Example:

 ql list remote

cim listと使い方が違ってアレですね。現状quicklispに登録されているもの全てを表示するql list remoteとインストールしたものだけを表示するql list [local]があります。ql depsでパスを指定したやつらにも使いたかったのですが方法が分かんないのでとりあえず先送りです。

1
2
3
4
5
6
7
8
9
10
11
12
$ ql help search
Usage:

 ql search <keyword>

Description:

Search quicklisp for <keyword>.

Example:

 ql search http

別名system-apropos。別名と本名がql helpと違うのも単にql:system-aproposを呼ぶのもql installと同じです。出力結果をもうちょっと制御したいなと思ってます。

ql uninstall

1
2
3
4
5
6
7
8
9
10
11
12
$ ql help uninstall
Usage:

 ql uninstall <system>...

Description:

Uninstall given system(s).

Example:

 ql uninstall caveman clack

ql:uninstallに同じ。以上。

ql update

1
2
3
4
5
6
7
8
9
10
11
12
$ ql help update
Usage:

 ql update [client]

Description:

Update installed systems. If target 'client' is given, update quicklisp itself.

Example:

 ql update client

ql:update-all-distsql:update-clientかを選べます。最初はsystem毎にアップデートしたかったのですが無理っぽいので止めました。

おわりに

とりあえずCIMの機能はこれで全部です。あ、開発用にcim resetとかありますけど使わないで下さい。とういうか使うなよ。絶対使うなよ。

これら使ってみてバグがあったらgithubのissueに投げるなりtwitterで報告するなりして下さい。

ところでCIMは私はちむと読んでます。しー・あい・えむと読む人も居るようです。何でも良いです。プロジェクトとしてのちむとコマンドとしてのちむを区別するためにコマンドは小文字でcim、そしてcimclqlを含んだプロジェクトは大文字でCIMと書くことにします。今考えました。

Written by κeen