Mark から開始したときは、オリジナルの forward-word を使用、それ以外は単語の先頭に移動する

http://d.hatena.ne.jp/kitokitoki/20091128/p2 で、M-f が単語の先頭に移動できて快適だったけど、問題が。単語をコピーしようとすると、単語の先頭に移動するものだから、コピーした尻にスペースが入る。

  • Mark (C-space) から開始したときは、通常のforward-word
  • それ以外は単語の先頭に移動
  • ついでに、日本語の文節移動も可

にしたい。

日本語を考慮してforward-word - とりあえず暇だったし何となくはじめたブログ を参考に何とかしようとしたけど、自分の Emacs Lisp 技術では付いていけない。

何かごちゃごちゃしているけど、これで良いことにする。

;; Mark から開始したときは、オリジナルの forward-word を使用
;; それ以外は単語の先頭に移動する
(defvar my-forward-word-flag nil) ;; Mark から開始したかどうか
(defun my-forward-word (arg)
  (interactive "p")

  ;; M-f 以外だったら、フラグ を nil
  (if (not (eq last-command 'my-forward-word))
        (setq my-forward-word-flag nil))

  (if (or my-forward-word-flag (eq last-command 'set-mark-command))
      (progn
        ;; Mark が起点のときは、フラグを立てて通常の forward-word
        (setq my-forward-word-flag t)
        (forward-word arg))
    (if (looking-at ".$")
        ;; 行末時は、単語の先頭へ移動
        (re-search-forward "\\W\\b\\")
        (if (looking-at "\\cj")
            (progn
              ;; 日本語の途中のときは、通常の forward-word。日本語の文節移動
              (forward-word arg)
              (if (looking-at "\\(。\\|、\\|.\\|,\\)")
                  ;; 。、.,で止まったときは、その後ろへ移動
                  (re-search-forward "\[。、.,\]+")))
          ;; 行末以外または日本語の途中以外のときは、行末または単語の先頭に移動
          (re-search-forward "\\(.$\\|\\W\\b\\)")))))
(global-set-key "\M-f" 'my-forward-word)