usr_40.txt For Vim バージョン 9.1. Last change: 2022 Jun 23
VIM USER MANUAL - by Bram Moolenaar
新しいコマンドを作る
Vim は拡張可能なエディタです。よく使う操作を一つにまとめて新しいコマンドを作成
したり、既存のコマンドを再定義したりできます。自動コマンドを使うと、コマンドを
自動的に実行できます。
40.1 キーマッピング
40.2 コマンドラインコマンドを定義する
40.3 自動コマンド
次章: usr_41.txt Vim script 書法
前章: usr_32.txt undo ツリー
目次: usr_toc.txt
==============================================================================
40.1 キーマッピング
05.4 で簡単なマップを説明しました。マップの原理は、キー操作を他のキー操作に
変換するというものです。単純ですが強力な仕組みです。
典型的な使い方は、一つのキーを複数のキーにマップする方法です。ファンクション
キー (<F1>以外) には機能が割り当てられていないので、それらのキーを使うとよいで
しょう。例: >
このマップでは三つのモードが使われています。"G" で最後の行にジャンプし、"o" で
新しい行を開いて挿入モードを開始、"Date: " というテキストを入力してから <Esc>
で挿入モードを抜けます。
特殊キーを <> で囲んで表記していますが、これは括弧表記というものです。特殊キー
を押すのではなく、見たまま文字どおり入力してください。この表記を使ったマップは
読むのが簡単で、そのままコピー&ペーストして使うことができます。
さて、":" でコマンドラインモードに入ります。":read !date" コマンドは、"date"
コマンドの出力を読み込んで、現在行の下に追加します。<CR> は ":read" コマンドを
実行するために必要です。
この時点で、テキストは次のようになっています:
Date: ~
Fri Jun 15 12:54:34 CEST 2001 ~
最後に、"kJ" で上に移動してから二つの行を一行につなげます。
マップするキーを選ぶときは map-which-keys を参考にしてください。
☆マップとモード
":map" コマンドはノーマルモードのキーマップを定義します。同様に、他のモードの
マップを定義することもできます。例えば ":imap" で挿入モードのマップを定義でき
ます。次のマップは、カーソルの下に日付を挿入します: >
多少の違いはありますが、ノーマルモードで <F2> にマップしたものと同じです。この
マップを定義してもノーマルモードの <F2> は消えません。このように、同じキーを
モード別にマップすることができます。
このマップは挿入モードの中で開始しますが、実行後はノーマルモードになってしまい
ます。挿入モードを継続したい場合はマップの最後に "a" を追加してください。
マップコマンドはモード別に用意されています:
:map ノーマルモード、ビジュアルモード、オペレータ待機モード
:vmap ビジュアルモード
:nmap ノーマルモード
:omap オペレータ待機モード
:map! 挿入モード、コマンドライン
:imap 挿入モード
:cmap コマンドライン
オペレータ待機モードとは、"d" や "y" などのオペレータを入力した後、モーション
コマンドやテキストオブジェクトの入力を待機している状態のことです。例えば "dw"
の "w" はオペレータ待機モードでの入力です。
例えば、d<F7> コマンドで C プログラムのブロック ({}で囲まれたテキスト) を削除
できるように、あるいは、y<F7> でブロックをヤンクできるようにしたい場合は、<F7>
をマップしてプログラムブロックを選択できるようにする必要があります。次のように
します: >
オペレータ待機モードで <F7> を押すと "a{" によってブロックが選択されます。この
マップは、{ が押しにくい位置にあるキーボードでは便利です。
☆マップの一覧を表示する
定義されたマップの一覧を確認したい場合は、":map" コマンドを引数なしで実行しま
す。モード別のマップコマンドを使うこともできます。次のような一覧が表示されま
す:
_g :call MyGrep(1)<CR> ~
v <F2> :s/^/> /<CR>:noh<CR>`` ~
n <F2> :.,$s/^/> /<CR>:noh<CR>`` ~
<xHome> <Home>
<xEnd> <End>
最初の列は、マップが機能するモードを示しています。"n" はノーマルモード、"i" は
挿入モード、などなど。":map" で定義されたマップには空白が使われます。空白の場
合はノーマルモードとビジュアルモードで使えます。
この一覧を見れば、<> 表記で書いた特殊キーが正しく認識されているかを確認できま
す (カラー表示がサポートされている場合に限る)。例えば、<Esc> が色付きで表示さ
れていれば、それはエスケープ文字です。他のテキストと同じ色で表示されている場合
は、それは "<Esc>" という 5 文字の文字列です。
☆再マップ
マップは他のマップを含むことができます。例えば、上述の <F2> のマップは次のよう
に短くできます: >
ノーマルモードの <F2> は、最後の行に移動して <F3> を押すようにマップされていま
す。挿入モードの <F2> は、<Esc> で挿入モードを停止して <F3> を押すようにマップ
されています。そして、<F3> には目的の機能がマップされています。
例えば、Ex モードはほとんど使わないので "Q" をテキスト整形コマンドとして使える
ようにしたい (昔の Vim はそういう動作でした) 場合は、次のようなマップを定義し
ます: >
しかし、Ex モードが使いたくなることもあるかもしれません。"gQ" を Q にマップし
て、EX モードが使えるようにしましょう: >
この状態で "gQ" を入力すると "Q" にマップされます。ここまではいいですね。とこ
ろが、さらに "Q" が "gq" にマップされてしまいます。つまり、"gQ" は "gq" に変換
されるので Ex モードを使うことはできないのです。
再マップされないようにするには、":noremap" コマンドを使います: >
これで、マップされた "Q" に対して他のマップが適用されなくなります。同じような
コマンドがモード別に用意されています:
:noremap ノーマルモード、ビジュアルモード、オペレータ待機モード
:vnoremap ビジュアルモード
:nnoremap ノーマルモード
:onoremap オペレータ待機モード
:noremap! 挿入モード、コマンドライン
:inoremap 挿入モード
:cnoremap コマンドライン
☆再帰マップ
マップが自分自身を含んでいる場合、そのマップは永遠に動き続けます。これを利用す
れば、コマンドを無限に繰り返すことができます。
例えば、いくつかのファイルがあって、すべてのファイルは一行目にバージョン番号が
書かれているとします。"vim *.txt" でそれらのファイルを開くと、一つ目のファイル
が開いた状態になります。次のマップを定義します: >
そして、",," を入力してマップを実行します。このマップは一行目の "5.1" を "5.2"
に変更し、":wnext" で上書き保存してから次のファイルを開きます。マップの最後は
",," になっているので同じマップが再び適用され、置換と保存が実行されます。
このマップは、何かエラーが発生するまで止まりません。このマップの場合、置換コマ
ンドの実行で "5.1" が見つからなかった場合にエラーが発生します。その場合は、
"5.1" を挿入してから再びマップを実行します。最後のファイルに到達すると、
":wnext" が失敗してマップが停止します。
マップの途中でエラーが発生した場合は、そのマップの残りの部分は無視されます。
マップは CTRL-C で中断できます (MS-WindowsではCTRL-Break)。
☆マップを削除する
マップを削除するには ":unmap" コマンドを使います。このコマンドにも、モード別の
ものが用意されています:
:unmap ノーマルモード、ビジュアルモード、オペレータ待機モード
:vunmap ビジュアルモード
:nunmap ノーマルモード
:ounmap オペレータ待機モード
:unmap! 挿入モード、コマンドライン
:iunmap 挿入モード
:cunmap コマンドライン
例えば、ビジュアルモードを除き、ノーマルモードとオペレータ待機モードだけでマッ
プを定義したいような場合は次のトリックが使えます。最初に三つのモードでマップを
定義し、ビジュアルモードのマップだけを削除します: >
"<C-A>" は CTRL-A キーとして解釈されます。
すべてのマップを削除するには :mapclear コマンドを使います。他のコマンドと同
様に、これにもモード別のコマンドが用意されています。マップの削除はアンドゥでき
ないので注意してください。
☆特殊文字
":map" コマンドの後ろには他のコマンドを続けて書くことができます。その場合は |
文字でコマンドを区切ります。そのため、マップの中では | 文字が使えません。この
文字を使いたい場合は <Bar> (5文字) を使ってください。例: >
同じ問題は ":unmap" コマンドにもあります。":unmap" の場合はさらに末尾のスペー
スにも注意しなければなりません。以下の二つのコマンドは動作が違います: >
一つ目のコマンドは "a " (スペース付き) のマップを削除します。
マップの中でスペースを使いたい場合は <Space> (7文字) を使ってください: >
このマップはスペースキーを押すと、次の単語 (空白区切り) に移動します。
マップコマンドの末尾にはコメントを付けられません。なぜなら、" 文字はマップの一
部として処理されてしまうからです。代わりに |" を使ってください。これは、新しい
空のコマンドを開始して、そのコマンドにコメントをつけます。例: >
☆マップと短縮入力
挿入モードのマップは短縮入力とよく似ています。引数は同じ方法で処理されます。主
な違いは実行されるタイミングです。短縮入力は単語の後で単語以外の文字を入力した
ときに実行されます。マップはマップ文字列の最後の文字を入力したときに実行されま
す。
違いは他にもあります。短縮入力では入力した文字がすぐに挿入されます。短縮入力が
実行されると元の文字が削除されて指定された文字列に置換されます。マップされた文
字を入力したときは最後の文字を入力してマップが実行されるまで何も挿入されませ
ん。'showcmd' オプションがオンに設定されている場合は、入力途中の文字がウィンド
ウ下部に表示されます。
マップがあいまいな場合は少し違う動作になります。例えば、次の二つのマップがある
とき: >
"aa" と入力した時点では、一つ目のマップを適用すべきか、それとも二つ目のマップ
を使うべきか、判断できません。その場合は、他の文字が入力されるまで待機状態にな
ります。"a" を入力すると二つ目のマップが適用されて "bar" が挿入されます。他の
文字、例えばスペース、を入力すると一つ目のマップが適用されて "foo" が挿入さ
れ、さらにスペースが挿入されます。
☆さらに...
<script> キーワードを使うと、スクリプトローカルなマップを定義できます。
:map-<script> 参照。
<buffer> キーワードを使うと、バッファローカルなマップを定義できます。
:map-<buffer> 参照。
<unique> キーワードを使うと、定義しようとしたマップがすでに定義されていた場合
にコマンドが失敗します。このキーワードを使わない場合は、古いマップが上書き定義
されます。:map-<unique> 参照。
何もしないキーを定義したい場合は <Nop> (5文字) を使います。次のコマンドは、
<F7> キーが何もしないように設定しています: >
<Nop> の後に空白を入れないでください。
==============================================================================
40.2 コマンドラインコマンドを定義する
Vim では新しいコマンドを定義することができます。定義したコマンドはコマンドライ
ンモードの他のコマンドと同じように使えます。
コマンドを定義するには ":command" コマンドを使います: >
":DeleteFirst" コマンドを実行すると、":1delete" が実行され、最初の行が削除され
ます。
Note:
ユーザー定義コマンドの名前は必ず大文字で開始する必要があります。":X"、
":Next"、":Print" を使うことはできません。アンダースコア ("_") も使え
ません。数字は使えますがお勧めしません。
ユーザー定義コマンドの一覧を見るには、次のコマンドを実行します: >
組み込みコマンドと同じように、ユーザー定義コマンドも省略できます。他のコマンド
と区別するのに十分な長さの文字を入力するだけでコマンドを実行できます。コマンド
ライン補完を使って完全な名前を得ることもできます。
☆引数の数
ユーザー定義コマンドは引数を取ることができます。引数の数は -nargs オプションで
指定する必要があります。例えば、上述の :DeleteFirst コマンドは引数を取らないの
で、次のように定義できます: >
指定が無ければ 0 が使われるので、わざわざ "-nargs=0" を指定する必要はありませ
ん。-nargs には次の値を指定できます:
-nargs=0 引数なし
-nargs=1 引数 1 個
-nargs=* いくつでも
-nargs=? 引数なし、もしくは 1 個
-nargs=+ 引数 1 個以上
☆引数の使い方
コマンド定義の中では、<args> キーワードを使って引数を表します。例: >
次のコマンドを実行すると: >
"Hello World" と表示されます。引数に引用符 (") が使われると、これはうまく動き
ません。例: >
特殊な文字が含まれているときにそれを適切にエスケープして文字列として使えるよう
にするには "<q-args>" を使います: >
上記の ":Say" コマンドを実行すると、次のコマンドが実行されます: >
<f-args> キーワードを使うと、引数が関数呼び出しに適した形に展開されます。例: >
次のコマンドが実行されます: >
☆範囲指定
いくつかのコマンドは範囲指定を受け付けますが、そのようなコマンドを定義したい場
合は -range オプションを使います。このオプションには次の値を指定できます:
-range 範囲指定を許可。省略時は現在行が選択される。
-range=% 範囲指定を許可。省略時はファイル全体が選択される。
-range={count} 範囲指定を許可。範囲指定の最後の数値だけを使う。省略時
は {count} が使われる。
範囲指定を使う場合は、<line1> キーワードと <line2> キーワードを使って範囲の最
初と最後の行を取得できます。例えば、次のコマンドは、指定された範囲のテキストを
"save_file" に保存するコマンドを定義しています: >
☆他のオプション
使用できるオプションやキーワードは他にもあります:
-count={number} カウント指定を受け付ける。省略時は {number}。
カウント指定は <count> キーワードで取得できま
す。
-bang ! の指定を受け付ける。! が使われた場合は
<bang> キーワードが ! に置き換わります。
-register レジスタの指定を受け付ける。(省略時は無名レジ
スタ。)
指定されたレジスタは <reg> (または <register>)
で取得できます。
-complete={type} コマンドライン補完の種類を指定する。使用できる
補完の種類は :command-completion を参照。
-bar コマンドの後ろに | を使って他のコマンド (ある
いはコメント) を続けて書くことを許可する。
-buffer カレントバッファでのみ使用できるコマンドを定義
する。
最後に <lt> キーワードを説明します。これは文字 "<" を意味します。<> 表記をエス
ケープして、特殊な意味を消すために使います。
☆再定義と削除
同じ名前のコマンドを再定義したい場合は ! を使います: >
コマンドを削除したい場合は ":delcommand" を使います。削除したいコマンドの名前
を引数に指定してください。例: >
次のコマンドですべてのユーザー定義コマンドを削除できます: >
コマンドの削除はアンドゥできないので注意してください。
ユーザー定義コマンドについての詳細はリファレンスマニュアルを参照してください。
user-commands。
==============================================================================
40.3 自動コマンド
自動コマンドとは、さまざまなイベントに応じて自動的に実行されるコマンドのことで
す。ファイルを読み書きしたり、バッファを切り替えたりしたときに実行されます。例
えば、gzipプラグインは、圧縮ファイルを開くために自動コマンドを使っています。
自動コマンドは非常に強力です。適切に使えばいろんな手間を省くことができます。し
かし、不適切な使い方をすればさまざまなトラブルの原因になります。
例えば、ファイルを保存するときに、保存した日付をファイル末尾に書き込んでみま
しょう。まず、次の関数を定義します: >
バッファをファイルに保存する直前にこの関数を実行したいわけです。次のコマンドで
設定します: >
"BufWritePre" は自動コマンドが実行されるイベントです。このイベントはバッファを
ファイルに保存する直前に発行されます。"*" の部分はファイル名にマッチするパター
ンです。"*" はすべてのファイルにマッチします。
この自動コマンドが設定された状態で ":write" を実行すると、ファイル名にマッチし
たすべての BufWritePre 自動コマンドが実行されてから、ファイルが保存されます。
:autocmd の正式な書式は次のとおりです: >
[group] は省略可能です。コマンドを管理したり呼び出したりしたい場合に使います
(後述)。{events} はコマンドを実行するイベントのリストです (コンマ区切り)。
{file-pattern} はファイル名です。ワイルドカードが使えます。例えば、"*.txt" な
ら ".txt" で終わるファイルに対してコマンドが実行されます。 [++nested] は省略可
能です。自動コマンドを再帰的に呼び出したい場合に指定します (下記参照)。そして、
実行したいコマンドを {command} に指定します。
自動コマンドを追加する際、既に存在するものは残ります。自動コマンドが複数回追加
されるのを防ぐにはこの形式を使用する必要があります: >
新しい定義の前の `:autocmd!` によって以前に定義していた自動コマンドは削除され
ます。グループについては後述します。
☆イベント
BufReadPost は最も便利なイベントの一つです。これは新しいファイルを開いたときに
発行されます。普通はオプションを設定したりするのに使われます。例えば、"*.gsm"
というファイルを GNU アセンブリ言語のファイルとして扱いたい場合は、次のように
設定します: >
ファイルの種類が検出されて、'filetype' オプションが設定されると、Filetype イベ
ントが発行されます。このイベントはファイルの種類に応じて何かを実行したい場合に
使います。例えば、テキストファイルを開いたときに短縮入力の定義を読み込むには次
のようにします: >
新しいファイルを作成したときにスケルトンを挿入することもできます: >
イベントの一覧は autocmd-events を参照してください。
☆パターン
{file-pattern} 引数には複数のパターンをコンマ区切りで指定できます。例えば、
"*.c,*.h" なら、末尾が ".c" と ".h" のファイルにマッチします。
パターンには一般的なワイルドカードが使えます。次のようなものがよく使われます:
* 何かの文字が何文字でも
? 何かの文字が 1 つ
[abc] a か b か c
. ドット
a{b,c} ab か ac
パターンにスラッシュ (/) が含まれている場合は、ディレクトリ名と比較されます。
スラッシュが含まれていない場合は、ファイル名のみが使われます。例えば、
"/home/biep/readme.txt" には "*.txt" がマッチします。"/home/biep/*" も同様に
マッチします。しかし、"home/foo/*.txt" はマッチしません。
スラッシュが含まれているときは、ファイルの絶対パス ("/home/biep/readme.txt")
と相対パス (例えば "biep/readme.txt") の両方が比較されます。
Note:
MS-Windows のように、ディレクトリの区切りにバックスラッシュを使うよう
なシステムでもスラッシュを使ってパターンを指定することができます。
バックスラッシュはエスケープする必要があるので、スラッシュを使ったほう
が簡単です。自動コマンドの移植性もあがります。
☆自動コマンドを削除する
自動コマンドの削除には、定義と同じコマンドを使います。ただし、削除するときは !
を使い、{command} は指定しません。例: >
"FileWritePre" イベントの、"*" パターンを使っている自動コマンドがすべて削除さ
れます。
☆一覧表示する
定義されている自動コマンドの一覧を見るには次のようにします: >
とても長い出力が表示されます。ファイルタイプの認識が有効になっている場合は特に
長くなります。一部のコマンドだけを表示したい場合は、グループ、イベント、パター
ンのどれかを指定してください。例えば、次のコマンドで BufNewFile に設定された自
動コマンドを表示できます: >
"*.c" に対する自動コマンドを表示したい場合は次のようにします: >
イベントに "*" を指定すると、すべてのイベントが表示されます。cprograms グルー
プの自動コマンドを表示したい場合は次のようにします: >
☆グループ
自動コマンドを定義するとき、{group} を指定することで、関連した自動コマンドをグ
ループ化できます。例えば、特定のグループの自動コマンドをまとめて削除したりでき
ます。
自動コマンドをグループ化するには、":augroup" コマンドを使います。例えば、C 言
語用の自動コマンドを定義してみましょう: >
次のように書くこともできます: >
"cprograms" グループのすべての自動コマンドを削除するには、次のようにします: >
☆ネスト
通常は、自動コマンドの中で実行されたコマンドによってイベントが発行されることは
ありません。例えば、FileChangedShell イベントの中でファイルを読み込んでも、シ
ンタックスを設定するための自動コマンドは実行されません。イベントを発行させたい
場合は "nested" 引数を指定してください: >
☆自動コマンドを実行する
擬似的にイベントを発行して、自動コマンドを実行することができます。自動コマンド
の中から他の自動コマンドを実行するような場合に便利です。例: >
新しいファイルが開かれたときに実行される自動コマンドを定義しています。ファイル
名の末尾が ".new" になっているものが対象です。":execute" コマンドは、引数を評
価した結果をコマンドとして実行します。例えば、"tryout.c.new" を開くと、次のコ
マンドが実行されます: >
expand() 関数に指定された "<afile>" が自動コマンドで使われたファイル名に展開さ
れ、":r" によって、そのルート部分 {訳注: .newを除いた部分} が使われます。
":doautocmd" はカレントバッファの上で実行されます。":doautoall" コマンドは、
":doautocmd" と同じ操作をすべてのバッファに対して実行します。
☆ノーマルモードコマンドを使う
自動コマンドで使用できるのはコマンドラインコマンドです。ノーマルモードコマンド
を使いたい場合は ":normal" コマンドを使ってください。例: >
*.log ファイルを開くと、ファイル末尾にカーソルがジャンプします。
":normal" コマンドは少し複雑です。指定するコマンドは完結していなければなりませ
ん。例えば、"i" で挿入モードに入ったら、<Esc> でモードを抜ける必要があります。
"/" で検索する場合は、<CR> で検索を実行する必要があります。
":normal" コマンドはすべてのテキストを引数として解釈するので、| を使って他のコ
マンドを続けて書くことはできません。それが必要な場合は ":execute" コマンドの中
で ":normal" コマンドを実行してください。":execute" を使うと、特殊文字を指定す
るのが簡単になります。例: >
長いコマンドを見やすくするために、バックスラッシュを使って複数行に分けていま
す。この方法はスクリプトファイルの中だけで使えます (コマンドラインで入力すると
きは使えません)。
自動コマンドの中で複雑なことを実行すると、必然的にカーソルの位置が変わってしま
います。それを元に戻す方法については restore-position を参照してください。
☆イベントの無効化
自動コマンドを実行して欲しくないときは、'eventignore' オプションに無視したいイ
ベントを設定してください。例えば、次のように設定すると、他のウィンドウに移動し
たときのイベントが無視されます: >
すべてのイベントを無視するには、次のように設定します: >
通常の状態に戻すには、'eventignore' を空に設定します: >
==============================================================================
次章: usr_41.txt Vim script 書法
Copyright: see manual-copyright vim:tw=78:ts=8:noet:ft=help:norl:
VIM USER MANUAL - by Bram Moolenaar
新しいコマンドを作る
Vim は拡張可能なエディタです。よく使う操作を一つにまとめて新しいコマンドを作成
したり、既存のコマンドを再定義したりできます。自動コマンドを使うと、コマンドを
自動的に実行できます。
40.1 キーマッピング
40.2 コマンドラインコマンドを定義する
40.3 自動コマンド
次章: usr_41.txt Vim script 書法
前章: usr_32.txt undo ツリー
目次: usr_toc.txt
==============================================================================
40.1 キーマッピング
05.4 で簡単なマップを説明しました。マップの原理は、キー操作を他のキー操作に
変換するというものです。単純ですが強力な仕組みです。
典型的な使い方は、一つのキーを複数のキーにマップする方法です。ファンクション
キー (<F1>以外) には機能が割り当てられていないので、それらのキーを使うとよいで
しょう。例: >
:map <F2> GoDate: <Esc>:read !date<CR>kJ
このマップでは三つのモードが使われています。"G" で最後の行にジャンプし、"o" で
新しい行を開いて挿入モードを開始、"Date: " というテキストを入力してから <Esc>
で挿入モードを抜けます。
特殊キーを <> で囲んで表記していますが、これは括弧表記というものです。特殊キー
を押すのではなく、見たまま文字どおり入力してください。この表記を使ったマップは
読むのが簡単で、そのままコピー&ペーストして使うことができます。
さて、":" でコマンドラインモードに入ります。":read !date" コマンドは、"date"
コマンドの出力を読み込んで、現在行の下に追加します。<CR> は ":read" コマンドを
実行するために必要です。
この時点で、テキストは次のようになっています:
Date: ~
Fri Jun 15 12:54:34 CEST 2001 ~
最後に、"kJ" で上に移動してから二つの行を一行につなげます。
マップするキーを選ぶときは map-which-keys を参考にしてください。
☆マップとモード
":map" コマンドはノーマルモードのキーマップを定義します。同様に、他のモードの
マップを定義することもできます。例えば ":imap" で挿入モードのマップを定義でき
ます。次のマップは、カーソルの下に日付を挿入します: >
:imap <F2> <CR>Date: <Esc>:read !date<CR>kJ
多少の違いはありますが、ノーマルモードで <F2> にマップしたものと同じです。この
マップを定義してもノーマルモードの <F2> は消えません。このように、同じキーを
モード別にマップすることができます。
このマップは挿入モードの中で開始しますが、実行後はノーマルモードになってしまい
ます。挿入モードを継続したい場合はマップの最後に "a" を追加してください。
マップコマンドはモード別に用意されています:
:map ノーマルモード、ビジュアルモード、オペレータ待機モード
:vmap ビジュアルモード
:nmap ノーマルモード
:omap オペレータ待機モード
:map! 挿入モード、コマンドライン
:imap 挿入モード
:cmap コマンドライン
オペレータ待機モードとは、"d" や "y" などのオペレータを入力した後、モーション
コマンドやテキストオブジェクトの入力を待機している状態のことです。例えば "dw"
の "w" はオペレータ待機モードでの入力です。
例えば、d<F7> コマンドで C プログラムのブロック ({}で囲まれたテキスト) を削除
できるように、あるいは、y<F7> でブロックをヤンクできるようにしたい場合は、<F7>
をマップしてプログラムブロックを選択できるようにする必要があります。次のように
します: >
:omap <F7> a{
オペレータ待機モードで <F7> を押すと "a{" によってブロックが選択されます。この
マップは、{ が押しにくい位置にあるキーボードでは便利です。
☆マップの一覧を表示する
定義されたマップの一覧を確認したい場合は、":map" コマンドを引数なしで実行しま
す。モード別のマップコマンドを使うこともできます。次のような一覧が表示されま
す:
_g :call MyGrep(1)<CR> ~
v <F2> :s/^/> /<CR>:noh<CR>`` ~
n <F2> :.,$s/^/> /<CR>:noh<CR>`` ~
<xHome> <Home>
<xEnd> <End>
最初の列は、マップが機能するモードを示しています。"n" はノーマルモード、"i" は
挿入モード、などなど。":map" で定義されたマップには空白が使われます。空白の場
合はノーマルモードとビジュアルモードで使えます。
この一覧を見れば、<> 表記で書いた特殊キーが正しく認識されているかを確認できま
す (カラー表示がサポートされている場合に限る)。例えば、<Esc> が色付きで表示さ
れていれば、それはエスケープ文字です。他のテキストと同じ色で表示されている場合
は、それは "<Esc>" という 5 文字の文字列です。
☆再マップ
マップは他のマップを含むことができます。例えば、上述の <F2> のマップは次のよう
に短くできます: >
:map <F2> G<F3>
:imap <F2> <Esc><F3>
:map <F3> oDate: <Esc>:read !date<CR>kJ
:imap <F2> <Esc><F3>
:map <F3> oDate: <Esc>:read !date<CR>kJ
ノーマルモードの <F2> は、最後の行に移動して <F3> を押すようにマップされていま
す。挿入モードの <F2> は、<Esc> で挿入モードを停止して <F3> を押すようにマップ
されています。そして、<F3> には目的の機能がマップされています。
例えば、Ex モードはほとんど使わないので "Q" をテキスト整形コマンドとして使える
ようにしたい (昔の Vim はそういう動作でした) 場合は、次のようなマップを定義し
ます: >
:map Q gq
しかし、Ex モードが使いたくなることもあるかもしれません。"gQ" を Q にマップし
て、EX モードが使えるようにしましょう: >
:map gQ Q
この状態で "gQ" を入力すると "Q" にマップされます。ここまではいいですね。とこ
ろが、さらに "Q" が "gq" にマップされてしまいます。つまり、"gQ" は "gq" に変換
されるので Ex モードを使うことはできないのです。
再マップされないようにするには、":noremap" コマンドを使います: >
:noremap gQ Q
これで、マップされた "Q" に対して他のマップが適用されなくなります。同じような
コマンドがモード別に用意されています:
:noremap ノーマルモード、ビジュアルモード、オペレータ待機モード
:vnoremap ビジュアルモード
:nnoremap ノーマルモード
:onoremap オペレータ待機モード
:noremap! 挿入モード、コマンドライン
:inoremap 挿入モード
:cnoremap コマンドライン
☆再帰マップ
マップが自分自身を含んでいる場合、そのマップは永遠に動き続けます。これを利用す
れば、コマンドを無限に繰り返すことができます。
例えば、いくつかのファイルがあって、すべてのファイルは一行目にバージョン番号が
書かれているとします。"vim *.txt" でそれらのファイルを開くと、一つ目のファイル
が開いた状態になります。次のマップを定義します: >
:map ,, :s/5.1/5.2/<CR>:wnext<CR>,,
そして、",," を入力してマップを実行します。このマップは一行目の "5.1" を "5.2"
に変更し、":wnext" で上書き保存してから次のファイルを開きます。マップの最後は
",," になっているので同じマップが再び適用され、置換と保存が実行されます。
このマップは、何かエラーが発生するまで止まりません。このマップの場合、置換コマ
ンドの実行で "5.1" が見つからなかった場合にエラーが発生します。その場合は、
"5.1" を挿入してから再びマップを実行します。最後のファイルに到達すると、
":wnext" が失敗してマップが停止します。
マップの途中でエラーが発生した場合は、そのマップの残りの部分は無視されます。
マップは CTRL-C で中断できます (MS-WindowsではCTRL-Break)。
☆マップを削除する
マップを削除するには ":unmap" コマンドを使います。このコマンドにも、モード別の
ものが用意されています:
:unmap ノーマルモード、ビジュアルモード、オペレータ待機モード
:vunmap ビジュアルモード
:nunmap ノーマルモード
:ounmap オペレータ待機モード
:unmap! 挿入モード、コマンドライン
:iunmap 挿入モード
:cunmap コマンドライン
例えば、ビジュアルモードを除き、ノーマルモードとオペレータ待機モードだけでマッ
プを定義したいような場合は次のトリックが使えます。最初に三つのモードでマップを
定義し、ビジュアルモードのマップだけを削除します: >
:map <C-A> /---><CR>
:vunmap <C-A>
:vunmap <C-A>
"<C-A>" は CTRL-A キーとして解釈されます。
すべてのマップを削除するには :mapclear コマンドを使います。他のコマンドと同
様に、これにもモード別のコマンドが用意されています。マップの削除はアンドゥでき
ないので注意してください。
☆特殊文字
":map" コマンドの後ろには他のコマンドを続けて書くことができます。その場合は |
文字でコマンドを区切ります。そのため、マップの中では | 文字が使えません。この
文字を使いたい場合は <Bar> (5文字) を使ってください。例: >
:map <F8> :write <Bar> !checkin %:S<CR>
同じ問題は ":unmap" コマンドにもあります。":unmap" の場合はさらに末尾のスペー
スにも注意しなければなりません。以下の二つのコマンドは動作が違います: >
:unmap a | unmap b
:unmap a| unmap b
:unmap a| unmap b
一つ目のコマンドは "a " (スペース付き) のマップを削除します。
マップの中でスペースを使いたい場合は <Space> (7文字) を使ってください: >
:map <Space> W
このマップはスペースキーを押すと、次の単語 (空白区切り) に移動します。
マップコマンドの末尾にはコメントを付けられません。なぜなら、" 文字はマップの一
部として処理されてしまうからです。代わりに |" を使ってください。これは、新しい
空のコマンドを開始して、そのコマンドにコメントをつけます。例: >
:map <Space> W| " 次の単語に移動するのにスペースバーを使う
☆マップと短縮入力
挿入モードのマップは短縮入力とよく似ています。引数は同じ方法で処理されます。主
な違いは実行されるタイミングです。短縮入力は単語の後で単語以外の文字を入力した
ときに実行されます。マップはマップ文字列の最後の文字を入力したときに実行されま
す。
違いは他にもあります。短縮入力では入力した文字がすぐに挿入されます。短縮入力が
実行されると元の文字が削除されて指定された文字列に置換されます。マップされた文
字を入力したときは最後の文字を入力してマップが実行されるまで何も挿入されませ
ん。'showcmd' オプションがオンに設定されている場合は、入力途中の文字がウィンド
ウ下部に表示されます。
マップがあいまいな場合は少し違う動作になります。例えば、次の二つのマップがある
とき: >
:imap aa foo
:imap aaa bar
:imap aaa bar
"aa" と入力した時点では、一つ目のマップを適用すべきか、それとも二つ目のマップ
を使うべきか、判断できません。その場合は、他の文字が入力されるまで待機状態にな
ります。"a" を入力すると二つ目のマップが適用されて "bar" が挿入されます。他の
文字、例えばスペース、を入力すると一つ目のマップが適用されて "foo" が挿入さ
れ、さらにスペースが挿入されます。
☆さらに...
<script> キーワードを使うと、スクリプトローカルなマップを定義できます。
:map-<script> 参照。
<buffer> キーワードを使うと、バッファローカルなマップを定義できます。
:map-<buffer> 参照。
<unique> キーワードを使うと、定義しようとしたマップがすでに定義されていた場合
にコマンドが失敗します。このキーワードを使わない場合は、古いマップが上書き定義
されます。:map-<unique> 参照。
何もしないキーを定義したい場合は <Nop> (5文字) を使います。次のコマンドは、
<F7> キーが何もしないように設定しています: >
:map <F7> <Nop>| map! <F7> <Nop>
<<Nop> の後に空白を入れないでください。
==============================================================================
40.2 コマンドラインコマンドを定義する
Vim では新しいコマンドを定義することができます。定義したコマンドはコマンドライ
ンモードの他のコマンドと同じように使えます。
コマンドを定義するには ":command" コマンドを使います: >
:command DeleteFirst 1delete
":DeleteFirst" コマンドを実行すると、":1delete" が実行され、最初の行が削除され
ます。
Note:
ユーザー定義コマンドの名前は必ず大文字で開始する必要があります。":X"、
":Next"、":Print" を使うことはできません。アンダースコア ("_") も使え
ません。数字は使えますがお勧めしません。
ユーザー定義コマンドの一覧を見るには、次のコマンドを実行します: >
:command
組み込みコマンドと同じように、ユーザー定義コマンドも省略できます。他のコマンド
と区別するのに十分な長さの文字を入力するだけでコマンドを実行できます。コマンド
ライン補完を使って完全な名前を得ることもできます。
☆引数の数
ユーザー定義コマンドは引数を取ることができます。引数の数は -nargs オプションで
指定する必要があります。例えば、上述の :DeleteFirst コマンドは引数を取らないの
で、次のように定義できます: >
:command -nargs=0 DeleteFirst 1delete
指定が無ければ 0 が使われるので、わざわざ "-nargs=0" を指定する必要はありませ
ん。-nargs には次の値を指定できます:
-nargs=0 引数なし
-nargs=1 引数 1 個
-nargs=* いくつでも
-nargs=? 引数なし、もしくは 1 個
-nargs=+ 引数 1 個以上
☆引数の使い方
コマンド定義の中では、<args> キーワードを使って引数を表します。例: >
:command -nargs=+ Say :echo "<args>"
次のコマンドを実行すると: >
:Say Hello World
"Hello World" と表示されます。引数に引用符 (") が使われると、これはうまく動き
ません。例: >
:Say he said "hello"
特殊な文字が含まれているときにそれを適切にエスケープして文字列として使えるよう
にするには "<q-args>" を使います: >
:command -nargs=+ Say :echo <q-args>
上記の ":Say" コマンドを実行すると、次のコマンドが実行されます: >
:echo "he said \"hello\""
<<f-args> キーワードを使うと、引数が関数呼び出しに適した形に展開されます。例: >
:command -nargs=* DoIt :call AFunction(<f-args>)
:DoIt a b c
:DoIt a b c
次のコマンドが実行されます: >
:call AFunction("a", "b", "c")
☆範囲指定
いくつかのコマンドは範囲指定を受け付けますが、そのようなコマンドを定義したい場
合は -range オプションを使います。このオプションには次の値を指定できます:
-range 範囲指定を許可。省略時は現在行が選択される。
-range=% 範囲指定を許可。省略時はファイル全体が選択される。
-range={count} 範囲指定を許可。範囲指定の最後の数値だけを使う。省略時
は {count} が使われる。
範囲指定を使う場合は、<line1> キーワードと <line2> キーワードを使って範囲の最
初と最後の行を取得できます。例えば、次のコマンドは、指定された範囲のテキストを
"save_file" に保存するコマンドを定義しています: >
:command -range=% SaveIt :<line1>,<line2>write! save_file
☆他のオプション
使用できるオプションやキーワードは他にもあります:
-count={number} カウント指定を受け付ける。省略時は {number}。
カウント指定は <count> キーワードで取得できま
す。
-bang ! の指定を受け付ける。! が使われた場合は
<bang> キーワードが ! に置き換わります。
-register レジスタの指定を受け付ける。(省略時は無名レジ
スタ。)
指定されたレジスタは <reg> (または <register>)
で取得できます。
-complete={type} コマンドライン補完の種類を指定する。使用できる
補完の種類は :command-completion を参照。
-bar コマンドの後ろに | を使って他のコマンド (ある
いはコメント) を続けて書くことを許可する。
-buffer カレントバッファでのみ使用できるコマンドを定義
する。
最後に <lt> キーワードを説明します。これは文字 "<" を意味します。<> 表記をエス
ケープして、特殊な意味を消すために使います。
☆再定義と削除
同じ名前のコマンドを再定義したい場合は ! を使います: >
:command -nargs=+ Say :echo "<args>"
:command! -nargs=+ Say :echo <q-args>
:command! -nargs=+ Say :echo <q-args>
コマンドを削除したい場合は ":delcommand" を使います。削除したいコマンドの名前
を引数に指定してください。例: >
:delcommand SaveIt
次のコマンドですべてのユーザー定義コマンドを削除できます: >
:comclear
コマンドの削除はアンドゥできないので注意してください。
ユーザー定義コマンドについての詳細はリファレンスマニュアルを参照してください。
user-commands。
==============================================================================
40.3 自動コマンド
自動コマンドとは、さまざまなイベントに応じて自動的に実行されるコマンドのことで
す。ファイルを読み書きしたり、バッファを切り替えたりしたときに実行されます。例
えば、gzipプラグインは、圧縮ファイルを開くために自動コマンドを使っています。
自動コマンドは非常に強力です。適切に使えばいろんな手間を省くことができます。し
かし、不適切な使い方をすればさまざまなトラブルの原因になります。
例えば、ファイルを保存するときに、保存した日付をファイル末尾に書き込んでみま
しょう。まず、次の関数を定義します: >
:function DateInsert()
: $delete
: read !date
:endfunction
: $delete
: read !date
:endfunction
バッファをファイルに保存する直前にこの関数を実行したいわけです。次のコマンドで
設定します: >
:autocmd BufWritePre * call DateInsert()
"BufWritePre" は自動コマンドが実行されるイベントです。このイベントはバッファを
ファイルに保存する直前に発行されます。"*" の部分はファイル名にマッチするパター
ンです。"*" はすべてのファイルにマッチします。
この自動コマンドが設定された状態で ":write" を実行すると、ファイル名にマッチし
たすべての BufWritePre 自動コマンドが実行されてから、ファイルが保存されます。
:autocmd の正式な書式は次のとおりです: >
:autocmd [group] {events} {file-pattern} [++nested] {command}
[group] は省略可能です。コマンドを管理したり呼び出したりしたい場合に使います
(後述)。{events} はコマンドを実行するイベントのリストです (コンマ区切り)。
{file-pattern} はファイル名です。ワイルドカードが使えます。例えば、"*.txt" な
ら ".txt" で終わるファイルに対してコマンドが実行されます。 [++nested] は省略可
能です。自動コマンドを再帰的に呼び出したい場合に指定します (下記参照)。そして、
実行したいコマンドを {command} に指定します。
自動コマンドを追加する際、既に存在するものは残ります。自動コマンドが複数回追加
されるのを防ぐにはこの形式を使用する必要があります: >
:augroup updateDate
: autocmd!
: autocmd BufWritePre * call DateInsert()
:augroup END
: autocmd!
: autocmd BufWritePre * call DateInsert()
:augroup END
新しい定義の前の `:autocmd!` によって以前に定義していた自動コマンドは削除され
ます。グループについては後述します。
☆イベント
BufReadPost は最も便利なイベントの一つです。これは新しいファイルを開いたときに
発行されます。普通はオプションを設定したりするのに使われます。例えば、"*.gsm"
というファイルを GNU アセンブリ言語のファイルとして扱いたい場合は、次のように
設定します: >
:autocmd BufReadPost *.gsm set filetype=asm
ファイルの種類が検出されて、'filetype' オプションが設定されると、Filetype イベ
ントが発行されます。このイベントはファイルの種類に応じて何かを実行したい場合に
使います。例えば、テキストファイルを開いたときに短縮入力の定義を読み込むには次
のようにします: >
:autocmd Filetype text source ~/.vim/abbrevs.vim
新しいファイルを作成したときにスケルトンを挿入することもできます: >
:autocmd BufNewFile *.[ch] 0read ~/skeletons/skel.c
イベントの一覧は autocmd-events を参照してください。
☆パターン
{file-pattern} 引数には複数のパターンをコンマ区切りで指定できます。例えば、
"*.c,*.h" なら、末尾が ".c" と ".h" のファイルにマッチします。
パターンには一般的なワイルドカードが使えます。次のようなものがよく使われます:
* 何かの文字が何文字でも
? 何かの文字が 1 つ
[abc] a か b か c
. ドット
a{b,c} ab か ac
パターンにスラッシュ (/) が含まれている場合は、ディレクトリ名と比較されます。
スラッシュが含まれていない場合は、ファイル名のみが使われます。例えば、
"/home/biep/readme.txt" には "*.txt" がマッチします。"/home/biep/*" も同様に
マッチします。しかし、"home/foo/*.txt" はマッチしません。
スラッシュが含まれているときは、ファイルの絶対パス ("/home/biep/readme.txt")
と相対パス (例えば "biep/readme.txt") の両方が比較されます。
Note:
MS-Windows のように、ディレクトリの区切りにバックスラッシュを使うよう
なシステムでもスラッシュを使ってパターンを指定することができます。
バックスラッシュはエスケープする必要があるので、スラッシュを使ったほう
が簡単です。自動コマンドの移植性もあがります。
☆自動コマンドを削除する
自動コマンドの削除には、定義と同じコマンドを使います。ただし、削除するときは !
を使い、{command} は指定しません。例: >
:autocmd! FileWritePre *
"FileWritePre" イベントの、"*" パターンを使っている自動コマンドがすべて削除さ
れます。
☆一覧表示する
定義されている自動コマンドの一覧を見るには次のようにします: >
:autocmd
とても長い出力が表示されます。ファイルタイプの認識が有効になっている場合は特に
長くなります。一部のコマンドだけを表示したい場合は、グループ、イベント、パター
ンのどれかを指定してください。例えば、次のコマンドで BufNewFile に設定された自
動コマンドを表示できます: >
:autocmd BufNewFile
"*.c" に対する自動コマンドを表示したい場合は次のようにします: >
:autocmd * *.c
イベントに "*" を指定すると、すべてのイベントが表示されます。cprograms グルー
プの自動コマンドを表示したい場合は次のようにします: >
:autocmd cprograms
☆グループ
自動コマンドを定義するとき、{group} を指定することで、関連した自動コマンドをグ
ループ化できます。例えば、特定のグループの自動コマンドをまとめて削除したりでき
ます。
自動コマンドをグループ化するには、":augroup" コマンドを使います。例えば、C 言
語用の自動コマンドを定義してみましょう: >
:augroup cprograms
: autocmd BufReadPost *.c,*.h :set sw=4 sts=4
: autocmd BufReadPost *.cpp :set sw=3 sts=3
:augroup END
: autocmd BufReadPost *.c,*.h :set sw=4 sts=4
: autocmd BufReadPost *.cpp :set sw=3 sts=3
:augroup END
次のように書くこともできます: >
:autocmd cprograms BufReadPost *.c,*.h :set sw=4 sts=4
:autocmd cprograms BufReadPost *.cpp :set sw=3 sts=3
:autocmd cprograms BufReadPost *.cpp :set sw=3 sts=3
"cprograms" グループのすべての自動コマンドを削除するには、次のようにします: >
:autocmd! cprograms
☆ネスト
通常は、自動コマンドの中で実行されたコマンドによってイベントが発行されることは
ありません。例えば、FileChangedShell イベントの中でファイルを読み込んでも、シ
ンタックスを設定するための自動コマンドは実行されません。イベントを発行させたい
場合は "nested" 引数を指定してください: >
:autocmd FileChangedShell * ++nested edit
☆自動コマンドを実行する
擬似的にイベントを発行して、自動コマンドを実行することができます。自動コマンド
の中から他の自動コマンドを実行するような場合に便利です。例: >
:autocmd BufReadPost *.new execute "doautocmd BufReadPost " . expand("<afile>:r")
新しいファイルが開かれたときに実行される自動コマンドを定義しています。ファイル
名の末尾が ".new" になっているものが対象です。":execute" コマンドは、引数を評
価した結果をコマンドとして実行します。例えば、"tryout.c.new" を開くと、次のコ
マンドが実行されます: >
:doautocmd BufReadPost tryout.c
expand() 関数に指定された "<afile>" が自動コマンドで使われたファイル名に展開さ
れ、":r" によって、そのルート部分 {訳注: .newを除いた部分} が使われます。
":doautocmd" はカレントバッファの上で実行されます。":doautoall" コマンドは、
":doautocmd" と同じ操作をすべてのバッファに対して実行します。
☆ノーマルモードコマンドを使う
自動コマンドで使用できるのはコマンドラインコマンドです。ノーマルモードコマンド
を使いたい場合は ":normal" コマンドを使ってください。例: >
:autocmd BufReadPost *.log normal G
*.log ファイルを開くと、ファイル末尾にカーソルがジャンプします。
":normal" コマンドは少し複雑です。指定するコマンドは完結していなければなりませ
ん。例えば、"i" で挿入モードに入ったら、<Esc> でモードを抜ける必要があります。
"/" で検索する場合は、<CR> で検索を実行する必要があります。
":normal" コマンドはすべてのテキストを引数として解釈するので、| を使って他のコ
マンドを続けて書くことはできません。それが必要な場合は ":execute" コマンドの中
で ":normal" コマンドを実行してください。":execute" を使うと、特殊文字を指定す
るのが簡単になります。例: >
:autocmd BufReadPost *.chg execute "normal ONew entry:\<Esc>" |
\ 1read !date
\ 1read !date
長いコマンドを見やすくするために、バックスラッシュを使って複数行に分けていま
す。この方法はスクリプトファイルの中だけで使えます (コマンドラインで入力すると
きは使えません)。
自動コマンドの中で複雑なことを実行すると、必然的にカーソルの位置が変わってしま
います。それを元に戻す方法については restore-position を参照してください。
☆イベントの無効化
自動コマンドを実行して欲しくないときは、'eventignore' オプションに無視したいイ
ベントを設定してください。例えば、次のように設定すると、他のウィンドウに移動し
たときのイベントが無視されます: >
:set eventignore=WinEnter,WinLeave
すべてのイベントを無視するには、次のように設定します: >
:set eventignore=all
通常の状態に戻すには、'eventignore' を空に設定します: >
:set eventignore=
==============================================================================
次章: usr_41.txt Vim script 書法
Copyright: see manual-copyright vim:tw=78:ts=8:noet:ft=help:norl: