リージョンをペアとなる文字で囲う

Vimの surround.vimのように指定した範囲を囲うということが
Emacsでもできたらいいなと思って調べてみるといくつ見つかった
ので、調べた insert-pairというものと自分が書いた elispについて
紹介します。

insert-pair

http://atomized.org/2008/08/useful-insert-pair/


指定した文字と insert-pair-alistという alistに格納されている
対応する文字を挿入するというものです。サイトのままですが、
以下のように設定すると使えます。

(define-key global-map (kbd "M-\'") 'insert-pair)
(define-key global-map (kbd "M-\"") 'insert-pair)
(define-key global-map (kbd "M-[") 'insert-pair)
(define-key global-map (kbd "C-c `") 'insert-pair-region)

ただ上記で指定したコマンドを実行すると、ある文字とそれと
対となる文字を連続して挿入するだけになります。

  ;; □はカーソル位置
  □apple melon orange
  ;; M-"
  ""apple melon orange

単語を囲む場合は M-数字をプレフィックスとして与えます。

   □apple melon orange
   ;; M-1 M-"
   "apple" melon orange

   apple□melon orange
   ;; M-2 M-"
   apple "melon orange"

すぐ見てわかる範囲ならいいんだけど、かなり離れていると
とっさに単語数がわからないし、複数文字で囲いたいときも
あるよなってことで、自分で書いてみました。

insert-pair-region

コードは以下のようになりました。

(define-key global-map (kbd "C-c `") 'insert-pair-region)

(defun insert-pair-region (start end str)
  (interactive
   (list (region-beginning) (region-end)
         (read-string "Insert string: ")))
  (save-excursion
    (goto-char start)
    (setq start (point-marker))
    (goto-char end)
    (setq end (point-marker))
    (let* ((pair-str (mapconcat #'insert-pair-region:find-pair str ""))
           (rev-pair-str (apply 'string (reverse (string-to-list pair-str)))))
      (goto-char start)
      (insert-string str)
      (goto-char end)
      (insert-string rev-pair-str)))
  (goto-char start))

(defun insert-pair-region:find-pair (chr)
  (let ((left (assoc chr insert-pair-alist))
        (right (rassoc (list chr) insert-pair-alist)))
    (char-to-string (cond (left (cadr left))
                          (right (car right))
                          (t chr)))))

実例は以下のようになります。

  apple
  ;; appleをリージョンで指定して C-c ` (<[
  (<[apple]>)
  ;; insert-pair-alistにペアが存在しない文字はそのまま表示
  ;; 上記の文字列をリージョン指定して C-c` orange
  orange(<[apple]>)egnaro

となります。


ネタとしては

  (´д`)
  ;; リージョン指定して C-c ` 工工エエエエエェェ
  工工エエエエエェェ(´д`)ェェエエエエエ工工

というようなこともできます。

おわりに

リージョンを指定した文字列で囲う方法について示しました。
デフォルトでありそうな気もするので、何かありましたら、
教えてください。

Vimテクニックバイブル ?作業効率をカイゼンする150の技

Vimテクニックバイブル ?作業効率をカイゼンする150の技