リージョン選択(松山智大)
「Emacsのトラノマキ」連載第五回「リージョン選択」
リージョン選択
前回は、コピーアンドペーストというエディタにおけるごく基本的な操作を通して、リージョンの概念と基本操作を説明しました。今回は、前回あまり説明しなかったリージョン選択を、具体的に実用できるものとして取り上げたいと思います。
(Emacsにおける)リージョン選択という操作では、前回説明したC-SPC
でマークを設置してカーソルを移動することによりリージョン選択を行う方法は、ある意味では最後の手段です。Emacsを利用する理由は人によって様々だと思いますが、Emacs使用者としておそらく追求すべきことは、タイプ量を減らすことです。それを考えると、例えばALongLongWordという単語をコピーするためにC-SPC C-f C-f C-f ...
とカーソル移動を何度も行うのはEmacs使用者として怠惰であると言えます。この場合だと、前方に単語移動するM-f (forward-word)
を使ってC-SPC M-f
とするか、カーソル直後の単語をリージョン選択するM-@ (mark-word)
を使うのが正しいです。
Emacsを使う以上、タイプ量を減らす努力はすべきです。そのためにはまず、日頃自分が無意識に入力している冗長なキー入力を認識することからはじまります。問題を発見したら、既存のコマンドでそれを解決できないか調べます。一般的にはEmacsのinfoを読んだり、M-x apropos-command
でキーワードから該当のコマンドを探します。該当のコマンドがなければEmacs Lispを書いて自分でコマンドを作ることになります。
リージョン選択においてはおそらく、このような努力がある程度必要になるでしょう。というのも、残念ながら標準のEmacsではリージョン選択を行うのに必要なコマンドが若干不足しているのです。もちろん、ごく基本的なリージョン選択手段はちゃんと用意されていますし、普通に使う分なら問題ないでしょう。しかし、考えられる限り最小のタイプで目的を達成するという意味においては不足していると言えます。そのことに関する解決策は最後に一つ提案します。
前にちらりと示しましたが、リージョン選択には二つの手段があります。一つはコマンド一発で目的の「何か」をリージョン選択する手段です。これには例えば、先に示したM-@ (mark-word)
などがあります。知識として覚えておいて欲しいのですが、リージョン選択するコマンドにはmark
という名前が付くのが慣習です。そのためM-x apropos-command RET ^mark- RET
とすれば「何か」をリージョン選択するコマンドを一覧することができます。リージョン選択のもう一つの手段は、M-SPC
でマークを設置してから任意のカーソル移動で目的の範囲をリージョン選択するというものです。おそらく将来説明することになると思いますが、カーソル移動というのもEmacsにおける非常に重要な操作の一つになります。カーソル移動を学ぶということは、他の全操作に関して、その効率を倍加することに直結します。リージョン選択も例にもれず、C-SPC
でマークを設置した後のカーソル移動のスキルにその効率が大きく左右されるわけです。ただし今回は、できるだけ少ないタイプで目的を達成することに重きを置いているので、前者のコマンド一発でリージョン選択する手段についてのみ説明します。
以下によく使うリージョン選択コマンドを示します。
| コマンド | 説明 | キーバインド |
|-------------------+----------------------------------------+----------------------|
| mark-word | カーソル直後の単語をリージョン選択する | M-@ |
| mark-sexp | カーソル直後のS式をリージョン選択する | C-M-SPCあるいはC-M-@ |
| mark-paragraph | カーソルのある段落をリージョン選択する | M-h |
| mark-defun | 関数定義をリージョン選択する | C-M-h |
| mark-whole-buffer | バッファ全体をリージョン選択する | C-x h |
これらのコマンドは慣れれば非常に便利なコマンドです。ここでは簡単なユースケースを紹介するだけにとどめますが、しっかり身につけるようにしましょう。
mark-word
M-@ (mark-word)
はカーソル直後の単語をリージョン選択するコマンドです。コピーコマンドと組合せて、M-@ M-w
という一連のコマンドで覚えてしまうのがよいでしょう。mark-word
はカーソル直後の単語をリージョン選択するということに注意してください。例えばALongLongWordのWにカーソルがある状態でmark-word
してもWordがリージョン選択されるだけで、ALongLongWord全体がリージョン選択されるわけではありません。この動作については後述します。M-@
した後にM-@
すると次の単語もリージョン選択します。これは複数の単語をリージョン選択するのに便利なので覚えておいてください。
mark-sexp
C-M-SPC (mark-sexp)
はカーソル直後のS式をリージョン選択するコマンドです。コピーコマンドと組合せて、C-M-SPC M-w
という一連のコマンドで覚えてしまうのがよいでしょう。mark-sexp
はS式をリージョン選択する点以外はmark-word
と同じです。S式は任意のEmacs Lispの式を意味しているので、シンボルやリストや文字列は全てmark-sexp
でリージョン選択することができます。Emacs Lispを知らない人のためにどういったものがS式となるか例示しておきます。
- ALongLongWordやa_long_long_wordのようなシンボル
- 1234のような数値
(a b c)
のようなリスト"Hello World"
のような文字列表記
mark-sexp
は使い方によっては非常に便利な道具になります。例えばa_long_long_wordという単語(*)を一発でリージョン選択するにはmark-sexp
を使います。mark-word
では4回mark-word
を実行する必要がありますが、mark-sexp
なら一回で済みます。
(*) CやC++のコードにはありがちな名前です。
次に以下のCのコードを考えてみましょう。
if (cond1
|| cond2
|| cond2
|| (cond3 && cond4)) {
...
}
何らかの理由でこのコードのif文の条件部をコピーしたくなったとします。その場合もmark-sexp
を使えばすぐさまコピー可能な状態にもっていくことができます。操作は簡単で、ifの後の最初の開き括弧にカーソルを移動してmark-sexp
するだけです。Cのコードであってもほとんどの場合はS式で解釈できる形になっているので、このような利用が可能なわけです。
最後に"Hello World"
のような文字列表記をコピーするケースを考えてみます。このケースも先のケースと同じで、最初のダブルクオート(")にカーソルを移動してmark-sexp
するだけです。これを利用することでCやJavaの文字列表記を簡単にコピーすることができます。
mark-paragraph
M-h (mark-paragraph)
はカーソルがある段落をリージョン選択するコマンドです。例として、文章を書いている時に、現在の段落を別の場所に移動するケースを考えてみましょう。まずM-h
で現在の段落をリージョン選択します。次にC-w
でリージョン選択した段落をカットします。続いて段落の移動先にカーソルを移動します。この時M-{ (backward-paragraph)
やM-} (forward-paragraph)
を利用すると、より簡単に目的の位置に移動できるでしょう。最後にC-y
でカットした内容をペーストすれば完了です。
mark-paragraph
は時として最も有用なリージョン選択コマンドであることがあります。例えば、ソースコードをある一定の概念を改行で区切って記述している場合や、リージョン選択したい範囲が偶然改行が区切られている場合、それを段落とみなすことによりmark-paragraph
を利用することができます。例えば、レコードが改行で区切られたデータベースで、特定のレコードをコピーするケースを考えてみます。
ID: xxx
Title: First record
Date: 2009/7/2
ID: yyy
Title: Second record
Date: 2009/7/4
ID: zzz
Title: Third record
Date: 2009/7/9
ID=yyy
のレコードをコピーするには、そのレコードまでカーソルを移動してM-h M-w
します。このような操作は最初はなかなか指が動いてくれないものです。しかし慣れてしまえば指が自然に動くようになり、効率も次第に向上していきます。
mark-defun
C-M-h (mark-defun)
は関数定義をリージョン選択するコマンドです。関数定義はモードごとに適切に解釈されます。mark-defun
は言うまでもなく、関数定義をカットしたりコピーするのに便利です。関数定義の移動は、前節の段落の移動と同じように行うことができます。まずC-M-h
で関数定義をリージョン選択します。次にC-w
でリージョン選択した関数定義をカットします。続いて関数定義の移動先にカーソルを移動します。この時C-M-a (beginning-of-defun)
やC-M-e (end-of-defun)
を利用すると、より簡単に目的の位置に移動できるでしょう。最後にC-y
でカットした内容をペーストすれば完了です。
mark-whole-buffer
C-x h (mark-whole-buffer)
はバッファ全体をリージョン選択するコマンドです。コピーコマンドと組合せて、C-x h M-w
という一連のコマンドで覚えてしまうのがよいでしょう。
コラム: C-x C-x (exchange-point-and-mark)
上記で説明したコマンドを利用してリージョン選択したときに、想定した範囲とは違う範囲がリージョン選択されてしまうことがあります。その場合は、通常のカーソル移動とC-x C-x (exchange-point-and-mark)
を組合せてリージョン選択の範囲を調整します。C-x C-x
はカーソルの位置とリージョン選択の開始位置(マーク)を交換するコマンドで、リージョン選択の範囲を調整する場合は、適宜、カーソルとマークを入れかえて両端の位置を調整します。例えば、M-h (mark-paragraph)
したら、想定したより上からリージョン選択されてしまった場合、C-x C-x
でマークとカーソルを入れかえて、カーソルで開始位置を調整します。
C-x C-x
は他にも、A点とB点を行き来しながら編集するのに使ったり、リージョン選択が画面内に収まらないときに開始位置と終了位置を確認するのにも使えます。地味なコマンドですが、細かな所で非常に有用なコマンドなのです。
コラム: 表の整形
Emacsにおいて表を書く方法は色々あります。一番単純な方法は任意のフォーマットで表を書いてalign
コマンドやalign-regexp
コマンドで表として整形する方法でしょう。しかしこれらのコマンドではなかなかうまく整形できないことが多いです。table.el
(*)などの拡張を使用するのは一つの手ですが、拡張をインストールするのが面倒くさいです。最近発見したことですが、実はEmacs22から標準で搭載されたorg-mode
という拡張アウトライン編集モードの表整形機能を利用することにより、もっと簡単にもっと美しく表を整形することができます。
(*) http://taiyaki.org/elisp/table/
例えば次のような未整形な表があるとします。任意のフォーマットで表を書いて、
|コマンド|説明|キーバインド|
|mark-word|カーソル直後の単語をリージョン選択する|M-@|
|mark-sexp|カーソル直後のS式をリージョン選択する|C-M-SPCあるいはC-M-@|
|mark-paragraph|カーソルのある段落をリージョン選択する|M-h|
|mark-defun|関数定義をリージョン選択する|C-M-h|
|mark-whole-buffer|バッファ全体をリージョン選択する|C-xh|
これを整形するには、M-h (mark-paragraph)
などでリージョン選択して(*)、M-x org-table-align
を実行します。その結果は以下のようになります。
(*) 実はリージョン選択する必要はなく、org-align-table
が表の範囲を自動的に推測してくれます。
| コマンド | 説明 | キーバインド |
| mark-word | カーソル直後の単語をリージョン選択する | M-@ |
| mark-sexp | カーソル直後のS式をリージョン選択する | C-M-SPCあるいはC-M-@ |
| mark-paragraph | カーソルのある段落をリージョン選択する | M-h |
| mark-defun | 関数定義をリージョン選択する | C-M-h |
| mark-whole-buffer | バッファ全体をリージョン選択する | C-xh |
なお、あらかじめorg
をロードしておく必要があります。よくわからない人は次のコードを~/.emacs
に書いておいてください。
(require 'org)
矩形選択
出鼻を挫くようですが、Emacsには矩形選択という概念が存在しません。つまり矩形選択を視覚的に感知することができないのです。その代わりにリージョン選択を矩形選択とみなして処理する矩形編集コマンドが存在します。少し趣旨とは離れるかもしれませんが、ここでは矩形編集について説明します。おそらく一度は目にした事があると思いますが、C-x r t
やC-x r k
が矩形編集コマンドです。
矩形選択は視覚的に感知できない上、C-x r t
やらC-x r t
やら長ったらしいコマンドを覚えるのは大変なので、おそらく多くの人は矩形編集を活用できないままでいると思います。ここではそのような人を助けるための機能や拡張を紹介したいと思います。
sense-region.el
sense-region.el
は矩形選択を視覚的に表示してくれる拡張です。また矩形に対してカットやコピーを行う機能も提供しています。
sense-region.el
は以下のURLからダウンロードできます。
http://taiyaki.org/elisp/sense-region/src/sense-region_2002-05-23.el
load-path
の通ったディレクトリにコピーしたら次のコードを~/.emacs
に書いておきましょう。
(require 'sense-region)
(sense-region-on)
使い方は簡単です。まず次のように普通にリージョン選択します。
その状態でC-SPC
を押します。すると矩形選択が視覚的になります。
ここでC-w (kill-region)
やM-w (kill-ring-save)
するとリージョン選択されたテキストではなく、矩形選択されたテキストがカット、コピーされます。非常に直感的です。
また、M-% (query-replace)
やC-M-% (query-replace-regexp)
で矩形選択したテキストだけに置換を適用するといったことも可能です。
cua-mode
cua-mode
のcuaとはCommon User Accessの略で、一般的なエディタのインターフェース(例えばC-c
でコピー)をEmacsで再現するためのモードです。が、著者としてはC-c
でコピーしたりC-v
でペーストするのはEmacsでは邪道なので全くお勧めしません。ではなぜ紹介したかというと、cua-mode
に含まれる矩形編集機能が大変便利だからです。cua-mode
の本来の機能を殺して、この矩形編集機能だけ利用するには~/.emacs
に次のように書きます。なお、cua-mode
はEmacsに標準で搭載されているので、特にインストールする必要はありません。
(cua-mode t)
;; C-cやC-vの乗っ取りを阻止
(setq cua-enable-cua-keys nil)
cua-mode
の矩形編集機能を使うにはC-RET
を押します。もしEmacsをターミナル上で動かしている場合はM-x cua-set-rectangle-mark
とするか、cua-set-rectangle-mark
コマンドを適当なキーに割り当ててください。
さて、C-RET
を押してカーソルを移動すると次のようになります。
この状態で適当に文字を入力してみましょう。ここでは-bar
と入力します。すると次のようになります。
またバックスラッシュキーで文字を矩形にそって削除できることも確認してください。
sense-region.el
と同様、C-w (kill-region)
やM-w (kill-ring-save)
も可能です。
sense-region.el
との大きな違いは、追加や削除に加えてさまざまなコマンドが用意されている点です。矩形編集で使える主なコマンドを以下に示します。
| キーバインド | 説明 |
| M-b | 矩形をスペースで埋める |
| M-f | 矩形を入力された1文字で埋める |
| M-i | 矩形の各行の数値をインクリメントする |
| M-k | 矩形をキルする |
| M-n | 矩形の各行にインクリメントされた数値をフォーマットして挿入する |
| M-r | 矩形を置換する |
| M-t | 矩形を入力された文字列で埋める |
| M-| | 矩形を入力としてシェルコマンドを実行する。引数が指定されている場合はシェルコマンドの結果が矩形に埋まる |
| M-/ | 矩形の正規表現にマッチする行をハイライト |
どのコマンドも便利なのですが、この中では特にM-n
が便利だと思います。M-n
を使えば矩形内に特定のフォーマットに従って連番をふることができます。例えば0から+1していく連番をふる場合はM-n 0 RET 1 RET %d RET
ですし、0から+1していく16進数の連番はM-n 0 RET 1 RET %x RET
です。
例えばfoo1からfoo9という名前を一覧するケースを考えてみましょう。まずC-u 10 RET
して10個の改行を挿入します。次に最初の行でC-RET
して最後の行までカーソルを移動します。
そしてM-n
します。最初に開始値1を入力します。次にインクリメント値1を入力します。最後にフォーマットを入力します。ここではfoo%d
と入力します。このフォーマットはformat
関数で使えるものである必要があります。次に示すのがその結果です。
これが矩形選択内で使えるので、例えばデータを作る場合などで重宝すると思います。
isearch
M-@ (mark-word)
やC-M-@ (mark-sexp)
でリージョン選択したテキストを使ってisearchしたいということがしばしばあります。isearchとしてはC-s C-w
で検索単語を拾うのが正攻法なのですが、人間というのは曖昧なもので前後が逆になるというのは往々にして発生します。これを解決するために次のコードを~/.emacs
に書いてください。
(defadvice isearch-mode (around isearch-mode-default-string (forward &optional regexp op-fun recursive-edit word-p) activate)
(if (and transient-mark-mode mark-active (not (eq (mark) (point))))
(progn
(isearch-update-ring (buffer-substring-no-properties (mark) (point)))
(deactivate-mark)
ad-do-it
(if (not forward)
(isearch-repeat-backward)
(goto-char (mark))
(isearch-repeat-forward)))
ad-do-it))
これによりリージョン選択した状態でC-s (isearch-forward)
やC-r (isearch-backward)
を実行すると、リージョン選択されたテキストが検索文字列としてあらかじめ設定された状態でisearchがはじまります。
なお、この方法はリージョン選択をisearchで伸ばす人には不便な代物でしかないでしょう。
thing
冒頭で宣言したとおり、Emacsにおけるリージョン選択機能の不足を解決するための方法を一つ提案します。M-@ (mark-word)
やC-M-SPC (mark-sexp)
を実際に使ってみて体で感じた人なら分かるかもしれませんが、Emacsのリージョン選択で、ある意味致命的なのは、おそらく最も頻繁に扱うであろう単語単位でのリージョン選択が極めて不十分という点に要約されると思います。もう一度、mark-word
の説明を確認してみると、「カーソル直後の単語をリージョン選択する」となっていることが分かります。つまり単語の途中にカーソルがあるときにmark-word
しても、カーソル直前の単語はリージョン選択されないということです。そのため、単語の途中にカーソルがある場合は、一度M-b (backward-word)
などで単語単位で後ろに戻ってからmark-word
する必要があるのです。なんだか面倒くさいですし、直感的ではありません。
Emacsの好敵手であるVimでは、この辺りの扱いが秀逸です。Vimではテキスト内の何らかの概念に該当する部分文字列をテキストオブジェクトと呼び、ユーザーはモーションにテキストオブジェクトを指定することにより、そのテキストオブジェクトにオペレーションを実行することができます。例えば、指定されたモーションを削除した後に編集モードになるc
というオペレーションと、iw
という単語を表わすテキストオブジェクトをモーションとして用いて、ciw
というコマンドを実行することにより、カーソルが指している単語を消して編集モードになることができます。また、テキストオブジェクトとしてHTMLタグや文字列表記、括弧なども使用でき、これらは任意のオペレーションと自由に組合せることができます。
一方Emacsはと言うと、Vimのテキストオブジェクトと同じように何らかの概念を持つ部分文字列を抽象的に表現するthing
という機構はあるものの、Vimで言うところのオペレーションが欠如しています。つまり対象を表わす手段はあるが、その対象をどうしたらいいか分からない、というのが現状です。thing
に関して言えば、非常に柔軟性が高く、ユーザーは自由に新しいthing
を定義することができます。例えば、前節でmark-defun
やmark-paragraph
の説明を行いましたが、これらは、考え方を変えれば、関数定義や段落といったthing
に対して処理を行っていると考えることができます。また、カーソルが指しているURLを外部ブラウザで開くコマンドbrowse-url-at-point
は、url
というthing
を定義することにより、うまくURLを抽出するようにしています。しかし、thing
を直接操作するコマンドは標準では用意されていません。その点もVimと比べて劣る点だと思います。
紙面の都合上、thing
についての詳しい説明は割愛しますが、簡単な原理だけ説明しておきます。thing
はシンボルで具現化されます。例えば単語のthing
ならword
です。カーソルが指しているthing
を取得するには、thing-at-point
関数を使います。カーソルがHelloを指している状態でM-: (thing-at-point 'word)
を評価すると"Hello"
が返ってくるはずです。この時、内部的にforward-word
という関数が呼び出され、単語の開始位置と終了位置を割り出しています。開始位置と終了位置が分かれば、その部分文字列を返せばよいのです。
さて、前置きが長くなりましたが、本節ではthing
を活用してリージョン選択を(Vimのように)もっと効率よく行えるようにします。まず次のURLからthing-opt.el
をインストールしてください。
http://www.emacswiki.org/emacs/download/thing-opt.el
手前味噌で申しわけないのですが、この拡張はthing
を扱うために著者が作成したものです。使用するには次のコードを~/.emacs
に書いてください。
(require 'thing-opt)
この拡張は次の機能を提供しています。
| コマンド | 説明 |
| kill-thing | カーソルが指している`thing`をキルする |
| copy-thing | カーソルが指している`thing`をコピーする |
| mark-thing | カーソルが指している`thing`をマークする |
これらのコマンドは操作対象のthing
を尋ねてきます。例えば、単語を対象にするならword
、URLを対象にするならurl
を入力します。利用できるthing
はM-: (list-thing)
で確認できます。一々thing
の名前を入力するのが面倒なのでdefine-thing-commands
関数を呼び出して必要な関数を自動で定義させましょう。
(define-thing-commands)
これでmark-word*
(*)や`mark-url
などが使えるようになります。
(*) mark-wordはすでに使用されているのでこのような名前になります
単語を指した状態でM-x mark-word*
すると次のようになります。
thing-opt.el
は追加で文字列表記とリストのthing
を定義しています。文字列表記を指した状態でM-x mark-string
すると次のようになります。
リスト表記(...)を指した状態でM-x mark-up-list
すると次のようになります。
このようにthing
を用いることによりあらゆる対象を簡単に操作できるようになるのです。
これらのコマンドを使いやすくするために次のように割り当てるとよいでしょう。
(global-set-key (kbd "C-$") 'mark-word*)
(global-set-key (kbd "C-\"") 'mark-string)
(global-set-key (kbd "C-(") 'mark-up-list)
key-chord.el
key-chord.el
という面白い拡張を利用して、Vim風のUIを実現してみましょう。key-chord.el
はキーの同時押しにより任意のコマンドを実行できるようにする拡張です。key-chord.el
は次のURLから手に入ります。ちなみにchordとは和音という意味です。
http://www.emacswiki.org/cgi-bin/emacs/download/key-chord.el
インストールしたら次のコードを~/.emacs
に書いてください。
(require 'key-chord)
(key-chord-mode 1)
(setq key-chord-two-keys-delay 0.1)
(setq key-chord-one-keys-delay 0.1)
;; don't hijack input method!
(defadvice toggle-input-method (around toggle-input-method-around activate)
(let ((input-method-function-save input-method-function))
ad-do-it
(setq input-method-function input-method-function-save))))
key-chord-two-keys-delay
は同時押しの許容時間です。小さければ小さいほど同時押しの判定が厳しくなります。逆に大きすぎると意図せずにキーコードと判定され該当のコマンドが実行されます。
キーコードを定義するにはkey-chord-define-global
関数を使います。例えばj
とk
の同時押しでiswitchb-buffer
を実行するには次のように書きます。
(key-chord-define-global "jk" 'iswitchb-buffer)
さて、このkey-chord.el
を利用してthing
の操作をVim風にしてみましょう。先ほど定義したコマンドを利用してキーコードを定義すると次のようになるでしょう。なお、Vimでは-d
がカットするオペレーションを、y
がコピーするオペレーションを、v
がマークするオペレーションを表わしています。
(key-chord-define-global "dw" 'kill-word*)
(key-chord-define-global "yw" 'copy-word)
(key-chord-define-global "vw" 'mark-word*)
(key-chord-define-global "ds" 'kill-sexp*)
(key-chord-define-global "ys" 'copy-sexp)
(key-chord-define-global "vs" 'mark-sexp*)
(key-chord-define-global "dq" 'kill-string)
(key-chord-define-global "yq" 'copy-string)
(key-chord-define-global "vq" 'mark-string)
(key-chord-define-global "dl" 'kill-up-list)
(key-chord-define-global "yl" 'copy-up-list)
(key-chord-define-global "vl" 'mark-up-list)
上記のコードを見れば分かると思いますが、一応使い方を説明しておきます。
| キーコード | コマンド | 説明 |
| dw | kill-word* | カーソルが指している単語をカット |
| yw | copy-word | カーソルが指している単語をコピー |
| vw | mark-word* | カーソルが指している単語をリージョン選択 |
| ds | kill-sexp* | カーソルが指しているS式をカット |
| ys | copy-sexp | カーソルが指しているS式をコピー |
| vs | mark-sexp* | カーソルが指しているS式をリージョン選択 |
| dq | kill-string | カーソルが指している文字列表記をカット |
| ys | copy-string | カーソルが指している文字列表記をコピー |
| vs | mark-string | カーソルが指している文字列表記をリージョン選択 |
| dl | kill-up-list | カーソルが指しているリスト表記をカット |
| yl | copy-up-list | カーソルが指しているリスト表記をコピー |
| vl | mark-up-list | カーソルが指しているリスト表記をリージョン選択 |
まとめ
今回はリージョン選択の方法として、mark-paragraph
などの基本的なものから、最後のkey-chord.el
を使用した前衛的なものまで紹介しました。今回示した内容からも分かるように、リージョン選択にはまだまだ改善の余地があります。いかにすばやく、かつ脳へのオーバーヘッドを最小に抑えて、目的のリージョンを選択するか。なかなか難しい問題です。Vimはその点に関してEmacsの一歩先を行っています。もちろんそれはEmacsとVimで最も違う部分が起因しているのですが、だからといってEmacsがこのまま取り残されていいわけではありません。日頃意識してEmacsが他のエディタに遅れをとらない優れたエディタであり続けるよう努力しましょう。