LISPUSER

Emacs による Lisp HackingLisp isn't a language, it's a building material.

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 の公式ページ から入手可能です.現在は ArmedBearCL, AllegroCL, CLISP , Corman Lisp, CMUCL, ECL, LispWorks, OpenMCL, SBCL, Scieneer Common Lisp といった処理系に対応.( Scheme48 に対応した SLIME48 もあります)

  • 別プロセスで起動した lisp 処理系とソケット経由で通信する
  • 関数の引数表示
  • シンボルの補完機能 ( **例:** ``m-v-b TAB => multiple-value-bind`` )
  • コマンド一発で HyperSpec が引ける
  • コンパイラの note, warning, error をソース上で示してくれる(下線が引かれて,カーソルを合わせると詳細がでる)
  • 親切なデバッガ(バックトレース上でカーソルを合せると詳細が表示されたりとか)
  • 現在のパッケージを表示してくれる SLIME 独自の REPL

ダウンロードした slime を展開したら,

(add-to-list 'load-path "/the/path/to/this/directory")
(add-hook 'lisp-mode-hook (lambda ()
                            (slime-mode t)
                            (show-paren-mode)))

とするだけです.HyperSpec を引いたり,日本語を利用などを加えると次のよ うな設定になります.

;; HyperSpec の場所を指定する
(require 'hyperspec)
(setq common-lisp-hyperspec-root

(concat "file://" (expand-file-name "~/doc/HyperSpec/")) common-lisp-hyperspec-symbol-table (expand-file-name "~/doc/HyperSpec/Data/MapSym.txt"))

(require 'slime)
(setq slime-net-coding-system 'utf-8-unix) ;; 日本語利用のための設定(Lisp 環境側の対応も必要)
(setq inferior-lisp-program "sbcl")
(add-hook 'inferior-lisp-mode-hook (lambda () (inferior-slime-mode t)))
(add-hook 'lisp-mode-hook (lambda ()

(slime-mode t) (show-paren-mode) (global-set-key "\C-cH" 'hyperspec-lookup)))

(slime-autodoc-mode)
;; These are the 3 CL implementations that currently work with SLIME/Win32:
;; (Note: Unless you want to try out all 3, you only need one of these functions)
;; CMU Common Lisp - http://www.common-lisp.net/project/cmucl
(defun cmucl-start ()
  (interactive)
  (shell-command "~/local/bin/lisp -core ~/local/lib/cmucl/lib/user.core -load ~/.slime.lisp&"))
;; SBCL
(defun sbcl-start ()
  (interactive)
  (shell-command "sbcl --core ~/local/lib/sbcl/main.core --load ~/.slime.lisp &"))
;; GNU CLISP - http://clisp.cons.org/
(defun clisp-start ()
  (interactive)
  (shell-command (format "clisp -K full -q -ansi -i %s/.slime.lisp &" (getenv "HOME"))))

SLIME Features

[[http://www.cliki.ne//www.cliki.net/SLIME%20FeaturesLIME%20Features][http://www.cliki.net/SLIME%20Features]] を勝手に超意訳.思ったより長いから別ページにしようかなぁ….

SLIME の特徴.次のスクリーンショットは MacOS X 上の 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 処理系ではシグナル通知のあいまいさによりこの動作は確実ではありません。
  • TAB - ポイント位置の 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

評価コマンドはプログラムの小さな部分をテストするのに便利です.

.. いちいち REPL に打ち込まなくていいので.

``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 する

HyperSpec を読む

info で Info 形式の dpANS3 を読む

http://whome.phys.au.dk/~harder/dpans.html の手順に従って info を作成します。 ただし、2008年8月の時点ではデータの取得先が消えているので、以下に現在利用可能な手順を示します。

  1. Texinfo をインストールしておく
  2. dpans2texi をダウンロード
  3. dpans2tex-1.03.tar.gz を展開し、cd dpans2texi-1.03/ で移動して ./configure
  4. http://quimby.gnus.org/circus/cl/ から dpANS3.tar.gz, dpANS3R.tar.gz の二つをダウンロード
  5. dpANS3.tar.gz, dbANS3R.tar.gz を展開し、それぞれ中身を dpans2tex-1.03/ へコピー (mv dpANS3/* dpans2texi-1.03/; mv dpANSR3/* dpans2texi-1.03/)
  6. cd dpans2texi-1.03/; make
  7. できあがった ansicl ansicl-1 ansicl-2 … ansicl-10 を Info のパスの通ったところにインストールする。(手動でやる場合は dir に ansicl のエントリを追加)

私の環境では dir には以下のようなエントリを追加しています。

* ANSI-CL: (ansicl).             ANSI Common Lisp

さらに、Emacs から引けるように .emacs で以下の設定を行います。 これはシンボルを ansicl の Symbol Index から検索する設定で、これを使うとヘルプを引くのが快適になります。

;; Info の設定
(require 'info-look)
(info-lookup-add-help
  :mode 'lisp-mode
  :regexp "[^][()'\" \t\n]+"
  :ignore-case t
  :doc-spec '(("(ansicl)Symbol Index" nil nil nil)))
;; 好みのキーバインドを割り当てる
(add-hook 'lisp-mode-hook (lambda () (global-set-key "\C-ci" 'info-lookup-symbol)))

あとは、lisp-mode で C-c i をタイプしてみましょう。

hyperspec.el で HTML 形式の HyperSpec を読む

dpANS3 より新しい Common Lisp HypserSpec はHTML版が ftp://ftp.lispworks.com/pub/softwaretools/reference/HyperSpec-7-0.tar.gz からダウンロード可能です。

slime に附属している hyperspec.el を使うと、Webブラウザを呼び出して HyperSpecを読む事ができます。 最近はこちらが一般的だと思います。emacs-w3m を使えば Emacs 内で読む事ができます。

;; ローカルに展開した HyperSpec (~/doc/HyperSpec/) を読む
(require 'hyperspec)
(setq common-lisp-hyperspec-root         (concat "file://" (expand-file-name "~/doc/HyperSpec/"))
      common-lisp-hyperspec-symbol-table (expand-file-name "~/doc/HyperSpec/Data/Map_Sym.txt"))

あとは、slime が起動している状態で C-c C-d h (slime-hyperspec-lookup) を呼び出しましょう。

emacs-w3m を使うには emacs-w3m をインストールした状態で次のような設定を追加します。

;; emacs-w3m の設定 (emacs-w3m をインストールしておいてください)
(require 'w3m)
(setq browse-url-browser-function 'w3m-browse-url)

これで、HTMLのブラウズに w3m が利用されるようになります。

xyzzy - Common Lisp なエディタ

Windows で Lisp と言えばこれ. xyzzy が素晴しいです.なんと Common Lisp(準拠度 6 割程度とのこと)を採用した高性能エディタです.

xyzzy は標準で lisp モードを持っていますが,何故かキーワードハイライト が OFF になってます.キーワードファイル自体は etc/lisp に存在しているの で,lisp-mode のフックで有効にするだけです.

(add-hook '*lisp-mode-hook*
  #'(lambda ()
       (make-local-variable 'keyword-hash-table)
       (setf keyword-hash-table (load-keyword-file "lisp"))
       (make-local-variable 'regexp-keyword-list)
       (setf regexp-keyword-list
          (compile-regexp-keyword-list
            '(("(" t (:color 14))

Common Lisp で開発する時に必須の HyperSpec を引けるように hyperspec.el を Emacs から移植しました.

LispWorks

LispWorks の IDE に附属のエディタは、高機能です.Emacs ライクな操作に加 えて Common Lisp による拡張も可能です.LispWorks の機能が使えるため CAPI ベースの GUI 拡張も可能です. Edi Weitz 氏の LW-ADD-ONS パッケージ を使うと SLIME ライクな補完とか正規表現ベースの Apropos などが 利用できるようになります.

;; -*- Mode: Lisp; -*-

;; Editor
(require "abbrev")
(require "c-mode")
(require "diff")
(require "dynamic-complete")
(require "idl-mode")
(require "page-directory")
(require "register")
;; for COM Support
(require "com")
(require "automation")
(require "ole")
;; Misc
(require "parsergen")
(require "jfile-info")

(in-package "EDITOR")
(bind-key "Indent And Complete Symbol" "Tab" :global :emacs)
(bind-key "Delete Previous Character" "Control-h" :global :emacs)
(bind-key "Help" "F1" :global :emacs)
(bind-key "Extended Command" #("Control-[" "x") :global :emacs)
(bind-key "Copy To Cut Buffer" #("Control-[" "w") :global :emacs)
(bind-key "Scrolling Window Up" #("Control-[" "v") :global :emacs)
(bind-key "Beggining of Buffer" #("Control-[" "<") :global :emacs)
(bind-key "End of Buffer" #("Control-[" ">") :global :emacs)

特徴適なのは bind-key でしょうか.これは Emacs の `*-set-key` に相当 しますが,シンボルや関数ではなくユーザーから見えるコマンドが文字列ベー スなのが大きな違いですね.呼び出すときも, `M-x` と打つと `Extended Command:` というプロンプトがミニバッファに表示され,そこで `End of Buffer` とタイプする事でエディタのコマンドを呼び出します.

コマンドの定義は `*defcommand*` 関数を使用して行ないます.標準のサンプ ルに含まれている例ですが,たとえばカーソル位置の関数定義を Disassemble した結果を表示するエディタコマンドを作成したいとします.まず `defcommand` でコマンドを定義します.

(defcommand "Disassemble Definition" (p)
     "Outputs assembly code for a definition, compiling it first if necessary."
     ""
  (let ((symbol (prompt-for-symbol p
                                   :prompt "Disassemble definition: "
                                   :default (current-top-level-definition-maybe))))
    (with-random-typeout-to-window ()
      (format t "Disassembly of ~S~%" symbol)
      (disassemble symbol))))

次に,このコマンドを ``bind-key`` 関数でキーに割り当てます.

(bind-key "Disassemble Function" "F2" :global :emacs)

これで F2 を押すとカーソル位置のシンボルをプロンプトで確認した後に disassemble して表示できるようになります.

$Last Update: 2006/08/30 23:42:28 $