行末C-fでdabbrev-expandする

Emacsdabbrev-expand(動的補完)は便利だが、デフォルトのキーバインドM-/となっておりやや使いにくい。 そこで、カーソルが行末の場合に限りC-fdabbrev-expandするようにしてみる。

;; intelligent C-f/C-b
(defun forward-char-or-dabbrev-expand (arg)
  (interactive "^p")
  (if (and (= arg 1) (= (point) (line-end-position)))
      (dabbrev-expand nil)
    (forward-char arg)))
(global-set-key "\C-f" 'forward-char-or-dabbrev-expand)

(defun backward-char-or-backward-kill-word (arg)
  (interactive "^p")
  (if (and (= arg 1) (= (point) (line-end-position)))
      (backward-kill-word 1)
    (backward-char arg)))
(global-set-key "\C-b" 'backward-char-or-backward-kill-word)

上の内容を~/.emacsなどに追記することで、C-fを押したとき行末ならdabbrev-expand、それ以外の場合はforward-charを行うようになる。 また、合わせてC-bについても行末の場合に限りbackward-kill-wordするようにしている。 いずれの場合もC-uでprefix argumentを与えた場合は、本来の動作を行う。

1ストロークで補完、修正できるようになって便利。

C-bでdabbrev-expandする前に戻す(2014-11-30追記)

backward-kill-wordだとdabbrev-expandする前に入力していた文字列が消えてしまうので、行末C-fの後にC-bを押した場合はundoするようにしてみる。

;; intelligent C-f/C-b
(defun forward-char-or-dabbrev-expand (arg)
  (interactive "^p")
  (cond
   ((and (= arg 1) (= (point) (line-end-position)))
    (if (eq last-command this-command)
        (setq forward-char-or-dabbrev-expand-repeat-count (1+ forward-char-or-dabbrev-expand-repeat-count))
      (setq forward-char-or-dabbrev-expand-repeat-count 1))
    (dabbrev-expand nil))
   (t
    (forward-char arg))))
(global-set-key "\C-f" 'forward-char-or-dabbrev-expand)

(defun backward-char-or-backward-kill-word (arg)
  (interactive "^p")
  (cond
   ((and (= arg 1) (= (point) (line-end-position)))
    (if (eq last-command 'forward-char-or-dabbrev-expand)
        (undo forward-char-or-dabbrev-expand-repeat-count)
      (backward-kill-word 1)))
   (t
    (backward-char arg))))
(global-set-key "\C-b" 'backward-char-or-backward-kill-word)

上のコードでは繰り返しC-fを押していた場合、その回数だけundoを行う。

関連リンク