Vimpulse / viper-modeの使い方

Vimpulse/viper-modeは Emacs上で動作する vi/vimのエミュレータです。

viper-modeは viのエミュレート、Vimpulseは vimのエミュレートを目的としています。

viper-modeは Emacsに標準添付されていますが Vimpulseは自分でインストールする必要があります。

現在Vimpulseは開発終了してEvilというVimエミュレータが開発中です。

http://emacswiki.org/emacs/Evil

はじめに

本ページではEmacs用vi/vimエミュレータ Vimpulse/viper-modeのについてのインストールや設定、カスタマイズ等について書いています。

また Vimpulse/viper-modeで扱いが相当アレなことになっているカーソル移動や検索等の日本語関係の対処もまとめてあります。

主にvi/vimを使っていてEmacsもvi/vim互換のキーバインドで使いたい人向けに書いているので、Emacsに対しての知識はほとんど必要ありません。

vi/vimな人は Emacs自体の操作について <C-g>がキャンセルなので、よくわからなくなったら <C-g>連打ぐらい知っていれば充分使えます。

Emacsな人は困ったらホットキー一発で Emacsモードへ移行できるので気楽に Vimpulse/viper-modeを試してみると良いと思います。

とりあえず <ESC> 連打で ノーマルモードへ戻れることだけ覚えておけば怖いもの無しです :-)

viの簡単な使い方(操作方法)自体についてはこちらです→「はじめてのvi

基本的に viper-modeより Vimpulseを使った方がよいと思いますが、 まずはインストール不要な viper-modeを使ってみたいという方は以下へ進んで下さい。

はじめての viper-mode

個人的な話ですが、たまに他人の環境(Emacs)で編集やペアプログラミングをすることがあります。

そのような場合は [M-delete] (Alt+Delete) を押す度に Vimpulse/viper-modeと Emacsモードを切り替え可能にして、相手の Emacsを使用することにしています。

随時切り替えて使用すると相手の環境(.emacsや キーバインド等)を汚すことなく自分は viキーバインドと好みの設定で使用可能なのでなかなか便利です。

Vimpulseのインストールと起動

ということで Vimpulseをインストールしてみます。

1. Vimpulseのファイルを site-lisp等の load-pathが通った場所にコピーします。

動作に最低限必要なのは本体だけです。

vimpulse.el (本体)

http://www.emacswiki.org/emacs/Vimpulse

undo-tree.el (多段undo、redoを使用可能にする)

http://www.emacswiki.org/emacs/UndoTree

