kill-word-camelcased.el

Swiftにおいて識別子はキャメルケースとすることが推奨されています。当然Cocoa APIもそれに従っており、さらにとても長い(ex. NSPersistentStoreCoordinatorStoresDidChange)。Emacsで編集する場合、kill-word [M-d]backward-kill-word [M-DEL]するとキャメルケースで合成された識別子はひとつの単語として扱われるため、煩わしいと思うことがあります。そんなわけで大文字化された部分で、単語を区切るようにする関数を書きました。gist

(defun kill-word-camelcased (arg)
  "Kill characters forward until the end of a word even if 
in a camelcased identifier. ARG is same as `kill-word`."
  (interactive "p")
  (let ((case-fold-search nil)
        (start (point))
        (bound (save-excursion (forward-word arg) (point)))
        (succ (if (> arg 0) 1 -1))
        current
        found)
    (when (not (= start bound))
      (setq current start)
      (while (not (= arg 0))
        (forward-word succ)
        (while (search-forward-regexp "[A-Z][a-z]"
                                      (+ current succ)
                                      t
                                      (- succ))
          (setq found t))
        (when (and found (< succ 0))
          (forward-char -2))
        (setq current (point))
        (setq arg (- arg succ)))
      (kill-region start (point)))))

(defun backward-kill-word-camelcased (arg)
  (interactive "p")
  (kill-word-camelcased (- arg)))

当初、add-advicekill-wordを上書きしようと思っていましたが、影響範囲が広そうなことと、Infoにおいてもadviceよりもhookやkeyremapの利用をまず考えるべきとあったので、swift-modeでkill-word及びbackward-kill-wordを上書きし利用します。

(define-key swift-mode-map [remap kill-word] 'kill-word-camelcased)
(define-key swift-mode-map [remap backward-kill-word] 'backward-kill-word-camelcased)