Emacsのcua-modeを使っていない、あるいはそもそも知らない人が結構いるようなので紹介しておく。cua-modeは、Emacsの範囲選択にまつわるUIを改善し、Windows、Mac、GTK+/Qtなどにおけるテキスト編集操作との互換性も高めてくれるグローバルマイナーモードで、以下のような機能を提供する。

  • Shift+矢印による範囲選択
  • 範囲選択状態でBS/DELを押すと選択範囲をまるごと消去
  • 範囲選択状態でキー入力やペーストを行うと選択範囲まるごと上書きされる
  • 視覚化された矩形範囲選択モード(C-w, M-w, C-yなど通常の範囲選択と同様の操作性)
  • 矩形範囲選択モードでの複数行同時操作(文字入力、文字削除、連番挿入等)
  • Windows互換のCtrl+Z,X,C,V(※)

Emacs 22.1.1から標準添付されているので、試したければ何も設定せずにM-x cua-modeで使える。上記のうち最後の機能は率直に言って邪魔なのだが、これはWindowsから来た人をターゲットに据えた本モードの目玉機能のようで、デフォルトでオンになっている。ために、Emacsに慣れた人ほど、少し触ったところで戸惑いを感じて敬遠しがちなのが残念なところ。
このcua-modeを起動時から有効化するには、M-x customize-group RET cua RETとしてcustomize画面に入り、”Cua Mode”を”on”にする。私のように上記※が不要だと思う人は”Cua Enable Cua Keys”を”Disabled”にして、”Set for current session”を押す。これでcua-modeが(一時的に)有効な状態になるので、他のバッファで挙動を確認してみよう。満足したら、customizeバッファに戻って”Save for future sessions”を押せば恒久保存される。
さて、Shift+矢印による範囲選択を試してみただろうか。GUI上のEmacsで動くのは当然として、xterm互換ターミナル上のEmacsでも動くのには軽い感動を覚えたかもしれない。ただし、Emacsのバグで、S-left, S-right, S-downは動くのになぜかS-upだけは期待通り動作せず、selectキーとして認識されてしまう。これは以下のようなコードで期待通り動くようになる。(ついでにendキーがおかしいのも直している)

(defadvice terminal-init-xterm (after fix-some-keys activate)
  (define-key input-decode-map "\e[1;2A" [S-up])
  (define-key input-decode-map "\e[4~" [end]))

ところで、矩形選択モードのトグルキーはデフォルトではC-RETだが、私はcua-toggle-global-markの方に割り当てられているC-S-SPCに変更している。これは、先のカスタマイズ画面で”Cua Rectangle Mark Key”をC-S-SPCに設定(入力欄でC-qを押してから設定したいキーコンボを押すのが楽)して保存すれば済むはずだが、cuaの初期化フローがおかしいため、以下のコードも必要のようだ。

(define-key cua-global-keymap cua-rectangle-mark-key 'cua-set-rectangle-mark)

cua-toggle-global-markの方は、カスタマイズ変数がないので以下のようにコードを書いてC->に設定している。

(define-key cua-global-keymap (kbd "C->") 'cua-toggle-global-mark)

なお、C-RET, C-S-SPC, C->などの特殊キーコンボをターミナル上で使うためにはターミナルエミュレータの設定が必要なので、こちらの記事を参考にされたい。
というわけでおしまい、でもいいのだけれど、矩形選択モードで単語単位の移動ができないのはちょっと不便だと思う私はこんな設定を施している。

(eval-after-load "cua-rect"
  '(progn
     (defun cua-resize-rectangle-move-bol ()
       "Resize rectangle to the BOL."
       (interactive)
       (while (not (bolp)) (backward-char)))
     (defun cua-resize-rectangle-move-eol ()
       "Resize rectangle to the EOL."
       (interactive)
       (while (not (eolp)) (forward-char)))
     (defun cua-resize-rectangle-right-word (n)
       "Resize rectangle to the right word."
       (interactive "p")
       (if (< n 0)
         (let ((pos (save-excursion (backward-word (- n)) (point))))
           (while (< pos (point)) (backward-char)))
         (let ((pos (save-excursion (forward-word n) (point))))
           (while (< (point) pos) (forward-char)))))
      (defun cua-resize-rectangle-left-word (n)
        "Resize rectangle to the left word."
        (interactive "p")
        (cua-resize-rectangle-right-word (- n)))
      (defadvice cua--init-rectangles
        (after custom-key-bindings () activate)
        (define-key cua--rectangle-keymap [remap move-end-of-line]         'cua-resize-rectangle-move-eol)
        (define-key cua--rectangle-keymap [remap move-beginning-of-line]   'cua-resize-rectangle-move-bol)
        (define-key cua--rectangle-keymap [remap forward-word]             'cua-resize-rectangle-right-word)
        (define-key cua--rectangle-keymap [remap backward-word]            'cua-resize-rectangle-left-word)
        (cua--rect-M/H-key ?B 'cua-blank-rectangle)
        (cua--rect-M/H-key ?b 'cua-resize-rectangle-left-word)
        (cua--rect-M/H-key ?F 'cua-fill-char-rectangle)
        (cua--rect-M/H-key ?f 'cua-resize-rectangle-right-word))))

癖のあるモジュールだけど、がんばって飼い慣らして使いましょう。

Tags :
Categories : Tech