対応する括弧で閉じてくれる elisp
3種類の括弧の閉じ分けが面倒なので作ってみた。デバッグ不十分なので不具合あるかも。あと、ナローイングとか考慮されていません。
;; 開き括弧 { or ( or [ に対応した閉じ括弧 } or ) or ] を挿入する (defun clj-close-sexp () (interactive) (let ((close-pos (point))) (insert ")") (condition-case ERR (clj-close-sexp-impl close-pos) (error (clj-close-sexp-error close-pos))))) (defun clj-close-sexp-impl (close-pos) (backward-list) (let ((open-pos (point))) (let ((ch (buffer-substring open-pos (1+ open-pos)))) (let ((new-char (cond ((string= ch "[") "]") ((string= ch "{") "}")))) (when new-char (goto-char close-pos) (delete-char 1) (insert new-char))))) (goto-char (1+ close-pos))) (defun clj-close-sexp-error (close-pos) (goto-char close-pos) (delete-char 1)) ;; ) 入力時に実行されるようキーバインド (add-hook 'clojure-mode-hook (lambda () (local-set-key "\)" 'clj-close-sexp))) ;; チェックなしで任意に ) を入力出来るように。 (defun clj-close-sexp-no-check () (interactive) (insert ")")) ;; C-) にキーバインド (add-hook 'clojure-mode-hook (lambda () (local-set-key (kbd "C-)") 'clj-close-sexp-no-check)))
) を入力すると対応する括弧に合せて } or ] or ) が挿入されます。) を押し続けると対応する括弧が無くなったところで止ります。
ただそれだとプログラム構造と無関係に ) を入れることが出来なくなるので、一応それようのコードも入れてあります。
本当は、C-] じゃなく、C-) にバインドさせたかったんだけど、キー定義の書き方がわからなかった。どうやるんだ? (kbd "C-)") とすることでバインドできました。
他モードへの適用
clojure-mode での利用を前提にしています。
lisp-mode 試したところ、backword-sexp で [ や ( へは飛んでくれますが、{ は式の先頭と認識してくれないようです。このため { があると正常に動きませんでした。
コード修正
- 2010/06/28 開き括弧の前に ' や # などの記号がある場合正常に動作しないバグ修正 (clj-close-sexp-impl)
- 2010/06/28 開き括弧へジャンプする処理を backward-sexp から backward-list に変更、こちらなら ' などに関係なく正しく開き括弧へ飛んでくれるみたい(clj-close-sexp-impl)。【などの全角括弧でもちゃんと働いてくれます。
- 2010/06/30 clj-close-sexp-no-check のキーバインドを C-] から C-) に変更。