この時点で .emacsに (require 'vimpulse) を追加すればデフォルトで Vimpulseが起動するのですが、Vimpulse関係の設定をまとめておくために起動/環境設定用ファイルを作成すると良いかと思います。

2. 起動/環境設定用ファイル my-vimpulse.elを作成して同じく load-pathの通った場所にコピーします。

my-vimpulse.el

(setq viper-mode t)

(require 'vimpulse)

;; Vimpulse終了/起動

(define-key global-map [M-delete] 'toggle-viper-mode)

(provide 'my-vimpulse)

  • undo-tree.elは Vimpulseが勝手に呼び出すので requireは不要です。
  • キーマップは環境に応じて適当なキーに変更するか、不要なら削除してください。

3. Vimpulseを起動する

初回は M-x (Alt+x か ESC x)から load-libraryで起動します。

M-xはタブキーで補完可能なので適当に補完しつつ入力して下さい。

M-x load-library

Load library: my-vimpulse

以降は [M-delete] (Alt+Delete)で Vimpulseの有効/無効を切替可能です。

一度 my-vimpulseを読み込んだら M-x toggle-viper-modeでも有効/無効は切り替えできます。

起動/終了

起動

終了

M-x toggle-viper-mode

M-x viper-mode

M-x viper-go-away

* Vimpulse起動中は <C-z>でカレントバッファのみ vi-stateと emacs-stateを切替可能です。

デフォルトで Vimpulseを起動したいなら .emacsに追記します。

.emacs

(require 'my-vimpulse)

;; (viper-go-away)

viper-go-awayを実行しておくと Vimpulseはオフのままですが設定は読み込まれ、以降[M-delete]で起動可能です。

カスタマイズ

あとは my-vimpulse.elに好みの設定を追加するだけです。

Vimpulseは viper-modeを内部的に利用しているので viper-mode用の設定も全て有効になります。

viper-mode固有の設定例

;; 検索の際に大文字小文字を区別しない(smartcase)

(setq viper-case-fold-search t)

;; 検索はループする

(setq viper-search-wrap-around t)

;; オートインデントをデフォルトで有効

(setq-default viper-auto-indent t)

;; インデント幅

(setq viper-shift-width tab-width)

対応しているオプションなら、コマンドモードから vimのオプション指定も有効です。

:set shiftwidth=2

キーマップ

jk では物理行移動、C-n、C-pでは論理行移動するには以下のようにします。

Emacs23からは行移動のデフォルトが物理行移動に変更になっているので、バージョンや Emacsのオプションによって動作が変わらないようにしておく方が良いかもしれません。

;; 物理行移動を基本にする

(vimpulse-map "j" 'next-line)

(vimpulse-map "k" 'previous-line)

(vimpulse-map [?\C-n] 'viper-next-line)

(vimpulse-map [?\C-p] 'viper-previous-line)

;; h l は行頭/行末を超えられるようにする

(vimpulse-map "h" 'backward-char)

(vimpulse-map "l" 'forward-char)

;; deleteと backspaceキーは文字削除

(vimpulse-map [delete] 'vimpulse-delete)

(vimpulse-map [backspace] 'backward-delete-char-untabify)

Vimpulseのバージョンによっては "\C-n" のように制御キーと同時押しする場合 " " 形式が使えないことがあるので [?\C-n] を使用してください。

viper-modeのカスタマイズ」を使用するのも手です。

同様に各モードのキーを変更するマップが用意されています。

  • vimpulse-imap (挿入モード)
  • vimpulse-vmap (ビジュアルモード)
  • vimpulse-omap (オペレータモード)

;; ビジュアルモードの backspaceキーは選択文字列削除

(vimpulse-vmap [backspace] 'vimpulse-delete)

M-x describe-key の後にキー入力すると、そのキーに割り当てられている機能が確認できるのでそれを参考にすると良いでしょう。

M-x describe-bindingsでは全てのキーマップを参照可能です。

Vimpulse/viper-mode関係のコマンドは、以下のファイルの define-key設定部分が参考になるかもしれません。

  • /lisp/emulation/viper-keym.el
  • vimpulse.el

特殊キーの表記

;; Spaceキーで画面スクロール

(vimpulse-map [?\ ] 'viper-scroll-screen)

;; Shift+Spaceキーで画面逆スクロール

(vimpulse-map [?\S-\ ] 'viper-scroll-screen-back)

;; Shift+Returnで改行挿入

(vimpulse-map [S-return] "i\r\C-[")

;; Ctrl+Returnで改行挿入

(vimpulse-map [C-return] "i\C-m\C-[")

;; Ctrl+Shift+Insertでタブ挿入

(vimpulse-map [C-S-insert] "i\C-v\C-i\C-[")

;; f1でヘルプ

(vimpulse-map [f1] 'help-for-help)

;; C-\でキャンセル

(vimpulse-map [?\C-\\] 'keyboard-escape-quit)

M- 表記でMetaキーも使えます。

本来のMetaキーがあるキーボードは少ないので、 大抵 ESC か Altで代用されています。

Vimpulse/viper-modeでは当然 ESCが潰されますし、基本的に Metaキーはあまりマップしない方が良いんじゃないかと思います。

他のプラグインとのコンフリクトとか

Vimpulse/viper-modeでは他のプラグインが思うように動作しない事もあります。

たとえば自動入力補完の auto-complete.elで補完候補が出ている場合は <ESC>一回でノーマルモードへ戻れないので以下のように設定しています。

;; settings for auto-complete.el

(setq ac-use-quick-help nil)

(setq ac-use-menu-map t)

(define-key ac-completing-map "\C-[" 'viper-exit-insert-state)

Emacs自体がモードを持たない事を前提に作られているので、挿入モードにしないと特定の機能が動作しない場合もあります。

たとえば howmなどは挿入モードにしないとアクションロックが効かない、などです。

また挿入モードで <C-g>に何か機能を割り当てている場合は、minibuffer (M-xや :)にはキャンセルを割り当てておいた方がよいかもしれません。

(define-key viper-minibuffer-map "\C-g" 'keyboard-escape-quit)

これはミニバッファのデフォルトとして挿入モードに設定されるからです。

何か他のプラグイン等で問題があったらとりあえず挿入モードにしてみたり <C-z>で一時的に emacs-stateへ変更してやるとか、<Esc>ではなく <C-g>でキャンセルとかすると良いかもしれません。

他人の環境で使用している場合は環境を汚すのもアレなので、基本あまり細かい事は気にしない方がいいんじゃないかと思います。

ただし単純な設定で回避できるなら Vimpulse/viper-modeの起動/終了時に設定変更しても良いかもしれません。

起動・終了時に設定変更

たとえば、ありがちな事態として行番号表示されていない Emacs環境で Vimpulse/viper-modeの時だけは行番号表示したいとします。

行番号表示するのは linum-mode (新しめの Emacsなら標準で同梱)を使います。

;; 起動時に設定変更(linum-mode on)

(defadvice viper-mode (after my-viper-mode activate)

(linum-mode t))

;; 終了時に設定を戻す(linum-mode off)

(defadvice viper-go-away (after my-viper-go-away activate)

(linum-mode nil)

(message "Exit viper"))

その他、起動時にタブ幅を合わせてみたりしても良いかもしれません。

;; タブ幅をEmacsに合わせる

(setq viper-shift-width tab-width)

Vimpulse / viper-modeと日本語

英数字のみしか扱わないならデフォルトのままでわりと使えるのですが、もともと Emacs自体が日本語の扱いを考慮していないのもあり日本語を使用しようとすると結構面倒なことがあります。

特にカーソル移動は Vimpulse/viper-modeで独自処理されているのですが、日本語に対応していないので非常に困った事になります。

日本語を扱うための設定やスクリプトは以下のページに簡単にまとめました。

Vimpulse / viper-modeと日本語

  • 日本語対応のカーソル移動
  • 日本語に対応した * 検索コマンド
  • インクリメンタルサーチでの日本語検索
  • vi協調モード / 日本語入力固定モード

便利かもしれないスクリプト

挿入モードでモードラインの色を変更する

挿入モードではモードラインの色を変更すると現在の編集モードを間違える事が無くなって便利です。

挿入モードでモードラインの色を変更する」 (Vimpulse/viper-mode)

挿入モードでステータスラインの色を変更する」 (vim)

縦に連番を入力する

縦に連続した番号を追加したいときがあります。

fuga[]

fuga[]

fuga[]

これを次のように変更したりする場合です。

fuga[0]

fuga[1]

fuga[2]

Emacs用の縦の連番入力コマンドが有ればそれを割り当ててもいいのですが、Vimpulseなら 矩形選択で連番を貼り付け可能です。

「縦に連番を入力する」 (Vimpulse)

http://gitorious.org/vimpulse/pages/Tips#Fill+Visual+Block+selection+with+increasing+numbers

  1. 「Fill Visual Block selection with increasing numbers」を my-vimpulse.elなどの設定ファイルにコピーします。
  2. C-vで連番を挿入したい場所を矩形選択します。
  3. M-n で初期値と増減数を入力します。

縦に連番を入力する」 (vim)

ヒストリ貼り付け

22行目と、11行目から14行までと、17行目の三カ所をヤンク(コピー)して、コピーした順番に貼り付けをしたいというような時に使います。

コピーではなく削除でもかまいませんが、行単位を前提にしているので yy(Y) ddを使用して下さい。

vimだけではなく viでもほぼ同じトリックが標準で実装されているので、入れておいてもいいんじゃないかと思います。

コピペでソースを書いているようなアレな人にとってはわりと便利です。

;; ヒストリ貼り付け開始

(define-key viper-vi-global-user-map [\C-,] 'my-viper-Put-history-first)

;; ヒストリ貼り付け

(define-key viper-vi-global-user-map [\C-.] 'my-viper-Put-history)

  1. 貼り付けをしたい行を最大9カ所まで行単位でヤンク(削除)します。
  2. Ctrl+, でヒストリ貼り付けを開始します。
  3. 以降は Ctrl+. を押すごとにヒストリをさかのぼって貼り付けを行います。

キーマップを2つも使いたくない場合は Ctrl+, の代わりに "1Ctrl+. (3ストローク)でも代用可能です。

スクリプトは以下にあります。

Vimpulse/viper-mode用スクリプト」 (Vimpulse/viper-mode)

ヒストリ貼り付け」 (vim)

設定例では viper-modeでも使えるように viper-vi-global-user-mapを使用していますが、Vimpulseなら vimpulse-mapでもかまいません。

;; ヒストリ貼り付け開始

(vimpulse-map [\C-,] 'my-viper-Put-history-first)

;; ヒストリ貼り付け

(vimpulse-map [\C-.] 'my-viper-Put-history)

ビジュアルモードで選択中の文字列を検索文字列として設定する

ビジュアルモードで文字列選択中に * を押すとカーソル位置の文字列を取得して検索文字列として設定します。

検索はコマンド実行して検索文字列を取得した後に n か Nで実行します。

;; ビジュアルモードで選択中の文字列を検索文字列として設定

(vimpulse-vmap "*" 'my-vimpulse-visual-search-star)

ビジュアルモード用なので Vimpulse専用です。

スクリプトは以下にあります。

Vimpulse/viper-mode用スクリプト」 (Vimpulse/viper-mode)

検索レジスタに文字列設定」 (vim)

正直ビジュアルモードの * コマンドは使い道がよくわからないので、こちらの方がよいのではないでしょうか。

これは vimpulse.elの vimpulse-yank をコピーして一部改変しただけの手抜きスクリプトです。

Vimpulseのバージョンによって動作しない場合は vimpulse.elから同名関数をコピーして copy-regionしている部分を書き換えると良いかもしれません。

手抜きな割には使えるスクリプトじゃないかと思います。