2011-02-23

Lisp mode のカーソル移動 forward-list

Elisp を書くようになると、括弧関連のカーソル移動のコマンドも多用するようになります。

C-M-f, C-M-b S式単位で前後に移動
C-M-a, C-M-e 関数単位で移動
C-M-d, C-M-u 括弧の内側外側へ移動
C-M-p, C-M-n 括弧単位で前後に移動

この中で、唯一 C-M-n (M-x forward-list) だけ、挙動に納得がいかなかった。

(-0- list (list)-1-
          (list)-2-)

-0- がスタート地点で、 -1- が C-M-n の1回目の実行後。-2- が2回目の地点。
カーソルが括弧の後ろに移動します。この動きなら C-M-f で代用可能です。

期待したのは以下のように、括弧の先頭へのカーソル移動。

(-0- list -1-(list)
          -2-(list))

ということで、自分でコマンドを作るとこんな感じに。

(defun my-forward-list (&optional arg)
  "Do `forward-list' and `backward-sexp'."
  (interactive "p")
  (or arg (setq arg 1))
  (let ((start (point))
        end)
    (if (and (= arg 1)
             (= start (scan-sexps (scan-lists start 1 0) -1)))
        (setq end (scan-lists start 2 0))
      (setq end (scan-lists start arg 0)))
    (goto-char (or (and end (scan-sexps end -1))
                   (buffer-end arg)))))

(eval-after-load "lisp-mode"
  '(define-key lisp-mode-shared-map "\C-\M-n" 'my-forward-list)) ; forward-list

動作確認: GNU Emacs 22