Then you will see, it is not the spoon that bends, it is only yourself.
The Matrix
EmacsあるいはVimに慣れ親しんでいれば, Evilを使うのにある程度は勝手がわかるものの, 逆にしっくりこない点も多いでしょう. EvilはEmacsの機能との相互運用性を重視していることから, Vimユーザにとって不慣れな点が生じることは避けられず, EvilがVimをエミュレートする以上, Emacsユーザにとって不慣れな点が生じることも避けられません. 本稿では, どちらに慣れ親しんだユーザにとっても快適に使えるようにEvilをカスタマイズするためのヒントを紹介します. ただし, いくらカスタマイズしても完全なVimや完全なEmacsになることはありません. 使い勝手をよくして自分の好みに合わせながら, できるだけEvilのやり方に慣れていくように努めることが大切でしょう.
キーマップ
Evilの操作性を好みに合うようにするために一番多用するのは, キー設定でしょう. キー設定をするためには, それぞれのステートでどのようなキーマップが使用されるかに加えて, Emacsのキーマップの優先順位について理解する必要があります.
Emacsのキーマップは階層化されていて, あるキーを押したときには, 上の層から順に探索し, 条件に従って使うキーマップを決めます*1.
overriding-terminal-local-map
が定義されていればこれを使うoverriding-local-map
が定義されていればこれを使う- 以下のいずれかのキーマップにキーが存在していれば, そのキーマップを使う
- カーソル位置の文字の
keymap
プロパティ emulation-mode-map-alists
中のアクティブなモードのマップminor-mode-overriding-map-alist
中のアクティブなモードのマップminor-mode-map-alist
中のアクティブなモードのマップ- カーソル位置の文字の
local-map
プロパティ (current-local-map)
- カーソル位置の文字の
これらの条件によりキーマップが選択され, 結果としてそのキーマップ中に該当するキーがなければ, (current-global-map)
を使います. (current-global-map)
にも該当するキーがなければ, 「key is undefined
」のようなメッセージが表示されます.
ふつうのメジャーモードのキーマップは(current-local-map)
, マイナーモードのキーマップはminor-mode-map-alist
に設定されています. そしてminor-mode-overriding-map-alist
は, メジャーモードがマイナーモードのキーマップよりも優先するキーを設定するためにあります.
Evilは内部的にはマイナーモードで実装されていますが, その役割はEmacs全体のキー操作を根本から変えるものであるため, ふつうのメジャーモードやマイナーモードよりも優先してキーを受け取れなければなりません. このため, Evilに関するキーはすべてemulation-mode-map-alists
に設定され*2, ふつうのメジャーモードやマイナーモードよりもEvilのキーの方が基本的には優先されます. 逆に, Evilのキーが他のキーバインドに奪われてしまう場合は, emulation-mode-map-alists
よりも上位の層にそのキーがないか確認するとよいでしょう. たとえば, カーソル位置の文字のkeymap
プロパティが設定されている場合はこれが優先されることを知らないと, このキーマップの存在に思い至ることすら困難です.
特定のステートでのキー
あるステートで使うキーを設定するには, 設定ファイル(~/.emacs
や~/.emacs.d/init.el
等)の(require 'evil)
の後に, (define-key evil-state-state-map key definition
)の行を追加します. たとえば, モーションステートで;
を:
(evil-ex
)に割り当てるには,
(define-key evil-motion-state-map (kbd ";") #'evil-ex)
とします.
state
はnormal
, insert
, visual
, operator
, replace
, motion
のいずれかです. normal
はノーマルステート, insert
は挿入ステート, visual
はビジュアルステート(範囲選択中のステート), operator
はオペレータ待機ステート(オペレータを入力してから後続のキーを入力するまでのステート), replace
は置換ステート(R
したときのステート), motion
は編集を伴わない状態を表すためのステートです. motion
ステートで定義されたキーはnormal
やvisual
でも使えます. normal
で定義されたキーはvisual
でも使えます.
definition
には上の例のようなコマンドのシンボルの他に, 文字列(キーボードマクロとして動作), キーマップ(プレフィックスキーの定義になる)なども渡すことができます. 詳しくはM-x describe-function RET define-key RET
を参照して下さい.
既に定義されているキーを削除するには, define-key
にdefinition
としてnil
を渡します. たとえば, 挿入ステートでC-y
をふつうのEmacsのコマンド(yank
)にするには, evil-insert-state-map
からC-y
を削除します.
(define-key evil-insert-state-map (kbd "C-y") nil)
初期状態でどのステートにどんなキーが定義されているかはevil-maps.el
を見るとわかります. また, evil-state-state-map
の代わりにevil-state-state-local-map
を使うと, バッファローカルなキーバインドを定義できます.
初期状態では, 挿入ステートでもいくつかのキーにはVimの挿入モードと同様のコマンドが割り当てられています. もし挿入ステートでのキーバインドを完全にEmacs互換にしたい場合は, 次のようにします.
(setq evil-insert-state-map nil)
特定のモードの特定のステートでのキー
特定のモードが有効な場合には通常, mode-name-map
のようなキーマップで定義されたキーが有効になりますが, これらはemulation-mode-map-alists
で定義されているEvilのキーバインドより優先順位が低く, またEvilのステートごとに違ったキーバインドにすることができません.
evil-define-key
コマンドを使うと, 特定のモードが有効な場合のキーを, 優先順位を気にすることなく特定のステートでだけ定義できます. (evil-define-key state mode-map key definition)
の形で用いて, state
にEvilのステート, mode-map
に特定のモードで有効なキーマップを指定する以外は, define-key
と同様です. たとえば, view-mode
のモーションステートでのv
に, view-mode
を終了するコマンドを割り当てるには, 次のようにします.
(evil-define-key 'motion view-mode-map (kbd "v") #'(lambda () (interactive) (view-mode 0)))
state
にnil
を指定すると, すべてのステートで有効なキーを定義できます.
その他のEvilのキーマップ
Evilにはステートごとのキーマップ以外に以下のようなキーマップがあります.
evil-window-map
- ウィンドウ移動キー(
C-w
)を押した後のキーを定義するキーマップ evil-outer-text-objects-map
OP a
に続く, テキストオブジェクトを選択するキー(例:daw
のw
)を定義するキーマップevil-inner-text-objects-map
OP i
に続く, テキストオブジェクトを選択するキー(例:vib
のb
)を定義するキーマップevil-ex-search-keymap
- 検索(
/
や?
等)ミニバッファでのキーマップ(検索モジュールがevil-search
の場合のみ有効) evil-ex-completion-map
- コマンドライン(
:
)でのキーマップ evil-read-key-map
- 後続の文字を利用するオペレータ(
"
やf
)で, 文字を読み取るときのキーマップ
これらのキーマップを変更する場合はdefine-key
を使います.
ふつうのEmacsのキーマップを優先
前述の通り, Evilのキーは他のメジャーモード・マイナーモードのキーよりも優先されます. もし特定のモードで, Evilのキーよりも優先してそのモードのすべてのキーを使いたい場合は, evil-make-overriding-map
を使って, そのモードのキーマップの優先順位を上げる必要があります. (evil-make-overriding-map map state)
の形で用いて, map
には優先したいキーマップ, state
にはどのステートのときに優先するかを指定します. state
を省略すると全ステートで優先されます. たとえば, ノーマルステートでhowm-menu-mode-map
の全てのキーを優先するには次のようにします.
(evil-make-overriding-map howm-menu-mode-map 'normal)
むやみに優先順位を上げると, Evilの移動キー(hjkl
)などが覆い隠されて, 優先されたモードのコマンドが呼び出されるようになってしまうことがあります. これを避け, 移動キーはEvilのコマンドのままにするには, evil-add-hjkl-bindings
を使います. (evil-add-hjkl-bindings map state)
の形で用い, 引数の意味はevil-make-overriding-map
のものと同じです. たとえば, ノーマルステートでmew-message-mode-map
のhjkl
以外の全てのキーを優先するには以下のようにします.
(evil-make-overriding-map mew-message-mode-map 'normal) (evil-add-hjkl-bindings mew-message-mode-map 'normal)
移動キーを設定するついでに, その他のキーを設定することもできます. 次の例では, ノーマルステートでmew-summary-mode-map
のhjkl
以外の全てのキーを優先した上で, hl
はmew-summary-mode-map
のキー, GJK;
はevil-motion-satate-map
のキーを使うようにしています.
(evil-make-overriding-map mew-summary-mode-map 'normal) (evil-add-hjkl-bindings mew-summary-mode-map 'normal "h" (lookup-key mew-summary-mode-map "h") "l" (lookup-key mew-summary-mode-map "l") "G" (lookup-key evil-motion-state-map "G") "J" (lookup-key evil-motion-state-map "J") "K" (lookup-key evil-motion-state-map "K") ";" (lookup-key evil-motion-state-map ";"))
キーに関すること以外のEmacsの機能との相互運用については後の節で触れます.
カスタマイズ
続いて, Emacs標準のカスタマイズ機構を用いて設定できるオプションについて解説します.
Evilのカスタマイズオプションは, Evilの挙動をVimに近づけるか, あるいはEmacsに近づけるかを制御するためのオプションが中心ですが, Vimのオプションに相当するものもあります. Vimに慣れ親しんだユーザのために, 相当するVimのオプションも明記しました. Vimの挙動にできる限り近づけたい場合は, 後の節も参照して下さい.
オプションを実際に設定する場合, 2通りの方法があります. Emacs標準のカスタマイズ機構を専用のUIで操作する方法と, 設定ファイルにLisp式を書く方法です. 前者の場合, M-x customize-group RET evil RET
(M-x
はAlt
とx
の同時押し)とすると, 設定項目一覧が表示され, マウスクリックで設定を変更できます(設定を変更した場合は保存するのを忘れないようにしましょう). 後者の場合は, ~/.emacs
や~/.emacs.d/init.el
で,
(setq evil-cross-lines t evil-search-module 'evil-search evil-ex-search-vim-style-regexp t) (require 'evil) (evil-mode 1)
のように, Evilをrequire
するよりも前に, setq
で設定します. もしもEl-Getを使っている場合は,
(setq evil-cross-lines t evil-search-module 'evil-search evil-ex-search-vim-style-regexp t) (el-get-bundle evil) (require 'evil) (evil-mode 1)
のように, (el-get-bundle evil)
よりも前に設定しなければならないことに注意しましょう.
setq
にはオプションの名前と設定値を書いていきます. 以下の説明では, 設定値としてのシンボルはそのままシンボル名を書いていますが, Lispの式として表現する際には'
をつける必要があります(ただし'(...)
の中ではつけません).
すべてのカスタマイズオプションの一覧は付録に記載してあります. ここでは重要なもののみを紹介します.
evil-cross-lines
カーソル移動時に行をまたぐかどうか. t
はVimのwhichwrap=b,s,h,l,<,>,[,]
に相当し, nil
はVimのwhichwrap=[,]
に相当します. Vimの初期値とは異なります.
evil-move-cursor-back
- 型
- boolean
- 初期値
- t
- バージョン
- 1.0.0
- Vim
- -
挿入ステートを抜けるときにカーソルを後退するかどうか. また, nil
の場合, Vimとは違ってカーソルを改行文字の上に移動することができるようになります.
evil-want-C-i-jump
- 型
- boolean
- 初期値
- t
- バージョン
- 1.0.0
- Vim
- -
C-i
をジャンプコマンド(evil-jump-forward
)に割り当てるかどうか. デフォルトでVimと同様にC-i
はジャンプコマンドに割り当てられます. デフォルト設定のままだと, TAB
とC-i
の区別がないため, ノーマルステートやビジュアルステートではTAB
で自動インデントなどの操作ができません.
evil-search-module
- 型
- isearch | evil-search
- 初期値
- isearch
- バージョン
- 1.0.0
- Vim
- -
検索に使うモジュール. isearch
はEmacsに組み込みの検索モジュール, evil-search
はEvil独自の検索モジュールです. evil-search
を選択すると, Vimの検索により近い挙動になります.
evil-ex-search-vim-style-regexp
Vim風の正規表現を使うかどうか. nil
の場合は従来のEmacsの正規表現を用います. t
の場合はVimと互換な正規表現を内部でEmacsの正規表現に変換します. Vimと違い, デフォルトではEmacsの正規表現を用います. この設定はevil-search-module
がevil-search
の場合のみ有効です. evil-search-module
がisearch
の場合は常にEmacsの正規表現を用います.
evil-esc-delay
- 型
- number
- 初期値
- 0.01
- バージョン
- 1.0.0
- Vim
- -
ESC
が押された際に後続のキーを待つ秒数. 端末では単体のESC
とM-
を区別することができないため, ごく短い間に(事実上同時に)他のキーが押された場合のみM-
として認識する必要があります. 端末そのもの(screen
やtmux
)でも同様に短い時間待つ設定がある場合は, そちらの調整も必要です.
Emacsの機能との共存
Emacsの機能のキーマップとEvilのキーマップの衝突を防ぐ方法は前の節で説明した通りです. この節ではそれ以外にEmacsの機能をEvilから扱いやすくする方法を解説します. EvilでEmacs本来の機能をうまく扱うための設定の一部は, Evil本体にevil-integration.el
として組み込まれていて, ここで解説する内容の具体例になっています.
ここで解説する設定は(require 'evil)
の行よりも後に書きます.
モードごとのデフォルトのステート
特定のモードでの初期ステートを指定するには, (evil-set-initial-state mode state)
を使います. バッファ内容の編集を伴わないようなモードをモーションステートにしたいといったような場合に使います. たとえば, view-mode
がモーションステートになるようにするには,
(evil-set-initial-state 'view-mode 'motion)
とします(実際にはこの設定は不要で, view-mode
は元からモーションステートになるように設定されています). モードには本来メジャーモードを指定すべきですが, 上記の例のようにマイナーモードを指定することもできます.
EmacsのコマンドをEvil化
ほとんどのEmacsのコマンドは, Evilからもふつうに使えますが, Evil独自の機能(繰り返しやビジュアルステート)との親和性を高めるための調整方法も用意されています. Evilに慣れてきて, Evilの機能とEmacsのコマンドがうまく組み合わさっていないことに気づいたら, 以下の宣言が必要かどうか検討してみましょう.
(evil-declare-not-repeat command)
command
を繰り返し操作の対象外にします.(evil-declare-abort-repeat command)
command
を実行したら繰り返す操作の記録を中止します.(evil-declare-change-repeat command)
- 繰り返し操作のために
command
によるバッファの変更点を記録します. 通常はキー入力しか記録せず, 多くの場合はそれで問題ありません. 自動補完メニューが表示されるのを待ってから選択する場合など, キー入力の再現がバッファの変更内容を再現しないようなコマンドに対してはこれを設定するとよいでしょう. (evil-declare-motion command)
command
を移動コマンドとして宣言します. 移動コマンドはビジュアルステートを終了しません.
EmacsのリージョンコマンドをEvilのオペレータにするといったような, 高度なEvil化の方法については拡張編を参照して下さい.
事例紹介: SKKとの共存
Emacsのパッケージの機能とEvilの機能はしばしば衝突します. キーマップの定義やコマンドのEvil化で済む場合は簡単ですが, それでは済まない場合も多々あります. 開発者にメーリングリストで対策を仰ぐのも一つの方法ですが, ここでは自力でうまく動くようにする一例を紹介します.
日本語入力にSKKを使っていると, いくつかの機能がEvilと衝突します.
SKKには入力モードに応じてカーソルの色を自動的に変更する機能がありますが, Evilもステートに応じてカーソル形状を変更するため, 調整が必要です. 挿入ステートの場合だけ, カーソルの制御をSKKに任せるのがよいでしょう. defadvice
で関数そのものを置き換えて, ad-do-it
で元の関数を呼び出すというイディオムを使うと, 以下のように書けます.
(defadvice update-buffer-local-cursor-color (around evil-update-buffer-local-cursor-color-in-insert-state activate) ;; SKKによるカーソル色変更を, 挿入ステートかつ日本語モードの場合に限定 "Allow ccc to update cursor color only when we are in insert state and in `skk-j-mode'." (when (and (eq evil-state 'insert) (bound-and-true-p skk-j-mode)) ad-do-it)) (defadvice evil-refresh-cursor (around evil-refresh-cursor-unless-skk-mode activate) ;; Evilによるカーソルの変更を, 挿入ステートかつ日本語モードではない場合に限定 "Allow ccc to update cursor color only when we are in insert state and in `skk-j-mode'." (unless (and (eq evil-state 'insert) (bound-and-true-p skk-j-mode)) ad-do-it))
Evilの検索(evil-search
モジュール)は, 入力するごとに表示をアップデートしていくので, 日本語の変換途中にもアップデートが起きてしまい入力が困難です. SKKの未確定状態ではアップデートを抑制するとよいでしょう. 上の例と同じように, defadvice
を使って以下のように書けます.
(defadvice evil-ex-search-update-pattern (around evil-inhibit-ex-search-update-pattern-in-skk-henkan activate) ;; SKKの未確定状態(skk-henkan-mode)ではない場合だけ, 検索パターンをアップデート "Inhibit search pattern update during `skk-henkan-mode'. This is reasonable since inserted text during `skk-henkan-mode' is a kind of temporary one which is not confirmed yet." (unless (bound-and-true-p skk-henkan-mode) ad-do-it))
Vimの再現性を高める
Emacs本来の機能を損なわないために, デフォルト設定ではEmacs寄りの設定とVim寄りの設定の中間になっています. このため, Vimと全く同じ挙動を期待した場合にはしばしばうまくいかないでしょう. この節では, Vimに慣れ親しんだユーザのために, できる限りVimに近い挙動にするためにどんな設定をすればいいか解説します.
多くはVimの機能や設定に対応するEmacsのやり方の紹介ですが, 中にはEmacsの機能を犠牲にしてVimの挙動を愚直に再現しようとするものもあります. そのようにVimのやり方に固執すると, Emacsの機能も最大限に利用するという目標から外れるおそれがあることには留意しておきましょう.
カスタマイズ
カスタマイズオプションで設定できる範囲で, できる限りVimに近づけるには以下のようにします(これは(require 'evil)
よりも前に書きます).
(setq evil-want-C-u-scroll t evil-search-module 'evil-search evil-ex-search-vim-style-regexp t)
ただし, これはVimのデフォルト設定と対応しているわけではなく, Vimで以下のように設定した状態に近いものとなります.
set autoindent set smartcase set hlsearch set incsearch set shiftwidth=4 set shiftround set whichwrap=[,]
括弧の対応をハイライト
デフォルトでは対応する括弧のハイライトは有効になっていないので, 設定ファイルで次のようにします.
(show-paren-mode t)
バッファの終端を明示
Vimのように~
でバッファの終わりを明示する方法はありませんが, 他のやり方で同等のことが実現できます.
GUI版のEmacsを使っている場合は, 以下のようにするとバッファの終わり以降が左側の縁のところに明示されます.
(setq indicate-empty-lines t)
GUI版ではもう少し凝った方法でバッファの範囲を明示することもできます. バッファがまだ上下に続く場合は矢印が, 上限または下限の場合は鉤印が表示されます. 以下のように設定します.
(setq indicate-buffer-boundaries 'left)
また, 拙作のend-mark.el
を使うと, GUI版・コンソール版(emacs -nw
)によらず, バッファの終端に[EOF]
と表示できます. インストールするには, 上記ファイルを~/.emacs.d/
等に保存し, 以下の設定を書きます.
(add-to-list 'load-path user-emacs-directory) (require 'end-mark) (global-end-mark-mode)
ファイル末尾で必ず改行
設定ファイルに以下のように書きます.
(setq require-final-newline t)
単語境界をVim互換に
単語の境界をどう判別するかは, 基本的にはEmacsの仕組みをそのまま用いているため, Vimとはわずかに異なります. 具体的には, Vimと違い「_
」を単語の境界とみなします. Vimと同じように「_
」を単語の一部とみなすようにするには, 設定ファイルに以下のように書きます.
(modify-syntax-entry ?_ "w" (standard-syntax-table))
C-c
をESC
に, C-c
/ESC
でキャンセル
VimのようにC-c
をESC
のような役割にするには, 以下のようにします.
(defun evil-escape-or-quit (&optional prompt) (interactive) (cond ((or (evil-normal-state-p) (evil-insert-state-p) (evil-replace-state-p) (evil-visual-state-p)) [escape]) (t (kbd "C-g")))) (define-key key-translation-map (kbd "C-c") #'evil-escape-or-quit) (define-key evil-operator-state-map (kbd "C-c") #'evil-escape-or-quit) (define-key evil-normal-state-map [escape] #'keyboard-quit)
この設定では, Vimの挙動により近づけるために, C-c
とESC
ともにキャンセルの意味も持たせています.
C-a
/C-x
でインクリメント/デクリメント
EvilそのものにはC-a
/C-x
によるインクリメント/デクリメントは含まれていませんが, evil-numbersで提供されています.
MELPAを使っている場合はM-x package-install RET evil-numbers RET
でインストールされます. それ以外の場合は, evil-numbers.el
をダウンロードして, load-path
内のディレクトリに保存しましょう.
初期設定ではどのキーにも割り当てられないので, 以下のように設定します.
(define-key evil-normal-state-map (kbd "C-a") #'evil-numbers/inc-at-pt) (define-key evil-normal-state-map (kbd "C-x") #'evil-numbers/dec-at-pt)
ただし, この設定はEmacsのC-x
を無効にするため, 多くのEmacsの機能が利用できなくなります. 提供元の設定例では, 以下のようにC-c +
/C-c -
に割り当てる設定が推奨されています.
(define-key evil-normal-state-map (kbd "C-c +") #'evil-numbers/inc-at-pt) (define-key evil-normal-state-map (kbd "C-c -") #'evil-numbers/dec-at-pt)
mapleader
EvilそのものにはVimのmapleader
に相当する機能は実装されていませんが, evil-leaderで提供されています.
MELPAを使っている場合はM-x package-install RET evil-leader RET
でインストールされます. それ以外の場合は, evil-leader.el
をダウンロードして, load-path
内のディレクトリに保存しましょう.
たとえば, Vimのlet leader=","
, map
, map
に相当する設定をするには,
(require 'evil-leader) (evil-leader/set-leader ",") (evil-leader/set-key "e" #'find-file "b" #'switch-to-buffer)
とします.
コマンドラインでレジスタから貼り付け
いまのところ, Evil本体のコマンドラインではC-r
がレジスタからの貼り付けに割り当てられていない(バージョン1.0.0)か, 割り当てられてはいるもののVimのコマンドラインで使えるカーソル下のオブジェクトの貼り付け(C-r C-w
等)は実装されていません(バージョン1.0-dev). evil-ex-registers.el
を用いると, これらが使えるようになります.
インストールするには, evil-ex-registers.el
をダウンロードして, load-path
内のディレクトリに保存します. 設定ファイルに以下のように書くと有効になります.
(require 'evil-ex-registers) (define-key evil-ex-search-keymap (kbd "C-r") #'evil-ex-paste-from-register) (define-key evil-ex-completion-map (kbd "C-r") #'evil-ex-paste-from-register)
タブページ
Vimのタブページに相当するものはEmacsの標準パッケージには含まれていませんが, ElScreenを使うとほぼ同等のことができます.
ElScreenのインストールはMELPAを使うのが簡単でしょう. まずは設定ファイルに以下のように書きます(既に同じことが書いてある場合は必要ありません).
(require 'package) (add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/") t) (package-initialize)
一度Emacsを起動してM-x package-install RET elscreen RET
とするとインストールされます.
そのままのElScreenはEmacs用のインタフェースしかないので, :tabnew
などで操作したい場合は設定が必要です. 以下の設定を設定ファイルに書くと, Vimのタブページに関する操作が概ね有効になります. ただし, タブ番号が0で始まる等, 些細な差異はあります.
set listchars
Vimでは空白文字を表示するのにlistchars
オプションを使いますが, Emacsではディスプレイテーブルを使います. この仕組みは, 原理上あらゆる文字の表示方法を制御できます.
空白文字に限れば, 簡単な設定をするだけで, 裏側でディスプレイテーブル(やフォントロック)を使った制御をしてくれるパッケージwhitespace.el
がEmacs 23から標準搭載されているので, これを使うのがよいでしょう.
以下が, Vimの設定に対応するディスプレイテーブルもしくはwhitespace.el
の設定です.
(require 'whitespace) (setq whitespace-style '(face tabs tab-mark space space-mark newline)) ;; set lcs=eol:$ (setcar (nthcdr 2 (assq 'newline-mark whitespace-display-mappings)) [?$ ?\n]) ;; set lcs=tab:^\ , (setcar (nthcdr 2 (assq 'tab-mark whitespace-display-mappings)) [?^ ?\t]) ;; set lcs=tab:^-, (setcar (nthcdr 2 (assq 'tab-mark whitespace-display-mappings)) [?^ ?- ?- ?- ?- ?- ?- ?-]) ;; set lcs=extends:<,precedes:< (set-display-table-slot standard-display-table 'truncation ?<) ;; set nbsp:% (setcar (nthcdr 2 (assq 'space-mark whitespace-display-mappings)) [?%]) (global-whitespace-mode)
whitespace.el
が表示を制御するのはwhitespace-style
に入っている要素のみです. 要素の意味と, 他にどんなものの表示を制御できるかは, M-x describe-variable RET whitespace-style RET
を参照して下さい.
set-display-table-slot
を使う場合, 文字のフェイス(フォントや色など)も同時に変更することができます. この場合は(set-display-table-slot standard-display-table slot (make-glyph-code c face))
のようにします. face
にはフェイスを表すシンボルを指定します. 既に定義されているフェイスはM-x list-face-display RET
で一覧できます. 自分で新しいフェイスを作るにはdefface
マクロを使います.
このような設定を用いても, 以下の点はVimと異なります.
set lcs=tab:xy
のy
を設定する場合はタブ幅が固定set lcs=trail:c
は設定できない- 色だけ変えることは可能(ただし,
whitespace-style
からspace-mark
を外しておく)(setq show-trailing-whitespace t)
(set-face-background 'trailing-whitespace "#cc9900")
- 色だけ変えることは可能(ただし,
set lcs=extends:c
とset lcs=precedes:c
を個別には設定できないset lcs=conceal:c
はconcealに完全に対応する概念がないため設定できない- Emacsでは折り返し記号も変更可能
(set-display-table-slot standard-display-table 'wrap c)
- Emacsでは非表示の行を表す記号も変更可能
(set-display-table-slot standard-display-table 'selective-display c)
- Emacsでは
standard-display-table
を直接書き換えればあらゆる文字の表示のしかたを変更可能
set tabstop
:set tabstop=num
相当のことをするには:(setq tab-width num) RET
とします. デフォルトのタブ幅を指定するには, 設定ファイルに以下のように書きます.
(setq tab-width 4)
set expandtab
:set expandtab RET
相当のことをするには:(setq indent-tabs-mode nil) RET
とします. デフォルト設定を変えるには, 設定ファイルに以下のように書きます.
(setq indent-tabs-mode nil)
既に入力されているタブをtab-width
の幅のスペースに展開するには, 展開する範囲を選択してM-x untabify RET
とします.
set statusline
VimのステータスラインはEmacsではモードラインと呼びます. モードラインはmode-line-format
という変数に決まったデータ構造の値を設定することで変更できます. このデータ構造はシンボルや文字列のリストが入れ子になったもので, 文字列にはプロパティも設定できるため, 見せ方を自由に変更できます. 文字列中の%c
は特別な意味を持ち表示する際に展開されますが, Vimとは意味が異なるため, Emacsのマニュアルを参照して下さい.
set number
:set number RET
相当のことをするにはM-x linum-mode RET
とします. もう一度同じことをすると:set nonumber RET
になります. 行番号を常に表示にするには設定ファイルに以下のように書きます.
(global-linum-mode)
色テーマ
Vimではcolorscheme
で色設定をしますが, Emacsでは2つのやり方があります. 一つはcolor-themeを使う方法で, もう一つはEmacs 24から標準搭載されたカスタムテーマを使う方法です. color-themeは近頃はメンテナンスされていないので, 古いEmacsを使う予定がなければ使わない方がよいでしょう.
color-themeは, MELPAを使っている場合はM-x package-install RET color-theme RET
でインストールできます. テーマそのものは初期状態でもいくつか定義されていて, 追加でインストールすることもできます. 特定のテーマを適用にするには設定ファイルに以下のように書きます.
(color-theme-initialize) (color-theme-dark-laptop) ; テーマdark-laptopを適用
カスタムテーマを使うには, load-theme
コマンドを使います. デフォルトで提供されているテーマか, 自分で~/.emacs.d/
*3に保存したname-theme.el
ファイルを読み込むことができます. 設定ファイルに書く場合は以下のようにします.
(load-theme 'zenburn t) ; テーマzenburnを適用
Vimで人気の配色はEmacsにも移植されています. 以下にcolor-theme用, カスタムテーマ用の対応するEmacsパッケージを挙げておきます.
colorscheme | color-theme | カスタムテーマ |
---|---|---|
desert | color-theme-desert.el |
desert-theme.el |
molokai | color-theme-molokai.el |
|
solarized | color-theme-solarized.el |
solarized-dark-theme.el , solarized-light-theme.el |
zenburn | color-theme-zenburn.el |
zenburn-theme.el *4 |
モードライン
EmacsにもVimのモードライン相当のものがありますが, 記法が異なります. Vimのモードラインの記法(の一部)をEmacsでも利用できるようにするにはemacs-vim-modelineを使います.
その他のべんり設定
物理行移動と論理行移動を入れ替え
Vimと同じく, デフォルトではj
, k
は論理行移動(改行文字単位の行移動)で, gj
, gk
が物理行移動(見たままの行移動)になっています. 通常は物理行で移動した方がわかりやすいので, Vimユーザでこれを入れ替えている人も多いでしょう. Evilでは以下のようにすると入れ替えることができます(この設定は(require 'evil)
の行よりも後に書きます).
(defun evil-swap-key (map key1 key2) ;; MAP中のKEY1とKEY2を入れ替え "Swap KEY1 and KEY2 in MAP." (let ((def1 (lookup-key map key1)) (def2 (lookup-key map key2))) (define-key map key1 def2) (define-key map key2 def1))) (evil-swap-key evil-motion-state-map "j" "gj") (evil-swap-key evil-motion-state-map "k" "gk")
C-n
/C-p
をハイブリッドに
デフォルトでは, EvilのノーマルステートのC-n
とC-p
はYankRing.vim
のようにヤンク履歴の操作に割り当てられています*5. p
などで貼り付けた直後に, C-p
で一つ前にヤンク(コピー)した内容を貼り付け直し, C-n
で一つ後のものを貼り付け直すという機能です.
これはこれで大変べんりな機能ですが, 本来の行移動コマンドをつぶす割に, 直前のコマンドが貼り付けではない場合にはエラーメッセージが出るだけで, 勿体ない感じがします. 直前が貼り付けコマンドでなければふつうに上下移動してくれてもよいでしょう.
そういうわけで, C-n
, C-p
の直前が貼り付けコマンドでないときに上下移動になるようにするには以下のようにします.
(defadvice evil-paste-pop (around evil-paste-or-move-line activate) ;; evil-paste-popできなかったらprevious-lineする "If there is no just-yanked stretch of killed text, just move to previous line." (condition-case err ad-do-it (error (if (eq this-command 'evil-paste-pop) (call-interactively 'previous-line) (signal (car err) (cdr err)))))) (defadvice evil-paste-pop-next (around evil-paste-or-move-line activate) ;; evil-paste-pop-nextできなかったらnext-lineする "If there is no just-yanked stretch of killed text, just move to next line." (condition-case err ad-do-it (error (if (eq this-command 'evil-paste-pop-next) (call-interactively 'next-line) (signal (car err) (cdr err))))))
プラグイン
Evilのために書かれたプラグインを紹介します. ここで紹介されている以外にも, Vimのプラグインと同等の機能を持ったEmacsパッケージは多数存在します(対応表は導入編を参照)が, それらの導入方法は個別のパッケージのドキュメントを参照して下さい. ここではEvilに特化したプラグインのみを挙げます. これらはEvil公式のものではなく, ユーザたちが作成して公開しているものです.
evil-mode-line
EmacsのモードラインにEvilのステートを表示し, ステートに応じてモードラインの背景色を切り替える機能を提供します.
インストールするには, evil-mode-line.el
とmode-line-color.el
をダウンロードして, load-path
内のディレクトリに保存します. 設定ファイルに以下のように書くと有効になります.
(require 'evil-mode-line)
カスタマイズ方法などはtarao/evil-pluginsのページを参照して下さい.
evil-surround
surround.vim
の移植版です. 選択範囲に対してStype
とすると, type
で指定された種類の要素を追加します. たとえば, S<tag>
とすると, 選択範囲が<tag>
タグで囲まれます.
インストールするには, evil-surround.el
をダウンロードして, load-path
内のディレクトリに保存します. 設定ファイルに以下のように書くと有効になります.
(require 'evil-surround) (global-evil-surround-mode 1)
カスタマイズ方法などはevil-surroundのページを参照して下さい.
evil-nerd-commenter
NERD_commenter.vim
の移植版です. 行ごとのコメントアウト/アンコメントのためのプラグインです.
インストールするには, evil-nerd-commenter.el
をダウンロードして, load-path
内のディレクトリに保存します. 設定ファイルに以下のように書くと, M-;
でコメントアウトできるようになります.
(require 'evil-nerd-commenter) (evilnc-default-hotkeys)
カスタマイズ方法などはevil-nerd-commenterのページを参照して下さい.
これをインストールしなくても, Emacsでは元々M-;
がcomment-dwim
に割り当てられていて, 選択範囲のコメントアウト/アンコメントができます. evil-nerd-commenterは, 範囲を選択しなかったときに現在の行をコメントアウトする, 行数を指定できる, という点が異なります.
evil-operator-comment
commentop.vim
の移植版です. コメントアウト/アンコメントのためのオペレータを定義します. オペレータなので, 同じキー2回で行に対して適用, 行数指定での適用, オブジェクト単位での適用, 文字・行・矩形選択範囲に対しての適用などが可能です.
インストールするにはevil-operator-comment.el
をダウンロードして, load-path
内のディレクトリに保存します. 設定ファイルに以下のように書くと, C
でコメントアウトできるようになります.
(require 'evil-operator-comment) (global-evil-operator-comment-mode 1)
カスタマイズ方法などはtarao/evil-pluginsのページを参照して下さい.
これをインストールしなくても, Emacsでは元々M-;
がcomment-dwim
に割り当てられていて, 選択範囲のコメントアウト/アンコメントができ, 選択範囲に対してはEvilのオペレータとして用いることができます. ただし, 矩形選択時にも正しく動作させるためにはevil-operator-commentが必要です.
evil-operator-moccur
選択範囲などに対して複数ファイル/ディレクトリにまたがる検索(moccur-grep-find
)をするためのオペレータです.
インストールするには, color-moccur.el
とevil-operator-moccur.el
をダウンロードして, load-path
内のディレクトリに保存します. 設定ファイルに以下のように書くと, M
で検索できるようになります.
(require 'evil-operator-moccur) (global-evil-operator-moccur-mode 1)
カスタマイズ方法などはtarao/evil-pluginsのページを参照して下さい.
evil-relative-linum
オペレータを入力した直後から適用範囲が確定するまでの間, 相対行番号を表示します.
インストールするには, linum+.el
とevil-relative-linum.el
をダウンロードして, load-path
内のディレクトリに保存します. 設定ファイルに以下のように書くと有効になります.
(require 'evil-relative-linum)
Vimのrelativenumber
オプションと違い, オペレータが入力されたときだけ相対行番号を表示します.
evil-little-word
camelcasemotion.vim
の移植版です. 通常の単語単位よりも小さい部分を単語として扱う移動コマンド, オブジェクトを提供します. たとえば, "CamelCase"を"Camel"と"Case"の2語として, "snake_case"を"snake"と"case"の2語として扱うような単語単位です.
インストールするには, evil-little-word.el
をダウンロードして, load-path
内のディレクトリに保存します. 設定ファイルに以下のように書くと, glw
/glb
による移動, ilw
/alw
のオブジェクトが定義されます.
(require 'evil-little-word)
オリジナルのcamelcasemotion.vim
と違い, 英語のアルファベット以外の文字の大文字・小文字も正しく扱われます. たとえば, "TietokoneenÄäni"という文字列は, camelcasemotion.vim
では1語になりますが, evil-little-wordでは"Tietokoneen"と"Ääni"の2語になります.
evil-textobj-between
textobj/between.vim
の移植版です. ifc
やafc
で, 文字c
に囲まれた部分を選択できるようになります.
インストールするには, evil-textobj-between.el
をダウンロードして, load-path
内のディレクトリに保存します. 設定ファイルに以下のように書くと有効になります.
(require 'evil-textobj-between)
evil-paredit
ParEditをEvilから使えるようにするためのプラグインです. 括弧の対応を保った編集が強制されるようになります.
インストールするにはMELPAを使ってM-x package-install RET evil-paredit RET
とします. 有効にするにはM-x evil-paredit-mode RET
とします. たとえば, Emacs Lispファイルを編集する際に有効にするには設定ファイルに以下のように書きます.
(require 'evil-paredit) (add-hook 'emacs-lisp-mode-hook 'evil-paredit-mode)
evil-rails
rails.vim
の移植版です. Railsプロジェクトを管理するためのインタフェースを提供します.
インストールするには, M-x package-install RET rinari RET
でRinariをインストールし, evil-rails.el
をダウンロードして, load-path
内のディレクトリに保存します. 設定ファイルに以下のように書くと有効になります.
(require 'rinari) (require 'evil-rails)
hexl-evil-patch
Emacsのバイナリエディタモード(hexl-mode
)をEvilから問題なく使えるようにするためのプラグインです.
インストールするにはhexl-evil-patch.el
をダウンロードして, load-path
内のディレクトリに保存します. 設定ファイルに以下のように書くと有効になります.
(require 'hexl-evil-patch)
参考になりそうな個人設定
本来は, Evilを使う上でのおすすめ設定をすぐに使える形で紹介したいところですが, それにはVimやEmacsの使い方にまで踏み込む必要があり, Evilの解説という範疇から外れてしまうため, また, VimやEmacsでのベストプラクティスそのものが多様であり意見の別れるところなので, 本稿ではそのような設定の紹介はあえてしないことにしました. むしろ, 本稿の読者の皆様が設定自慢の記事を書いて盛り上げてくれることを願っています.
ここでは代わりに, 既にEvilを使っているユーザの個人設定のうち, Web上で公開されているものをピックアップしました. これらを参考に是非とも自分だけの究極の設定を見出して下さい.
以下, ユーザIDの敬称は省略します.
tarao
本稿の筆者の個人設定です. 同じディレクトリに他のEmacs設定のファイルがあります. この設定のリポジトリそのものをgit clone
して, dotfiles/.emacs.d/init.el
に対して以下のようにEmacsを起動すると, 必要なパッケージが(リポジトリディレクトリ内に)自動的にダウンロードされて, 既存のEmacsの設定を汚すことなく設定を試すことができます(ただし, ダウンロードには少し不安になるくらい時間がかかります).
emacs -q -l init.el
mikio
いろいろなパッケージのコマンドが細かにEvil化されていて参考になります.