Next: , Previous: , Up: 目次   [Index]


新しいコマンドを作る

*usr_40.txt*	For Vim バージョン 8.1.  Last change: 2013 Aug 05

		     VIM USER MANUAL - by Bram Moolenaar

			     新しいコマンドを作る

Vim は擴張可能なエディタです。よく使ふ操作を 1 つにまとめて新しいコマンドを作成したり、既存のコマンドを再定義したりできます。自動コマンドを使ふと、コマンドを自動的に實行できます。

|40.1|キーマッピング
|40.2|コマンドラインコマンドを定義する
|40.3|自動コマンド

キーマッピング

|05.3| で簡單なマップを說明しました。マップの原理は、キー操作を他のキー操作に變換するといふものです。單純ですが强力な仕組みです。

典型的な使ひ方は、1 つのキーを複數のキーにマップする方法です。ファンクションキー (<F1> 以外) には機能が割り當てられてゐないので、それらのキーを使ふとよいでせう。例:

:map <F2> GoDate: <Esc>:read !date<CR>kJ

このマップでは 3 つのモードが使はれてゐます。"G" で最後の行にジャンプし、"o" で新しい行を開いて插入モードを開始、"Date: " といふテキストを入力してから <Esc> で插入モードを拔けます。

特殊キーを ‘<>’ で圍んで表記してゐますが、これは括弧表記といふものです。特殊キーを押すのではなく、見たまま文字どほり入力してください。この表記を使つたマップは讀むのが簡單で、そのままコピー&ペーストして使ふことができます。

さて、":" でコマンドラインモードに入ります。":read !date" コマンドは、"date" コマンドの出力を讀み込んで、現在行の下に追加します。<CR> は ":read" コマンドを實行するために必要です。

この時點で、テキストは次のやうになつてゐます:

Date:
Fri Jun 15 12:54:34 CEST 2001

最後に、"kJ" で上に移動してから 2 つの行を 1 行につなげます。 マップするキーを選ぶときは |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

ノーマルモードの <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コマンドライン

再歸マップ

マップが自分自身を含んでゐる場合、そのマップは永遠に動き續けます。これを利用すれば、コマンドを無限に繰り返すことができます。

例へば、いくつかのファイルがあつて、すべてのファイルは 1 行目にバージョン番號が書かれてゐるとします。"vim *.txt" でそれらのファイルを開くと、1 つ目のファイルが開いた狀態になります。次のマップを定義します:

: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コマンドライン

例へば、ビジュアルモードを除き、ノーマルモードとオペレータ待機モードだけでマップを定義したいやうな場合は次のトリックが使へます。最初に 3 つのモードでマップを定義し、ビジュアルモードのマップだけを削除します:

:map <C-A> /---><CR>
:vunmap <C-A>

"<C-A>" は CTRL-A キーとして解釋されます。

すべてのマップを削除するには |:mapclear| コマンドを使ひます。他のコマンドと同樣に、これにもモード別のコマンドが用意されてゐます。マップの削除はアンドゥできないので注意してください。

特殊文字

":map" コマンドの後ろには他のコマンドを續けて書くことができます。その場合は ‘|’ 文字でコマンドを區切ります。そのため、マップの中では ‘|’ 文字が使へません。この文字を使ひたい場合は <Bar> (5文字) を使つてください。例:

:map <F8> :write <Bar> !checkin %:S<CR>

同じ問題は ":unmap" コマンドにもあります。":unmap" の場合はさらに末尾のスペースにも注意しなければなりません。以下の 2 つのコマンドは動作が違ひます:

:unmap a | unmap b
:unmap a| unmap b

1 つ目のコマンドは "a " (スペース付き) のマップを削除します。

マップの中でスペースを使ひたい場合は <Space> (7文字) を使つてください:

:map <Space> W

このマップはスペースキーを押すと、次の單語 (空白區切り) に移動します。

マップコマンドの末尾にはコメントを付けられません。なぜなら、‘"’ 文字はマップの一部として處理されてしまふからです。代はりに ‘|"’ を使つてください。これは、新しい空のコマンドを開始して、そのコマンドにコメントをつけます。例:

:map <Space> W|     " 次の單語に移動するのにスペースバーを使ふ

