C-aで「行頭」と「インデントを飛ばした行頭」を行き来する Emacs23対応版

d:id:gifnksm:20090403:1238745022とかd:id:gifnksm:20090331:1238488792とかで書いたやつのEmacs23対応+改良版。js2-modeのC-aの動作を実現するelispとその物理行対応版。

(defun beginning-of-indented-line (current-point)
  "インデント文字を飛ばした行頭に戻る。ただし、ポイントから行頭までの間にインデント文字しかない場合は、行頭に戻る。"
  (interactive "d")
  (if (string-match
       "^[ \t]+$"
       (save-excursion
         (buffer-substring-no-properties
          (progn (beginning-of-line) (point))
          current-point)))
      (beginning-of-line)
    (back-to-indentation)))

(defun beginning-of-visual-indented-line (current-point)
  "インデント文字を飛ばした行頭に戻る。ただし、ポイントから行頭までの間にインデント文 字しかない場合は、行頭に戻る。"
  (interactive "d")
  (let ((vhead-pos (save-excursion (progn (beginning-of-visual-line) (point))))
        (head-pos (save-excursion (progn (beginning-of-line) (point)))))
    (cond
     ;; 物理行の1行目にいる場合
     ((eq vhead-pos head-pos)
      (if (string-match
           "^[ \t]+$"
           (buffer-substring-no-properties vhead-pos current-point))
          (beginning-of-visual-line)
        (back-to-indentation)))
     ;; 物理行の2行目以降の先頭にいる場合
     ((eq vhead-pos current-point)
      (backward-char)
      (beginning-of-visual-indented-line (point)))
     ;; 物理行の2行目以降の途中にいる場合
     (t (beginning-of-visual-line)))))

Emacs 23からデフォルトでvisual-line (物理行)の行頭へ移動する関数とかが用意されたのでそれを利用した。あと,物理行対応版の挙動を以下のように変更。

  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(改行じゃなくて折り返し)
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaa|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

この位置にカーソル ( | )がいるときにC-aを押すと,

  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

ここに移動。もう一度押すと

  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

ここに移動。さらにもう一度押すと

  |aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

となり以下行頭とインデントの頭を行き来する。
てな感じで動作にend-of-visual-lineとの対称性を持たせてみました。
言葉で説明すると伝わりにくいですね。是非是非上記の関数と以下の設定を.emacsに貼り付けて使ってみてください。

(global-set-key "\C-a" 'beginning-of-visual-indented-line)
(global-set-key "\C-e" 'end-of-visual-line)