Common Lisp の開発環境
Emacs 標準の S 式編集コマンド
こんなコードがあったとする.
S 式用の,Emacs の標準機能を以下に示す.
(*移動*) ESC C-a : beginning-of-defun : defun の先頭へ移動 ESC C-e : end-of-defun : defun の末尾へ移動 ESC C-f : forward-sexp : カーソル位置から始まる S 式の末尾に移動 ESC C-b : backward-sexp : カーソル位置より一つ後の S 式の先頭に移動 ESC C-d : down-list : 1 レベル内側の S 式へ移動 ESC C-u : backward-up-list : 1 レベル外側の S 式へ移動 ESC C-n : forward-list : 括弧のグループを超えて前方へ移動 ESC C-p : backward-list : 括弧のグループを超えて後方移動 ESC C-k : kill-sexp : カーソル位置から始まる S 式を kill する ESC C-backspace : backward-kill-sexp : カーソル位置より一つ後の S 式を kill する (*インデント*) 割り当て無し : indent-sexp : S 式内を indent する (*マーク*) ESC C-SPC : mark-sexp : 引数の数だけ S 式をマークする ESC C-h : mark-defun : defun 全体をマークする (*編集*) ESC C-t : transpose-sexps : ポイント位置前後の S 式を入れ換える C-x n d : narrow-to-defun : defun の範囲に narrow する C-x n w : widen : narrow-to-defun を解除
SLIME
SLIME の公式ページ から入手可能.いろいろと面白い機能がある.メインの環境が CMUCL な こともあって,最近は ILISP から SLIME に乗りかえ気味.現在は CMUCL, SBCL, OpenMCL, AllegroCL, LispWorks, CLISP といった処理系に対応.
- 別プロセスで起動した lisp 処理系とソケット経由で通信する
- コマンド一発で HyperSpec が引ける
- コンパイラの note, warning, error をソース上で示してくれる(下線が引かれて,カーソルを合わせると詳細がでる)
- 親切なデバッガ(バックトレース上でカーソルを合せると詳細が表示されたりとか)
- 現在のパッケージを表示してくれる SLIME 独自の repl
SLIME のセットアップ
README によれば,ダウンロードした slime を展開したら,
(add-to-list 'load-path "/the/path/to/this/directory") (require 'slime) (add-hook 'lisp-mode-hook (lambda () (slime-mode t) (show-paren-mode)))
とするだけ.Common Lisp らしいインデントにするには↓をどーぞ.(私の趣味ですが)
(add-hook 'slime-mode-hook (lambda () (setq lisp-indent-function 'common-lisp-indent-function))) ;; Additional definitions by Pierpaolo Bernardi. (defun cl-indent (sym indent) (put sym 'common-lisp-indent-function (if (symbolp indent) (get indent 'common-lisp-indent-function) indent))) (cl-indent 'if '1) (cl-indent 'generic-flet 'flet) (cl-indent 'generic-labels 'labels) (cl-indent 'with-accessors 'multiple-value-bind) (cl-indent 'with-added-methods '((1 4 ((&whole 1))) (2 &body))) (cl-indent 'with-condition-restarts '((1 4 ((&whole 1))) (2 &body))) (cl-indent 'with-simple-restart '((1 4 ((&whole 1))) (2 &body)))
SLIME Features
http://www.cliki.net/SLIME%20Features を勝手に超意訳.思ったより長いから別ページにしようかなぁ….
SLIME の特徴.次のスクリーンショットは見た目はこんなかんじ.
助け合いの精神によって、だれでも以下の文章を修正したり追加したりできます。 (訳注:Web 版では Wiki じゃないのでできません…メールで連絡ください) 変更点 が少なくなったら texinfo にまとめられるでしょう。
Read-Eval-Print-Loop (REPL)
SLIME の Read-Eval-Print ループは Emacs が Lisp への接続を確立するとすぐに *slime-repl* バッファ上に表示されます。REPL バッファは伝統的な *inferior-lisp* バッファに似ていますが、Emacs と Lisp がより統合されています。 トップレベルの一部分は Emacs Lisp で書かれており、Emacs は常にどこにプロンプ トを表示するかを知っており、出力や戻り値の違いを示す事ができます。また、REPL はエラーが発生すると自動的に SLIME のデバッガを使用します。
スクリーンショットの右上が REPL です(その下はデバッガ)。プロンプト、入力、出 力、式の戻り値のそれぞれに別個の色が使われています。
*slime-repl* バッファでは slime-mode キーバーインディングのほとんどが利用可 能です。さらに以下のコマンドが利用できます。
- Return - 現在行を Lisp に送り、評価します。もし行が完結していなければ(括弧の不整合等)、新しいインデントされた行を開始します。
- Control-Return - 対応する括弧を閉じてから Lisp に行を送って評価します。
- C-c C-c - SIGINT を用いて Lisp プロセスに割り込みます。通常、これは状態を通知し、SLIME デバッガに入ります。マルチスレッド化された Lisp 処理系ではシグナル通知のあいまいさによりこの動作は確実ではありません。
Debugger
SLIME は独自の Emacs に統合されたデバッガを備えています.Lisp は常に Emacs へのリクエストを評価しており,*DEBUGGER-HOOK* はエラー時に使用されるデバッガ にバインドされています.デバッガが起動されると Emacs バッファに利用可能なリ スタートやバックトレースの一部が表示されたエラー画面がポップアップされます. スクリーンショットの右上の上部がデバッガです.
最初はバックトレースの一行だけが表示されています.より多くのフレームを表示す るにはカーソルを下に移動してバッファの最後の --more-- の行に合わせるだけです.
デバッガはリスタートされるまでアクティブなままです.デバッガ内では通常の SLIME コマンドが利用可能で,それらのコマンドのエラーは再帰的にデバッガを呼ぶ 事になります.
リスタートのためのコマンド:
- 0 .. 9 - 数字によるリスタート
- q - トップレベルへ抜ける
- a - ABORT
- c - CONTINUE
カーソルで指定されたフレームを操作するコマンド:
- v - カレントフレームの式をバッファ内で表示
- t - 冗長なフレーム表示の切り替え.冗長な表示は全てのローカルな変数と CATCH タグを含みます.
- l - ローカルな変数を表示します
- e - フレーム内で式を評価します
- d - 式を評価して結果をバッファに表示します
- i - 式を評価して結果をインスペクトします
- : - 式をグローバル環境で評価します
- D - カレントフレームのコードをディスアセンブルします
- r - 呼ばれた時と同じ引数でフレームの実行を再開します(一部の処理系ではサポートされていません)
- R - カレントフレームの値を返します(一部の処理系ではサポートされていません)
フレーム間の移動:
- n - 次のフレームに移動します
- p - 前のフレームに移動します
- M-n - Detail-move で次のフレームに移動します.これは現在行を一行サマリに切り替え,移動先のフレームを冗長表示に切り替え(t),式を表示(v)します.
- M-p - Detail-move で前のフレームに移動します.
Edit Definition
多くの Lisp は関数のソースコードの位置を記録しています.SLIME はこの情報を使って特定のシンボルの定義を見つけます.ユーザーはこの機能のために独立した "タグテーブル" を維持する必要がありません.
- M-. - ポイント位置のシンボル定義にジャンプ
- M-, - ジャンプした関数定義から戻る
SLIME は関数定義にジャンプする前に現在位置をスタックにプッシュします.M-, はこのスタックのトップエレメントをポップし,保存されいていた位置にジャンプします.
お使いの Lisp 処理系のソースコードをインストールする事をお勧めします.ソースを読む事で多くのトリックを学ぶ事ができるからです.CMUCL の場合,次のようにどこにソースコードをインストールしたのかを .cmucl-init.lisp で設定する必要があります.
(setf (search-list "target:") '("/opt/cmucl/src/"))
SBCL ならば次のように対応する論理パスの定義を行なうと良いでしょう.
(setf (logical-pathname-translations "SYS") '(("SYS:SRC;**;*.*.*" #P"/opt/sbcl/src/**/*.*") ("SYS:CONTRIB;**;*.*.*" #P"/opt/sbcl/contrib/**/*.*")))
Documentation
SLIME は ILISP と同様に Erick Naggum 氏の作成した Common Lisp HyperSpec アク セスのためのパッケージを備えています.それはオンラインバージョンの HyperSpec を使うようになっていますが,もし何らかの理由で HyperSpec をローカルにダウン ロードして使いたい場合には .emacs で
(setq common-lisp-hyperspec-root "file:/usr/local/lisp/CLHS6/HyperSpec/")のように HyperSpec へのパスを設定してください.
Emacs に組込む web ブラウザは好みがあるので,もし他のブラウザを使いたければ emacs のカスタマイズ設定で "Browse Url Browser Function" から好きなブラウザ を指定してください.
Compilation
SLIME はファイル,定義,バッファ,リージョン,システム(訳注:おそらく defsystem で定義されるやつ)をコンパイルするためのコマンドを備えています.ファ イルをコンパイルするとシステムはコンパイルされたコードを fasl ファイルとして ディスクに保存します.定義やバッファやリージョンをコンパイルするとコードはメ モリ上に記憶され,ファイルには書き出されません.
C-c C-c 現在のトップレベルフォームをコンパイル M-x slime-compile-region リージョンをコンパイル C-c C-k カレントバッファのファイルをコンパイルし,ロードする(コンパイルが成功した場合だけロードされる) C-c M-k カレントバッファのファイルをコンパイルする(ロードしない) C-c C-l バッファのファイルをロードする M-x slime-load-sysmtem 入力されたシステムの変更されたファイルをコンパイルしてロードする
Compiler Warnings Commands
SLIME はコンパイラによって生成された警告を集め,ソース上の適切な位置を見つけ たりコンパイラのメッセージを表示するコマンドを提供します.SLIME は警告に対応 するソースコードにカーソルが重なると表示される注釈を付けます.カーソルに対応 するメッセージはミニバッファ上に表示されます.
M-n 次のコンパイラの警告位置に移動し,警告を表示します M-p 前のコンパイラの警告位置に移動し,警告を表示します M-x slime-list-compiler-notes 別のバッファに全てのコンパイラの警告を表示します. 警告をクリックもしくは RET キーで対応するソースコードをハイライトします
Evaluation
評価コマンドはプログラムの小さな部分をテストするのに便利です.
C-c : ミニバッファで式を一つ読み込んで評価し,その値をエコー領域に表示します (slime-interactive-eval) C-x C-e ポイント位置の前にある式を評価し,値をエコー領域に表示します (slime-eval-last-sexp') C-M-x ポイント位置の後もしくはポイント位置を含むトップレベルフォームを評価し, 値エコー領域に表示します (slime-eval-defun) C-x C-p ポイント位置の前にある式を評価し,新しい表示バッファに値を pretty-print します (slime-pprint-eval-last-expression) M-x slime-eval-region リージョン内の全ての式を評価します M-x slime-eval-buffer バッファ内の全ての式を評価します C-x M-e ポイント位置の前にある式を評価し,値をエコー領域と出力バッファに表示します (slime-eval-last-expression-display-output). C-c C-u ポイント位置のシンボルへの関数定義を取り除きます (slime-undefine-function).
C-c : はインタラクティブに式を評価するためのもっとも基本的なコマンドです. Emacs はミニバッファから文字列として式を読み込み,それを slime-buffer-package の値とともに Lisp に送ります.Lisp は文字列もパッケージ 内で read し,フォームを評価して文字列として結果を Emacs に返し,Emacs はエ コー領域に結果を表示します.
slime-buffer-package はバッファローカルな変数で,もっとも近い in-package フォー ムから見つけた名前を含みます.もしバッファに in-package フォームが無ければカ レントパッケージ(*package*)の値を使用します.
C-x C-e や C-M-x コマンドは C-c : に似ていますが,ミニバッファから式を読みません.C-x C-e はポイントの前にある S 式を,C-M-x はポイントの後もしくはポイントを含むトップレベルフォームを使用します.トップレベルフォームは最初のカラムが開き括弧から始まる S 式です.
Defvar Hack: C-M-x は defvar から始まるフォームを特別扱いします.もし既にそ の変数が存在しているなら,変数がリセットされます.したがって C-M-x は defvar を defparameter にします.C-x C-e はこのような defvar の特別扱いをしません.
Tip: slime-complete-symbol はポイントの周辺のシンボルを補完に使用する事ができます.それは Lisp バッファでは M-TAB に,ミニバッファでは TAB にバインドされています.
Inspector
slime-mode keybindings overview
ここでは C-h m (describe-mode) で示される slime-mode のキーバインドの要約を 示します.これらのコマンドのサブセットは *slime-repl* バッファでも利用可能で す.
SLIME: The Superior Lisp Interaction Mode for Emacs (minor-mode). カレントバッファのソースファイルをコンパイルしコンパイラの注意や警告をハイライトするには: C-c C-k - カレントバッファのファイルをコンパイルしてロードする C-c M-k - カレントバッファのファイルをコンパイルする C-c C-c - ポイント位置のトップレベルフォームをコンパイルする コンパイラの注意を巡回するには: M-n - 次の注意へ移動 M-p - 前の注意へ移動 C-c M-c - バッファ内の compiler-note を削除 定義を見つけるには: M-. - ポイント位置の関数定義を編集する M-, - 関数定義の編集から戻る プログラミング支援 C-c TAB - ポイント位置の Lisp シンボルの補完( M-TAB と同じ) C-c RET - Macroexpand once. C-c M-m - Macroexpand all. クロスリファレンス(CMUCL のマニュアルを参照): C-c C-w c - WHO-CALLS a function. C-c C-w r - WHO-REFERENCES a global variable. C-c C-w s - WHO-SETS a global variable. C-c C-w b - WHO-BINDS a global variable. C-c C-w m - WHO-MACROEXPANDS a macro. C-M-. - Goto the next reference source location. (Also C-c C-SPC) ドキュメント関連コマンド: C-c C-d - シンボルを Describe C-c C-a - Apropos 検索 C-c M-d - 関数のディスアセンブル 評価コマンド: C-M-x - ポイントを含むトップレベルフォームを評価 C-x C-e - ポイントの前の S 式を評価 C-c C-p - ポイントの前の S 式を評価し,結果を pretty-print する
xyzzy - Common Lisp なエディタ
Windows で Lisp と言えばこれ.xyzzy が素晴しいです.なんと Common Lisp (準拠度 6 割程度とのこと)を採用した高性能エディタです.
ILISP
ドキュメント
ilisp から利用可能な 1 ドキュメントとしては,
が ilisp からヘルプとして利用可能です.HyperSpec のが新しい規格書ですが,ドキュメントやサンプルが沢山あったほうが嬉しいので CLtL2 も入手しておきましょう .
ilisp の設定を済ませると,コマンド一発で CLtL2 や HyperSpec が引けるようになります.HTML を表示時に外部ブラウザが起動してうっとおしい人は lynx や w3m を使えば Emacs 内で全てが完結します.
また,通常の ilisp では関数名を入力した後のスペースで Window がポップアップして引数リストを表示してくれますが,これが邪魔という人は
(setf lisp-no-popper t)
とすればポップアップしなくなります.さらに,引数をミニバッファに表示するのすら邪魔だ,という人は
(setf ilisp-*arglist-message-lisp-space-p* nil)
で表示しないように設定できます.
ilisp 環境では
- 調べたいシンボルにカーソルをあわせる
- hyperspec-lookup コマンド一発
で,簡単にヘルプが引けます.
ilisp の機能
とりあえず,現状使ってる ilisp の機能.(broken?) は設定が悪いのかちゃんと動いてないやつ.(だれか教えて下さい…)
PREFIX : C-c C-c C-s slow-lisp 安全第一に C-c C-f fast-lisp 速度重視で C-c L cltl2-lookup CLtL2 を引く C-c H hyperspec-lookup HyperSpec を引く C-c k compile-file-lisp ファイルをコンパイル C-c l load-file-lisp ファイルをロード C-c S select-ilisp lisp を切り替える(複数の Lisp 処理系を使ってる時とか) C-c s status-lisp ilisp の状態を表示 C-c g abort-commands-lisp lisp に送ったコマンドを中断 C-c z reset-ilisp lisp の状態をリセット C-c y call-defun-lisp (broken?) C-c b switch-to-lisp lisp なバッファに切り換え C-c * Prefix Command C-c SPC mark-change-lisp 変更マークを付ける C-c ! default-directory-lisp lisp のデフォルトディレクトリを表示 C-c t trace-defun-lisp 関数のトレース ON/OFF C-c C-w compile-region-and-go-lisp リージョンをコンパイル後,lisp バッファへ移動 C-c C-n eval-next-sexp-and-go-lisp S 式を評価後,lisp バッファへ移動 C-c C-e eval-defun-and-go-lisp 関数定義を評価後,lisp バッファへ移動 C-c C-r eval-region-and-go-lisp リージョンを評価後,lisp バッファへ移動 C-c c compile-defun-lisp 関数定義をコンパイル C-c C-b ilisp-compile-buffer バッファにあるコードをコンパイル C-c w compile-region-lisp リージョン内のコードをコンパイル C-c n eval-next-sexp-lisp 次の S 式を評価 C-c e eval-defun-lisp 関数定義を評価 C-c r eval-region-lisp リージョンを評価 C-c ^ edit-callers-lisp (broken?) C-c M macroexpand-lisp マクロ展開 C-c m macroexpand-1-lisp マクロ展開(macroexpand-1 ふつーこっち) C-c d documentation-lisp ドキュメント表示 C-c a arglist-lisp 引数リスト表示 C-c I inspect-lisp インスペクタ表示 C-c i describe-lisp describe する C-c ) find-unbalanced-lisp 括弧の不一致を見つける C-c ; comment-region-lisp リージョンをコメントアウト C-c <return> complete 補完 C-c TAB complete-lisp lisp シンボルを補完 C-c C-c compile-defun-and-go-lisp 関数定義をコンパイル後,lisp なバッファに移動 C-c C-z run-lisp lisp を起動 ESC RET complete 補完 ESC TAB complete-lisp lisp シンボルを補完 ESC ` next-caller-lisp (broken?) ESC " replace-lisp 置換 ESC ? search-lisp (broken?) ESC . edit-definitions-lisp (broken?) ESC , next-definition-lisp (broken?) ESC C-e end-of-defun-lisp 関数定義の末尾へ移動 ESC C-a beginning-of-defun-lisp 関数定義の先頭へ移動 ESC C-q indent-sexp-ilisp S 式内をインデント ESC C-r reposition-window-lisp 位置を再設定 ESC q reindent-lisp 再インデント ESC C-x eval-defun-lisp 関数定義を評価 C-c * 0 clear-changes-lisp 変更マークをクリア C-c * c compile-changes-lisp 変更マークしたところをコンパイル C-c * e eval-changes-lisp 変更マークしたところを評価 C-c * l list-changes-lisp 変更マークのリスト表示
J
Java で書かれたエディタ。
- ArmedBear を参照。