マップと短縮入力

插入モードのマップは短縮入力とよく似てゐます。引數は同じ方法で處理されます。主な違ひは實行されるタイミングです。短縮入力は單語の後で單語以外の文字を入力したときに實行されます。マップはマップ文字列の最後の文字を入力したときに實行されます。

違ひは他にもあります。短縮入力では入力した文字がすぐに插入されます。短縮入力が實行されると元の文字が削除されて指定された文字列に置換されます。マップされた文字を入力したときは最後の文字を入力してマップが實行されるまで何も插入されません。’showcmd’ オプションがオンに設定されてゐる場合は、入力途中の文字がウィンドウ下部に表示されます。

マップがあゐまいな場合は少し違ふ動作になります。例へば、次の 2 つのマップがあるとき:

:imap aa foo
:imap aaa bar

"aa" と入力した時點では、1 つ目のマップを適用すべきか、それとも 2 つ目のマップを使ふべきか、判斷できません。その場合は、他の文字が入力されるまで待機狀態になります。"a" を入力すると 2 つ目のマップが適用されて "bar" が插入されます。他の文字、例へばスペース、を入力すると 1 つ目のマップが適用されて "foo" が插入され、さらにスペースが插入されます。

さらに...

<script> キーワードを使ふと、スクリプトローカルなマップを定義できます。|:map-<script>| 參照。

<buffer> キーワードを使ふと、バッファローカルなマップを定義できます。|:map-<buffer>| 參照。

<unique> キーワードを使ふと、定義しようとしたマップがすでに定義されてゐた場合にコマンドが失敗します。このキーワードを使はない場合は、古いマップが上書き定義されます。|:map-<unique>| 參照。

何もしないキーを定義したい場合は <Nop> (5文字) を使ひます。次のコマンドは、<F7> キーが何もしないやうに設定してゐます:

:map <F7> <Nop>| map! <F7> <Nop>

<Nop> の後に空白を入れないでください。

コマンドラインコマンドを定義する

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

次のコマンドが實行されます:

: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>

コマンドを削除したい場合は ":delcommand" を使ひます。削除したいコマンドの名前を引數に指定してください。例:

:delcommand SaveIt

次のコマンドですべてのユーザー定義コマンドを削除できます:

:comclear

コマンドの削除はアンドゥできないので注意してください。

ユーザー定義コマンドについての詳細はリファレンスマニュアルを參照してください。|user-commands|。

自動コマンド

自動コマンドとは、さまざまなイベントに應じて自動的に實行されるコマンドのことです。ファイルを讀み書きしたり、バッファを切り替へたりしたときに實行されます。例へば、|gzip| プラグインは、壓縮ファイルを開くために自動コマンドを使つてゐます。

自動コマンドは非常に强力です。適切に使へばいろんな手閒を省くことができます。しかし、不適切な使ひ方をすればさまざまなトラブルの原因になります。

例へば、ファイルを保存するときに、保存した日附をファイル末尾に書き込んでみませう。まづ、次の函數を定義します:

:function DateInsert()
:  $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} に指定します。

イベント

BufReadPost は最も便利なイベントの 1 つです。これは新しいファイルを開いたときに發行されます。普通はオプションを設定したりするのに使はれます。例へば、"*.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 cprograms BufReadPost *.c,*.h :set sw=4 sts=4
: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

長いコマンドを見やすくするために、バックスラッシュを使つて複數行に分けてゐます。この方法はスクリプトファイルの中だけで使へます (コマンドラインで入力するときは使へません)。

自動コマンドの中で複雜なことを實行すると、必然的にカーソルの位置が變はつてしまひます。それを元に戾す方法については |restore-position| を參照してください。

イベントの無效化

自動コマンドを實行して欲しくないときは、’eventignore’ オプションに無視したいイベントを設定してください。例へば、次のやうに設定すると、他のウィンドウに移動したときのイベントが無視されます:

:set eventignore=WinEnter,WinLeave

すべてのイベントを無視するには、次のやうに設定します:

:set eventignore=all

通常の狀態に戾すには、’eventignore’ を空に設定します:

:set eventignore=

Next: , Previous: , Up: 目次   [Index]