main help file
*map.txt* For Vim バージョン 7.3. Last change: 2011 Jun 13 VIM REFERENCE MANUAL by Bram Moolenaar キーマップ、短縮入力、ユーザ定義コマンドについて。 ユーザマニュアルの|05.3|、|24.7|、|40.1|でこの機能について紹介しています。 1. マップ |key-mapping| 1.1 マップコマンド |:map-commands| 1.2 特別な引数 |:map-arguments| 1.3 マップとモード |:map-modes| 1.4 マップの一覧表示 |map-listing| 1.5 特殊キーのマップ |:map-special-keys| 1.6 特殊文字 |:map-special-chars| 1.7 マップに使うキー |map-which-keys| 1.8 例 |map-examples| 1.9 マップを使う |map-typing| 1.10 Altキーを使ったマップ |:map-alt-keys| 1.11 オペレーターの作成 |:map-operator| 2. 短縮入力 |abbreviations| 3. ローカルマップとローカル関数 |script-local| 4. ユーザ定義コマンド |user-commands| ============================================================================== 1. マップ (Key mapping) *key-mapping* *mapping* *macro* マップは入力キーの動作を変更するために使われます。一般的にはファンクションキー にコマンドを割り当てるのに使われます。例: :map <F2> a<C-R>=strftime("%c")<CR><Esc> このマップはカーソルの位置に現在の日時を挿入します。(<F2>などは|<>|表記法を参照) 1.1 マップコマンド *:map-commands* マップを新しく作成、削除、一覧表示するコマンドがあります。マップコマンドの種類 とモードの関係については |map-overview|を参照してください。 {lhs} left-hand-side (左辺値) の略 *{lhs}* {rhs} right-hand-side (右辺値) の略 *{rhs}* :map {lhs} {rhs} |mapmode-nvo| *:map* :nm[ap] {lhs} {rhs} |mapmode-n| *:nm* *:nmap* :vm[ap] {lhs} {rhs} |mapmode-v| *:vm* *:vmap* :xm[ap] {lhs} {rhs} |mapmode-x| *:xm* *:xmap* :smap {lhs} {rhs} |mapmode-s| *:smap* :om[ap] {lhs} {rhs} |mapmode-o| *:om* *:omap* :map! {lhs} {rhs} |mapmode-ic| *:map!* :im[ap] {lhs} {rhs} |mapmode-i| *:im* *:imap* :lm[ap] {lhs} {rhs} |mapmode-l| *:lm* *:lmap* :cm[ap] {lhs} {rhs} |mapmode-c| *:cm* *:cmap* キー入力 {lhs} を {rhs} に割り当てます。作成したマップ は、マップコマンドに対応したモードで使用できます。マッ プが使用されたときに {rhs} が調べられ、再マップされま す。マップを入れ子にしたり再帰的にすることができます。 :no[remap] {lhs} {rhs} |mapmode-nvo| *:no* *:noremap* :nn[oremap] {lhs} {rhs} |mapmode-n| *:nn* *:nnoremap* :vn[oremap] {lhs} {rhs} |mapmode-v| *:vn* *:vnoremap* :xn[oremap] {lhs} {rhs} |mapmode-x| *:xn* *:xnoremap* :snor[emap] {lhs} {rhs} |mapmode-s| *:snor* *:snoremap* :ono[remap] {lhs} {rhs} |mapmode-o| *:ono* *:onoremap* :no[remap]! {lhs} {rhs} |mapmode-ic| *:no!* *:noremap!* :ino[remap] {lhs} {rhs} |mapmode-i| *:ino* *:inoremap* :ln[oremap] {lhs} {rhs} |mapmode-l| *:ln* *:lnoremap* :cno[remap] {lhs} {rhs} |mapmode-c| *:cno* *:cnoremap* キー入力 {lhs} を {rhs} に割り当てます。作成したマッ プ、はマップコマンドに対応したモードで使用できます。 {rhs} は再マップされないので、マップが入れ子になったり 再帰的になることはありません。コマンドを再定義するとき によく使われます。 {Vi にはない機能です} :unm[ap] {lhs} |mapmode-nvo| *:unm* *:unmap* :nun[map] {lhs} |mapmode-n| *:nun* *:nunmap* :vu[nmap] {lhs} |mapmode-v| *:vu* *:vunmap* :xu[nmap] {lhs} |mapmode-x| *:xu* *:xunmap* :sunm[ap] {lhs} |mapmode-s| *:sunm* *:sunmap* :ou[nmap] {lhs} |mapmode-o| *:ou* *:ounmap* :unm[ap]! {lhs} |mapmode-ic| *:unm!* *:unmap!* :iu[nmap] {lhs} |mapmode-i| *:iu* *:iunmap* :lu[nmap] {lhs} |mapmode-l| *:lu* *:lunmap* :cu[nmap] {lhs} |mapmode-c| *:cu* *:cunmap* マップコマンドに対応したモードの {lhs} というマップを 削除します。他のモードのマップは残ります。 Note: 末尾の空白は {lhs} に含まれます。次の unmap コマ ンドは機能しません: :map @@ foo :unmap @@ | print :mapc[lear] |mapmode-nvo| *:mapc* *:mapclear* :nmapc[lear] |mapmode-n| *:nmapc* *:nmapclear* :vmapc[lear] |mapmode-v| *:vmapc* *:vmapclear* :xmapc[lear] |mapmode-x| *:xmapc* *:xmapclear* :smapc[lear] |mapmode-s| *:smapc* *:smapclear* :omapc[lear] |mapmode-o| *:omapc* *:omapclear* :mapc[lear]! |mapmode-ic| *:mapc!* *:mapclear!* :imapc[lear] |mapmode-i| *:imapc* *:imapclear* :lmapc[lear] |mapmode-l| *:lmapc* *:lmapclear* :cmapc[lear] |mapmode-c| *:cmapc* *:cmapclear* マップコマンドに対応したモードのすべてのマップを削除し ます。{Vi にはない機能です} バッファローカルなマップを削除するには <buffer> 引数を 付けてください |:map-<buffer>|。 mappings |:map-<buffer>| 警告: 標準設定のマップも削除されます。 :map |mapmode-nvo| :nm[ap] |mapmode-n| :vm[ap] |mapmode-v| :xm[ap] |mapmode-x| :sm[ap] |mapmode-s| :om[ap] |mapmode-o| :map! |mapmode-ic| :im[ap] |mapmode-i| :lm[ap] |mapmode-l| :cm[ap] |mapmode-c| マップコマンドに対応したモードのすべてのマップを一覧表 示します。Note: ":map" と ":map!" は複数のモードを表示 できるのでよく使われます。 :map {lhs} |mapmode-nvo| *:map_l* :nm[ap] {lhs} |mapmode-n| *:nmap_l* :vm[ap] {lhs} |mapmode-v| *:vmap_l* :xm[ap] {lhs} |mapmode-x| *:xmap_l* :sm[ap] {lhs} |mapmode-s| *:smap_l* :om[ap] {lhs} |mapmode-o| *:omap_l* :map! {lhs} |mapmode-ic| *:map_l!* :im[ap] {lhs} |mapmode-i| *:imap_l* :lm[ap] {lhs} |mapmode-l| *:lmap_l* :cm[ap] {lhs} |mapmode-c| *:cmap_l* マップコマンドに対応したモードの {lhs} で始まるマップ を一覧表示します。 {Vi にはない機能です} マップコマンドを使うと、単キーまたは複数キーの入力を別の文字列にマップできま す。ファンクションキーにコマンド列を割り当てたり、あるキーを別のキーに変換した りできます。マップを保存、復元する方法については |:mkexrc| を参照してくださ い。 *map-ambiguous* 二つのマップがあって、両方とも同じ文字で始まっている場合、どちらを使用するかが あいまいになってしまいます。例: :imap aa foo :imap aaa bar "aa" と入力したとき、"aa" と "aaa" のどちらを使用するかを決定するためには、次 の文字が必要になります。そのため、"aa" が入力された時点ではまだマップは適用さ れず、次の入力まで待機状態になります。例えば空白文字を入力すれば "foo" と空白 文字が挿入されます。"a" を入力すれば "bar" が挿入されます。 {Vi はあいまいなマップを許可しません} 1.2 特別な引数 *:map-arguments* 引数に "<buffer>"、"<silent>"、"<special>"、"<script>"、"<expr>"、"<unique>"、 を指定できます。マップコマンドの直後 (他の引数の前) に置いてください。 *:map-local* *:map-<buffer>* *E224* *E225* カレントバッファだけで使用できるマップを作成するには、マップコマンドの引数に "<buffer>" を指定します。例: :map <buffer> ,w /[.,;]<CR> この場合、他のバッファで、",w" に対して別の操作を割り当てることができます: :map <buffer> ,w /[#&!]<CR> バッファローカルなマップは通常のマップよりも優先して使用されます。 "<buffer>" はマップを削除するときにも指定できます: :unmap <buffer> ,w :mapclear <buffer> バッファローカルのマップはそのバッファが削除されるときにいっしょに消去されま す。アンロード(|:bunload|)では消去されません。ローカルオプションと同じです。 *:map-<silent>* *:map-silent* 実行するコマンドがコマンドラインに表示されないようにするには、マップコマンドの 引数に "<silent>" を指定します。例: :map <silent> ,h /Header<CR> このマップを使用するとき、検索文字列はコマンドラインに表示されません。しかし、 実行されたコマンドが出力するメッセージは表示されてしまいます。それを静かにさせ るには ":silent" を使います。 :map <silent> ,h :exe ":silent normal /Header\r"<CR> それでもまだ、例えば inputdialog() のプロンプトなどは表示されます。 "<silent>" は短縮入力にも使えますが、コマンドラインで使うと正しく表示されなく なります。 *:map-<special>* *:map-special* 'cpoptions' に "<" フラグが入っている場合でも、<> 表記を使って特殊キーを記述で きます。'cpoptions' を設定することで副作用を発生させたくない場合に使ってくださ い。例: :map <special> <F12> /Header<CR> *:map-<script>* *:map-script* マップや短縮入力を定義するときに "<script>" 引数を指定すると、{rhs} の中の "<SID>" で始まるスクリプトローカルなマップだけが再マップされます。別の場所で マップが定義されていても (例えば mswin.vim で CTRL-V にマップが定義されていて もに)、その影響を避けることができます。その場合でも同じスクリプトで定義された マップは使うことができます。 Note: ":map <script>" と ":noremap <script>" の動作は同じです。コマンド名より "<script>" の効果が優先されます。再マップが制限されることが明確になるため ":noremap <script>" を使う方がいいでしょう。 *:map-<unique>* *E226* *E227* マップや短縮入力を定義するときに "<unique>" 引数を指定すると、同じ名前のものが すでに定義されていた場合に、コマンドは失敗します。例: :map <unique> ,w /[#&!]<CR> バッファローカルのマップを定義するときは、通常のマップも検査の対象となります。 失敗する例: :map ,w /[#&!]<CR> :map <buffer> <unique> ,w /[.,;]<CR> すでにマップされている機能をそのままに、新たにマップを設定したい場合は、 |maparg()| を参照してください。 *:map-<expr>* *:map-expression* マップや短縮入力を定義するときに "<expr>" 引数を指定すると、引数が式 (スクリプ ト) として扱われます。マップが実行されたときに、式が評価され、その値が {rhs} として使われます。例: :inoremap <expr> . InsertDot() InsertDot() 関数の戻り値が挿入されます。カーソルの前のテキストをチェックして、 ある条件に一致するなら omni 補完を開始する、というようなことができます。 短縮入力では、入力されて短縮入力展開のトリガーとなった文字が |v:char| にセット されます。これを使って {lhs} の展開方法を決めることもできます。自分で v:char を挿入したり変更したりすべきではありません。 副作用に注意してください。式は文字の取得中に評価されるため、簡単に異常動作を起 こせてしまいます。そのため、次のものは制限されます: - バッファのテキストの変更 |textlock|。 - 他のバッファの編集。 - |:normal| コマンド。 - カーソルの移動は可能ですが、後で元に戻されます。 - getchar() は使用できますが、既存の入力バッファからは取得できず、新しい入力 バッファは捨てられます。 以上のことを実現したい場合は、そのためのコマンド文字列を返してください。 例を示します。リスト番号を自動的に増加させつつ挿入します: let counter = 0 inoremap <expr> <C-L> ListItem() inoremap <expr> <C-R> ListReset() func ListItem() let g:counter += 1 return g:counter . '. ' endfunc func ListReset() let g:counter = 0 return '' endfunc CTRL-L で次の番号を挿入し、CTRL-R で番号をリセットします。CTRL-R は空文字列を 返すので、なにも挿入されません。 Note: 特殊キーが機能するようにしたり、テキスト中の CSI バイトをエスケープした りするために、特別な処理が行われています。|:map| コマンドも同様の処理を行うの で、それが二重に実行されるのを防ぐ必要があります。次のものは機能しません: :imap <expr> <F3> "<Char-0x611B>" なぜなら、<Char- で表記した文字 (あるいは本物の文字) のバイト列は |:imap| コマ ンドが解釈されるときにエスケープされ、<expr> で使われるときにもう一度エスケー プされるからです。次のものは機能します: :imap <expr> <F3> "\u611B" テキストの末尾以外で 0x80 をシングルバイトとして使った場合、それは機能しませ ん。特殊キーとして認識されます。 1.3 マップとモード *:map-modes* *mapmode-nvo* *mapmode-n* *mapmode-v* *mapmode-o* マップには 6 つの種類があります。 - ノーマルモード: ノーマルモードのコマンドを入力するとき。 - ビジュアルモード: ビジュアルモードのコマンドを入力するとき。 - セレクトモード: ビジュアルモードに似ていますが入力したテキストによって選択範 囲が置換されます。 - モーション待ちモード: コマンドを入力した後で、移動 (|{motion}|) を待って いるとき("d"、"y"、"c"、などの後)。|omap-info| 参照。 - 挿入モード: 上書きモードでも使われます。 - コマンドラインモード: ":" もしくは "/" コマンドを入力したとき。 例外として、ノーマルモードでカウント(コマンドの繰り返し回数)を入力しているとき は、0 (ゼロ)に対するマップは適用されません。これは 0 がマップされていても、カ ウントの指定でゼロを入力できるようにするためです。 *map-overview* *map-modes* マップコマンドとモードの対応表: コマンド: モード: ノーマル ビジュアル+セレクト 演算待ち状態 :map :noremap :unmap :mapclear yes yes yes :nmap :nnoremap :nunmap :nmapclear yes - - :vmap :vnoremap :vunmap :vmapclear - yes - :omap :onoremap :ounmap :omapclear - - yes :nunmap は修道院の外でも使えます。 *mapmode-x* *mapmode-s* いくつかのコマンドはビジュアルモードとセレクトモードの両方で機能しますが、そう でないコマンドもあります。「ビジュアル」という言葉がビジュアルモードとセレクト モードの両方を指している場合が多々あるので注意してください。 |Select-mode-mapping| NOTE: セレクトモードで印字可能文字にマップを定義するとユーザーの混乱を招くかも しれません。印字可能文字に対しては明示的に :xmap と :smap を使い分けるのがいい でしょう。マップを定義したあとで :sunmap を使う方法もあります。 コマンド: モード: ビジュアル セレクト :vmap :vnoremap :vunmap :vmapclear yes yes :xmap :xnoremap :xunmap :xmapclear yes - :smap :snoremap :sunmap :smapclear - yes *mapmode-ic* *mapmode-i* *mapmode-c* *mapmode-l* Some commands work both in Insert mode and Command-line mode, some not: コマンド: モード: 挿入 コマンドライン Lang-Arg :map! :noremap! :unmap! :mapclear! yes yes - :imap :inoremap :iunmap :imapclear yes - - :cmap :cnoremap :cunmap :cmapclear - yes - :lmap :lnoremap :lunmap :lmapclear yes* yes* yes* 訳注: Lang-Argについては |language-mapping| を参照 オリジナルの Vi はノーマルモード、ビジュアルモード、演算待ち状態モード、でひと まとまり、挿入モード、コマンドラインモード、でさらにひとまとまりのマップを持 ち、それぞれ区別されていませんでした。そのため、Vim の ":map" と ":map!" コマ ンドは複数のモードに対してマップを設定したり表示したりします。 Vim では ":nmap"、":vmap"、":omap"、":cmap"、":imap" を使い分けることで、それ ぞれのモード別にマップを設定することができます。 *omap-info* オペレータ待機マップを使うと、移動コマンドを定義できます。そして、オペレータと 組み合わせて使うことができます。簡単な例: ":omap { w" を定義した場合、"y{" が "yw" として、"d{" が "dw" として機能するようになります。 マップ適用時のカーソル位置を無視し、異なるテキストを選択するには、omap 内でビ ジュアルモードを開始して対象となるテキストを選択してください。例えば、現在行の 関数名を選択するには次のようにします: onoremap <silent> F :<C-U>normal! 0f(hviw<CR> CTRL-U (<C-U>) を使って (Vimによって挿入される) 範囲指定を削除しています。ノー マルモードコマンドを使って、最初の '(' 文字を探し、その前にある単語を選択しま す。通常はこれで関数名を選択できるでしょう。 あるマップをノーマルモードとビジュアルモードで使用し、そして、演算待ち状態モー ドでは使用しないという場合は、3つのモードに対してマップを定義してから演算待ち 状態モードのマップだけを削除します: :map xx something-difficult :ounmap xx ビジュアルモードと演算待ち状態モードの場合や、ノーマルモードと演算待ち状態モー ドの場合も同様にします。 *language-mapping* ":lmap" で定義したマップ(以下、言語マップ)は次の場面で利用できます: - 挿入モード - コマンドラインモード - 検索パターンを入力するとき - "r" や "f" などのコマンドに続いて文字を入力するとき - input() の入力 大まかに説明すると、Vim コマンドとしてではなく、テキストの一部として入力するよ うなときにはいつでも利用できます。"Lang-Arg" は別個のモードではなく、そのよう な場面の総称です。 ある言語用の言語マップをロードするには、オプション 'keymap' を設定するのが 簡単です。|45.5|を参照してください。 挿入モードとコマンドラインモードでは CTRL-^ で言語マップの使用の有無を切り替 えることができます|i_CTRL-^| |c_CTRL-^|。(検索パターンの入力ではなく)コマンド ラインに入力するときには CTRL-^ で切り替えるまで言語マップは無効になっています。 挿入モードと検索パターンでの使用状態は別々に記録されます。挿入モードの使用状態 は "f" や "t" などのコマンドで文字を入力するときにも使用されます。 言語マップは、既にマップが適用された文字には適用されません。言語マップは入 力された文字に対してのみ使用されます。これは、言語マップは文字が入力されたとき に適用されたはずという想定によるものです。 1.4 マップの一覧表示 *map-listing* マップを一覧表示したときの行頭の2文字は使用できるモードを表しています: CHAR MODE <Space> ノーマル、ビジュアル、セレクト、演算待ち状態モード n ノーマルモード v ビジュアルモード、セレクトモード s セレクトモード x ビジュアルモード o 演算待ち状態モード ! 挿入モード、コマンドラインモード i 挿入モード l Lang-Argモード。|language-mapping| c コマンドラインモード {rhs} の直前に特殊な文字が表示されているものは次のことを意味します: * 再マップされません & スクリプトローカルなマップだけが再マップされます @ バッファローカルなマップです。 {lhs} の後ろの最初の非空白文字から行末 (もしくは'|') までのすべての文字は {rhs} の一部です。そのため {rhs} の末尾を空白文字にすることができます。 Note: ビジュアルモードのマップでは "'<" マークが使えます。これはカレントバッ ファで選択されていた範囲の開始位置を示しています|'<|。 *:map-verbose* 'verbose' がゼロ以外のときにマップ一覧を表示すると、どこで定義されたのかも表示 されます。例: :verbose map <C-W>* n <C-W>* * <C-W><C-S>* Last set from /home/abcd/.vimrc 詳しくは |:verbose-cmd| を参照してください。 1.5 特殊キーのマップ *:map-special-keys* 特殊キーをマップに含めるのには次の 3 つの方法があります: 1. Vi 互換の方法: 生のキーコードをマップします。それはほとんどの場合 <Esc> で 始まるキーコード列です。このようなマップを入力するには、まず ":map " と入力 し、CTRL-V を押してからファンクションキーを押します。Note: そのキーのキー コードが termcap(t_options) にある場合は、自動的に内部コードの形式に変換さ れ、次の 2. のようなマップになります ('cpoptions' に 'k' フラグが指定されて いる場合は除く) 2. ファンクションキーの内部コードを使います。そのようなマップを入力するには、 CTRL-K を押してからファンクションキーを押します。もしくは、 "#1"、"#2"、.."#9"、"#0"、"<Up>"、"<S-Down>"、"<S-F7>"、などの形式で指定し ます。(キーの表は |key-notation| 参照。<Up> 以下のすべてのキーを使うことが できます)。1 から 10 までのファンクションキーは二つの方法で定義できます: "#2" のような番号だけの方法と、"<F2>" という表記で指定する方法です。この両 方がファンクションキー 2 を表します。"#0" はファンクションキー 10 を表し、 't_f10' で定義されます。"#0" は、キーボードによってはファンクションキー 0に なることがあります。'cpoptions' に '<' フラグが指定されている場合は、|<>|表 記は使えません。 3. termcap エントリを <t_xx> という形式で指定します。"xx" は termcap エントリ の名前です。どんなエントリの文字列も使うことができます。例: :map <t_F3> G これはファンクションキー 13 を "G" にマップします。'cpoptions' に '<' フラ グが指定されている場合は使えません。 2. と 3. の方法の利点は、異なる端末でもマップを修正する必要がないことです(ファ ンクションキーは、同じ意味の内部コード、もしくは実際のキーコードに変換されま す。使用している端末に依存しません。termcap が正しく設定されていれば、異なる端 末で同じマップを共有できます)。 詳細: まず Vim はキーボードから送られたキーコードがマップされているかどうかを 調べます。マップされていなければ、端末のキーコードかどうか調べます(参照 |terminal-options|)。端末コードであれば、内部コードで置き換えます。それからも う一度、マップされているかどうかをチェックします (これにより内部コードをマップ できます)。スクリプトファイルに書き込まれる内容は、どのように解釈されたかによ ります。端末のキーコードがマップとして認識された場合は、キーコードそのものがス クリプトファイルに書き込まれます。端末コードとして認識された場合は、内部コード がスクリプトファイルに書き込まれます。 訳注: > スクリプトファイルに書き込まれる... 訳注: おそらく |-w| の話。 1.6 特殊文字 *:map-special-chars* *map_backslash* Note: このドキュメントでは、マップや短縮入力を定義するときに、CTRL-V だけが特 殊な文字として触れられていますが、'cpoptions' が 'B' を含んでいない場合は、 バックスラッシュも CTRL-V と同様の特殊な働きをします。|<>| 表記も問題なく使用 できます。しかし、"<C-V>" を CTRL-V と同じように、(マップを入力するときに)次の 文字をエスケープする目的で使うことはできません。 バックスラッシュにマップしたり、バックスラッシュをそのまま {rhs} に使いたい場 合は、特別文字 "<Bslash>" を使います。マップを入れ子にした場合などにバックス ラッシュを二重にする必要がなくなります。 *map_CTRL_C* CTRL-C を {lhs} で使うことはできますが、それは Vim がキー入力を待機中のときだ け機能します。Vim がビジー状態 (何かを実行中) のときは機能しません。Vim がビ ジー状態の場合、CTRL-C は実行中のコマンドを中断します。 MS-Windows の GUI 環境では、CTRL-C にマップすることができるので、クリップボー ドにコピーする機能を割り当てることができます。Vim の動作を中断するには CTRL-Break を使います。 *map_space_in_lhs* {lhs} に空白文字を含めるには CTRL-V を前置してください (空白文字の前で CTRL-V を二度押しで入力)。 *map_space_in_rhs* {rhs} を空白文字で開始するには "<Space>" を使ってください。Vi との互換性を完全 に保ちたい場合は |<>| 表記を使わずに、{rhs} の直前に CTRL-V (CTRL-V を二度押し で入力)を前置してください。 *map_empty_rhs* CTRL-V を1つだけ入力した後に (CTRL-Vを2度押しで入力) 何も入力しないことで空の {rhs} を作ることもできます。残念ながらvimrcファイル内ではこの方法は使用できま せん。 *<Nop>* 空のマップを作るには {rhs} に "<Nop>" を指定する方法が簡単です。これは |<>| 表 記を使えるようにしていれば動作します。例えば、ファンクションキー 8 は何もしな い、としたい場合は次のようにします: :map <F8> <Nop> :map! <F8> <Nop> *map-multibyte* マルチバイト文字をマップすることができます。ただし、マルチバイト文字の一部のバ イトだけをマップすることはできません。それは次のような問題が起こるのを防ぐため です: :set encoding=latin1 :imap <M-C> foo :set encoding=utf-8 latin1 環境で文字「Ã」(0xc3 または <M-C>) をマップしています。例えば、「á」 (0xe1 または <M-a>) は UTF-8 では 0xc3 0xa1 の 2 バイトで表現されるので、0xc3 をマップしてしまうと á が入力できなくなってしまいます。 *<Leader>* *mapleader* マップコマンドで特別な文字列 "<Leader>" を使用すると、その部分が変数 "mapleader" に設定された文字列で置き換わります。"mapleader" が空文字列のときや 設定されていない場合にはバックスラッシュが使用されます。例: :map <Leader>A oanother line<Esc> これは次のものと同じ意味です: :map \A oanother line<Esc> しかし次のように設定したあとでは: :let mapleader = "," 次のものと同じ意味になります: :map ,A oanother line<Esc> Note: 変数 "mapleader" はマップを定義するときに使用されます。"mapleader"を変更 しても、すでに定義されているマップには影響しません。 *<LocalLeader>* *maplocalleader* <LocalLeader> は <Leader> に似ていますが、"mapleader" ではなく "maplocalleader" を使用します。<LocalLeader> はバッファローカルのマップに使用 するといいでしょう。例: :map <LocalLeader>q \DoItNow グローバルプラグインでは <Leader> を使用し、ファイルタイププラグインでは <LocalLeader> を使用するといいでしょう。"mapleader" と "maplocalleader" の設定 は同じでも構いませんが、別の値を設定すれば、グローバルプラグインとファイルタイ ププラグインのマップが重なる可能性が低くなります。設定例としては、"mapleader" をバックスラッシュのままにしておいて、"maplocalleader" をアンダースコア (_) に するなど。 *map-<SID>* 特別な文字列 "<SID>" を使ってスクリプトローカルなマップを定義できます。詳細は |<SID>|を参照してください。 *<Plug>* 特別な文字列 "<Plug>" を使ってスクリプトの内部作業用のマップを定義できます。こ れはどのキー入力にもマッチしません。プラグインを作成するときに便利です |using-<Plug>|。 *<Char>* *<Char->* <Char> を使って、文字を10進数、8進数、16進数の数値指定でマップできます: <Char-123> character 123 <Char-033> character 27 <Char-0x7f> character 127 これは 'keymap' ファイルで (マルチバイト) 文字を定義するのに便利です。表記は大 文字でも小文字でも構いません。 *map-comments* マップコマンドでは '"' (ダブルクオート) も {lhs} や {rhs} の一部と見なされるた め、マップコマンドの後ろにコメントを置くことはできません。 *map_bar* '|' 文字は、マップコマンドと次のコマンドを分けるために使われるので、'|' 文字を {rhs} に含めるには特殊な方法が必要です。 次の3つの方法があります: 方法 使用できる条件 例 <Bar> 'cpoptions'に'<'が含まれていない :map _l :!ls <Bar> more^M \| 'cpoptions'に'b'が含まれていない :map _l :!ls \| more^M ^V| VimとViで常に使用できる :map _l :!ls ^V| more^M (ここで ^V は CTRL-V を表します。一つの CTRL-V を挿入するには CTRL-V を二度押 しで入力します。この用途では、|<>|表記を使って"<C-V>"とすることはできません)。 'cpoptions' が標準設定のままなら、三つ全ての方法が使用できます。 'cpoptions' に 'b' が含まれている場合、"\|" は、 '\' で終わるマップコマンドの 後に、別のコマンドが続いているとみなされます。これは Vi 互換ですが、他のコマン ドの場合を考えるとあまり論理的ではありません。 *map_return* マップに Ex コマンドを含める場合、そのコマンドラインを実行するために改行文字を 挿入する必要があります。これには <CR> を使うことが推奨されています(参照|<>|)。 例: :map _ls :!ls -l %<CR>:echo "the end"<CR> 挿入モードやコマンドラインモードで、入力する文字がマップされないようにするに は、その文字を入力する前に CTRL-V を (1回) 押してください。'paste' がオンの場 合には、挿入モードでマップを使用できません。 Note: マップを使用したときに、エラーが起きた場合 (エラーメッセージやビープ音が 出ます)、マップのまだ実行されていない部分は実行されません。これはVi互換です。 Note: コマンド「@zZtTfF[]rm'`"v」と CTRL-X の引数にはマップは適用されません。 どのようなマップがあっても、レジスタやマークを指定できるようにするためです。 1.7 マップに使うキー *map-which-keys* マップを定義するときに {lhs} に指定するキーを選ぶことができますが、Vim のコマ ンドに使われているキーをマップしてしまうとそれらのコマンドを使用できなくなりま す。そこで、いくつかの提案があります: - ファンクションキー (<F2>、<F3>など) や Shift+ファンクションキー(<S-F1>、 <S-F2>など) を使用する。<F1> には既にヘルプコマンドが割り当てられています。 - Meta キー (ALTキー) を使用する。あなたのキーボードのアクセント記号付き文字の 使用頻度に依存します。 |:map-alt-keys| - "_" や "," などの文字と別の文字を組み合わせて使用する。コマンド "_" と"," は すでに存在していますが (|_|と|,|を参照)、使う機会はあまりないでしょう。 - 他に類するコマンドがあるキーを使用する。例えば、CTRL-P と CTRL-N。さらに多く のマップを使用するには、複数文字を使用します。 - <Leader> と 1 つまたは複数のキーを組み合わせて使用する。これは特にスクリプト で便利です。 |mapleader| 標準のキー操作を損なうことなくマップできるキーや、使われていないキーを探すには |index.txt| を参照してください。":help {key}^D" を使用してそのキーが使われてい るかどうかを調べることもできます ({key}は調べたいキー、^DはCTRL-Dの入力)。 1.8 例 *map-examples* マップの例をいくつか示します (見た通り入力してください。"<CR>" は 4 文字です。 このような表記(|<>|)は 'cpoptions' に '<' が含まれていると使用できません)。 :map <F3> o#include :map <M-g> /foo<CR>cwbar<Esc> :map _x d/END/e<CR> :map! qq quadrillion questions カウント指定の掛け算 マップの展開前にカウント指定が入力されると、そのカウントは {lhs} の前に入力さ れたものとして扱われます。例えば、次のマップを定義したとき: :map <F4> 3w 2<F4> は "23w" となります。つまり、2 * 3 単語移動するのではなく、23 単語の移動 になります。カウントを掛けたい場合は式レジスタを使ってください: :map <F4> @='3w'<CR> クォートで囲まれた部分が実行される式です。|@=| 1.9 マップを使う *map-typing* Vim は、入力されたキーで始まるマップがあるかどうか調べ、そのようなマップがある 場合は、入力とマップが完全に一致するか一致しないと判断できるまで、次の入力を待 ちます。例えば、"qq" というマップがあるとして、最初に入力した'q' は、次の文字 を入力するまで実際に入力されません。なぜなら、Vim には次に入力される文字が 'q' であるかそうでないかを知ることができないからです。'timeout' がオンになっている と (標準設定はオンです)、Vim は一秒間 (または 'timeoutlen' で指定されている時 間) だけ待機します。待機した後に、'q' という文字が入力されたのだと判断します。 ゆっくり入力したい場合や、遅いシステムを使用している場合は、'timeout' をオフに してください。'ttimeout'を設定するのもいいでしょう。 *map-keys-fails* 次のような状況では、キーコードが認識されないことがあります: - Vim がキーコードを部分的にしか読めない。これは最初の文字だけ読める場合が多い です。特定の Unix 版と xterm の組み合わせで起こります。 - 文字(列)の後にキーコードがあるマップ。例、"<F1><F1>" や "g<F1>"。 このように、キーコードが認識されない状況では、そのようなマップを使用することが できません。対処方が2つあります: - 'cpoptions' から 'K' フラグを除く。そうすると Vim はファンクションキーの残り のコードを待つようになります。 - <F1> から <F4> のキーによって生成される実際のキーコードが <xF1> から <xF4> と同じ場合があります。<xF1> を <F1> へ、<xF2> を <F2>へ、といったマップが存 在しますが、これはマップの後半では認識されません。<F1> から <F4> のキーの キーコードを正しく設定してください: :set <F1>=<type CTRL-V><type F1> <F1> を四文字として入力してください。"=" の後の部分は文字通りにではなく、実 際のキーを入力してください。 マップを定義するときに二番目の特殊キーを実際のキーコードで指定することでも解決 できます: :map <F1><Esc>OP :echo "yes"<CR> 本物の <Esc> を入力しないでください。Vim がキーコードを認識し、<F1> に置き換え てしまいます。 他にも、ALT や Meta キーを押しながらキーを入力したときに、コードの 8 ビット目 をセットする代わりにそのキーに ESC を前置するような端末で問題が起こることがあ ります。|:map-alt-keys| を参照。 *recursive_mapping* {rhs} の中に {lhs} を含めて、再帰マップを作成できます。{lhs} を入力すると {rhs} に置き換えられ、{rhs} の中に {lhs} があるとその {lhs} がさらに {rhs} に 置き換えられ、さらに {rhs} の中の {lhs} が置き換えられ...。というようにコマン ドを無限に繰り返すことができます。エラーを生じさせないと止めることができないの が唯一の問題です。例外として、{rhs} が {lhs} で始まっている場合は、その文字は 再帰的にマップされません (これは Vi 互換です)。 例えば次のマップは: :map ab abcd "a" コマンドを実行して "bcd" を挿入します。{rhs} の中の "ab" は再帰的にマップ されません。 二つのキーの意味を入れ換えるような場合は :noremap を使ってください。例えば: :noremap k j :noremap j k これは、カーソルの上下移動のコマンドを入れ換えます。 普通の :map コマンドでマップを定義した場合、'remap' オプションがオンになってい ると、そのマップが使用された後のテキスト ({rhs}) に {lhs} が含まれている限り、 マップが再帰的に繰り返されます。例えば、次のようなマップを使用する場合: :map x y :map y x Vim はまず、 x を y で置き換え、それから y を x で置き換え、...。これを 'maxmapdepth' に設定された回数だけ (標準設定は1000回) 繰り返し、"recursive mapping" というエラーメッセージを表示します。 *:map-undo* マップされたもの({rhs})がアンドゥコマンドを含んでいると、その操作を実行する前 の状態に戻すことになります。アンドゥが1回だけなら、その動作はオリジナルのVi互 換です(オリジナルのViでは、2回アンドゥしても意味がなく、最初のアンドゥを実行す る前の状態に戻るだけです)。 1.10 ALT キーを使ったマップ *:map-alt-keys* GUI では、Vim は Alt キーを直接取り扱うので、ALT キーを使ったマップは常に機能 します。CUI 端末では、Vim は受け取ったバイト列から、ALT キーが押されているかど うかを割り出さなければなりません。 初期設定では、ALT キーが押されているときは、文字の 8 ビット目が設定されるもの と仮定しています。xterm、aterm、rxvt など、ほとんどの端末はこの方法で問題あり ません。<A-k> のようなマップが動作しない場合は、その端末が、文字の前に ESC を 付けているのかもしれません。ユーザーが文字の前に ESC を入力することもできます から、Vim は何が起きたか知ることはできません (ただし、ESC と文字の間に延滞があ るかどうかをチェックする方法はあります。確実な方法ではありませんが)。 現在、gnome-terminal や konsole などの主要な端末が ESC を前置します。代わりに 8 ビット目を使うように設定する方法はないようです。Xterm では設定なしで機能しま す。Aterm と rxvt では "--meta8" 引数を使えば機能します。"metaSendsEscape"、 "eightBitInput"、eightBitOutput" のようなリソースを設定することでも動作を変更 できます。 Linux コンソールでは、"setmetamode" コマンドで動作を切り替えることができます。 ESC の前置を使わないようにすると、他のプログラムで問題が起こる可能性があるので 注意してください。bash の "convert-meta" が "on" になっていることを確認し、 Meta キーバインディングが動作するようにしてください。(システム固有の設定変更を していなければ、これは readline の標準の動作です)次の行を ~/.inputrc に追加す ると、その設定をすることができます: set convert-meta on ファイルをはじめて作成した場合は、システム全体の設定を維持するために、次の行を 最初に加える必要があるかもしれません(そのファイルがシステムにある場合): $include /etc/inputrc このように設定すると、ウムラウトのような特殊な文字を入力できなくなるかもしれま せん。その場合は、文字の前に CTRL-V を入力してください。 convert-meta は UTF-8 ロケールでは問題を起こすことがすでに報告されています。 xterm のような端末では、起動しているときに、メニューの "Main Options" から "metaSendsEscape" リソースを設定できます。メニューは端末を Ctrl-LeftClick する と表示できます。他のアプリケーションでは ESC を使い、Vim では使いたくない、と いう場合にこのリソースを使うと便利です。 1.11 オペレーターの作成 *:map-operator* オペレーターは {motion} コマンドと合わせて使われます。独自のオペレーターを定義 するには、最初に 'operatorfunc' を設定し、そして、|g@| オペレーターを呼びま す。ユーザーが {motion} コマンドを実行した後、設定した関数が実行されます。 *g@* *E774* *E775* g@{motion} 'operatorfunc' に設定された関数を実行します。 '[ マークに {motion} で選択された範囲の最初の位置が設 定されます。'] マークには選択範囲の最後の位置が設定さ れます。 関数の引数には、文字列が一つ渡されます: "line" {motion} は行単位 |linewise| "char" {motion} は文字単位 |characterwise| "block" {motion} はブロック選択 |blockwise-visual| "block" はたまにしか使われません。ビジュアルモードの場 合だけ渡されるのですが、"g@" と合わせてもそれほど便利 ではないからです。 {|+eval| が有効な場合のみ利用できます} 例を示します。これは <F4> を使ってスペースの数を数えます: nmap <silent> <F4> :set opfunc=CountSpaces<CR>g@ vmap <silent> <F4> :<C-U>call CountSpaces(visualmode(), 1)<CR> function! CountSpaces(type, ...) let sel_save = &selection let &selection = "inclusive" let reg_save = @@ if a:0 " Invoked from Visual mode, use '< and '> marks. silent exe "normal! `<" . a:type . "`>y" elseif a:type == 'line' silent exe "normal! '[V']y" elseif a:type == 'block' silent exe "normal! `[\<C-V>`]y" else silent exe "normal! `[v`]y" endif echomsg strlen(substitute(@@, '[^ ]', '', 'g')) let &selection = sel_save let @@ = reg_save endfunction Note: 一時的に 'selection' を "inclusive" に設定し、'[ から '] まで選択した範 囲を正しくヤンクできるようにしています。 Note: ビジュアルモードのために別のマップを定義しています。ビジュアルモードで ":" を押した場合に挿入される "'<,'>" を削除し、関数に visualmode() の値と追加 の引数を渡しています。 ============================================================================== 2. 短縮入力 (Abbreviations) *abbreviations* *Abbreviations* 短縮入力は、挿入モード、上書きモード、コマンドラインモードで使えます。短縮入力 として登録されている単語を入力すると、それが表す単語に置き換えられます。よく使 う長い単語を打ち込むときのタイプ数を減らしたり、明確なスペルミスを自動的に修正 するのに使えます。 例: :iab ms Microsoft :iab tihs this 短縮入力には三つの種類があります: full-id "full-id" タイプは完全なキーワード文字から構成されます( 'iskeyword' オプションに含まれる文字です)。最も一般的な短縮入力です。 例: "foo", "g3", "-1" end-id "end-id" タイプはキーワード文字で終わりますが、他の文字はキーワード 文字ではありません。 例: "#i", "..f", "$/7" non-id "non-id" タイプは非キーワード文字で終わります。他の文字はスペースと タブ文字以外のどんな文字でもよいです。{Vi では、このタイプはサポート されていません} 例: "def#", "4/7$" 短縮入力にできない文字列の例: "a.b", "#def", "a b", "_$r" 短縮入力は非キーワード文字を入力したときに展開されます。これは、挿入モードを終 わらせる<Esc>を入力したり、コマンドを終わらせる<CR>を入力したときにも起こりま す。短縮入力を終わらせる非キーワード文字は、短縮入力を展開した後に挿入されま す。<C-]>文字は例外で、短縮入力だけが展開され挿入されます。 例: :ab hh hello "hh<Space>" で "hello<Space>" に展開されます。 "hh<C-]>" で "hello" に展開されます。 カーソルの前の文字が短縮入力とマッチする場合のみ機能します。短縮入力の種類に よって、さらに条件があります: full-id マッチした場所の前が非キーワード文字、行頭、挿入を開始した場所、であ ること。例外: 短縮入力が1文字の場合、その前の文字がスペース、タブ、 以外の非キーワード文字なら短縮入力は展開されません。 end-id マッチした場所の前が非キーワード文字、スペース、タブ、行頭、挿入を開 始した場所、であること。 non-id マッチした場所の前がタブ、行頭、挿入を開始した場所、であること。 例: ({CURSOR}は非キーワード文字を入力する場所です) :ab foo four old otters " foo{CURSOR}" は " four old otters" に展開されます " foobar{CURSOR}" は展開されません "barfoo{CURSOR}" は展開されません :ab #i #include "#i{CURSOR}" は "#include" に展開されます ">#i{CURSOR}" は展開されません :ab ;; <endofline> "test;;" は展開されません "test ;;" は "test <endofline>" に展開されます 挿入モードで短縮入力の展開を避けるには、短縮入力の一部を入力してから挿入モード を <Esc> で抜け、再度挿入モードに "a" で入って残りを入力します。もしくは、 CTRL-V を押してから短縮入力の後の文字を入力します。 コマンドラインモードで短縮入力の展開を避けるには、短縮入力の文字の途中でCTRL-V を入力します (CTRL-V を2度押し)。展開されなかった場合、普通の文字の前のCTRL-V は普通は無視されます。 短縮入力の後で、カーソルを動かすこともできます: :iab if if ()<Left> これは、'cpoptions'に'<'フラグが含まれていると、うまく動作しません。|<>| さらに手の込んだこともできます。例えば、短縮入力を展開するときに入力したスペー スを消してしまうには: func Eatchar(pat) let c = nr2char(getchar(0)) return (c =~ a:pat) ? '' : c endfunc iabbr <silent> if if ()<Left><C-R>=Eatchar('\s')<CR> 標準設定されている短縮入力はありません。 短縮入力の展開は再帰的には行われません。":ab f f-o-o" という短縮入力を問題なく 使うことができます。しかし、展開された文字にはマップが適用されます。 {Vi のい くつかのバージョンで再帰的な短縮入力をサポートしていますが、そこになんら明確な 理由はありません} 'paste'オプションがオンの場合、短縮入力は使用できません。 *:abbreviate-local* *:abbreviate-<buffer>* マップと同じように、バッファローカルな短縮入力を作成できます。これは主に |filetype-plugin|などで使用されます。C言語用プラグインの例: :abb <buffer> FF for (i = 0; i < ; ++i) *:ab* *:abbreviate* :ab[breviate] すべての短縮入力を一覧表示します。行頭の文字は、その短 縮入力を使用できるモードを示しています: 'i' は挿入モー ド、'c' はコマンドラインモード、'!' はその両方。マップ の一覧表示と同じです。|map-listing|を参照。 *:abbreviate-verbose* 'verbose' がゼロ以外のときに短縮入力一覧を表示すると、どこで定義されたのかも表 示されます。例: :verbose abbreviate ! teh the Last set from /home/abcd/vim/abbr.vim 詳しくは |:verbose-cmd| を参照してください。 :ab[breviate] {lhs} {lhs} で始まる短縮入力を一覧表示します。 {lhs} に入力した文字が短縮入力として展開されないように するには CTRL-V (2度押しで入力する) を挿入します。そう しないとコマンドライン用の短縮入力があった場合にそれが 展開されてしまいます。 :ab[breviate] [<expr>] [<buffer>] {lhs} {rhs} {rhs} の短縮入力を {lhs} として定義します。既に {lhs} が定義されていると、新しい {rhs} で置き換えられます。 {rhs} はスペースを含んでいてもかまいません。 <expr> 引数については|:map-<expr>|を参照してください。 <buffer> 引数については |:map-<buffer>| を参照してくだ さい。 *:una* *:unabbreviate* :una[bbreviate] {lhs} {lhs} という短縮入力を全て削除します。見つからなかった 場合は、{lhs} に入力した文字を各短縮入力の {rhs} から 探して見つかったものを削除します。これは短縮入力が展開 されてしまった状態でも削除できるようにするためです。短 縮入力の展開を防ぐには CTRL-V (2度押しで入力する) を挿 入します。 *:norea* *:noreabbrev* :norea[bbrev] [<expr>] [<buffer>] [lhs] [rhs] ":ab" と同じですが、展開後にマップを適用しません。 {Vi にはない機能です} *:ca* *:cabbrev* :ca[bbrev] [<expr>] [<buffer>] [lhs] [rhs] ":ab" と同じですが、コマンドラインモード用の短縮入力の み対象です。{Vi にはない機能です} *:cuna* *:cunabbrev* :cuna[bbrev] {lhs} ":una" と同じですが、コマンドラインモード用の短縮入力 のみ対象です。{Vi にはない機能です} *:cnorea* *:cnoreabbrev* :cnorea[bbrev] [<expr>] [<buffer>] [lhs] [rhs] ":ab" と同じですが、コマンドラインモード用の短縮入力の み対象で、展開後にマップを適用しません。{Vi にはない機 能です} *:ia* *:iabbrev* :ia[bbrev] [<expr>] [<buffer>] [lhs] [rhs] ":ab" と同じですが、挿入モード用の短縮入力のみ対象で す。{Vi にはない機能です} *:iuna* *:iunabbrev* :iuna[bbrev] {lhs} ":una" と同じですが、挿入モード用の短縮入力のみ対象で す。{Vi にはない機能です} *:inorea* *:inoreabbrev* :inorea[bbrev] [<expr>] [<buffer>] [lhs] [rhs] ":ab" と同じですが、挿入モード用の短縮入力のみ対象で、 展開後にマップを適用しません。{Vi にはない機能です} *:abc* *:abclear* :abc[lear] [<buffer>] すべての短縮入力を削除します。{Vi にはない機能です} *:iabc* *:iabclear* :iabc[lear] [<buffer>] 挿入モード用の短縮入力を削除します。 {Vi にはない機能です} *:cabc* *:cabclear* :cabc[lear] [<buffer>] コマンドラインモード用の短縮入力を削除します。 {Vi にはない機能です} *using_CTRL-V* 特殊な文字を短縮入力の{rhs}で使うことができます。非印字可能文字の特殊な意味を 打ち消す(クォートする)には、CTRL-Vを使用します。必要なCTRL-Vの数は、どのような 短縮入力を作成するかによります。これはマップでも同様です。例を示します. "esc"を実際の<Esc>文字を挿入する短縮入力にしたいとしましょう。Vim で":ab"コマ ンドを使うときには、次のようにしなければなりません: (ここで^VはCTRL-Vで、^[は <Esc>です) 入力: ab esc ^V^V^V^V^V^[ キー入力はすべて^Vによるクォートが適用されます。つまり、1番目、3番目、 5番目の^Vは、2番目と4番目の^Vと、^[がコマンドラインに入力されるように しています。 見え方: ab esc ^V^V^[ コマンドラインには実際には2つの^Vと^[が表示されています。もしそうする つもりがあれば、これは .exrc ファイルでの見え方になるはずです。始めの ^Vは2番目の^Vをクォートするためにあります。:abコマンドは^Vをクォート文 字として扱いますので、短縮入力の中で、クォートされた空白文字や'|'文字 を使うことができます。:abコマンドは^[に対しては何も特殊な処理は行いま せん。だからクォートする必要もないです。(クォートしても問題はありませ ん。上の例は7(8はだめです!)個の^Vを入力しても動作します)。 格納: esc ^V^[ コマンドが解析された後、短い形式("esc")と長い形式("^V^["の2文字)とし て、短縮入力の一覧に加えられます。:ab コマンドを引数なしで実行したとき に、この形の短縮入力が表示されます。 あとで、ユーザが"esc"を入力し、短縮入力が展開されたとき、長い形式は実 際のキー入力と同様に^Vによるクォートが適用されます。つまり、^Vが^[を クォートし、 "挿入モードから抜ける"文字として解釈されることを防ぐので す。その代わりに、^[がテキストに挿入されます。 展開: ^[ [例は Steve Kirkendall によって提供されました] ============================================================================== 3. ローカルマップとローカル関数(Local mappings and functions) *script-local* いくつかのVimスクリプトを併用すると、あるスクリプトで使われているマップや関数 と同じ名前のものが別のスクリプトでも使用される恐れがあります。それを避けるに は、スクリプトローカルなマップや関数を使用します。 *<SID>* *<SNR>* *E81* マップやメニューに "<SID>" という特別な文字列を使用できます。これは'cpoptions' にフラグ '<' が含まれていると利用できません。マップコマンドを実行すると、 "<SID>" は、<SNR> という特別なキーコードとスクリプト固有の番号、そしてアンダー スコアに置換されます。例: :map <SID>Add これは"<SNR>23_Add"といったマップを定義します。 スクリプトで関数を作成するときに、関数名の前に"s:"を付けると、ローカル関数を作 成できます。しかし、その関数をマップで使用する場合、そのマップをスクリプト以外 の場所で実行すると、その関数がどのスクリプトで定義されたのか分かりません。これ を解決するには、マップ中で"s:"ではなく"<SID>"を使用します。この場合も"<SID>"は 上記の例と同じように置換されます。これでローカル関数の呼び出しを含むマップを定 義できます。 ローカル関数は、その関数を定義したスクリプトのコンテキストで実行されます。その ため、その関数内で新たに定義した関数やマップにも "s:" や "<SID>" を使用できま す。その場合、その関数自身と同じスクリプト番号が使用されます。"s:var" といった スクリプトローカル変数も同様です。 オートコマンドやユーザ定義コマンドもそれを定義したスクリプトのコンテキストで実 行されます。そのコマンドからローカル関数を呼び出したり、ローカルマップを使用す ることができます。 スクリプト以外の場所で "<SID>" を使うとエラーになります。 複雑な処理をするスクリプトで、スクリプト番号が必要な場合は、次の関数で番号を得 られます: function s:SID() return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$') endfun 関数やマップを一覧表示するときには "<SNR>" も表示されます。それらがどのように 定義されているのか調べるときに便利です。 コマンド|:scriptnames|を使って、それまでに実行されたスクリプトとそのスクリプト 番号を確認できます。 これらはすべて {Vi にはない機能です}。 {|+eval| が有効な場合のみ利用できます} ============================================================================== 4. ユーザ定義コマンド (User-defined command) *user-commands* ユーザ独自のExコマンドを定義することできます。ユーザ定義コマンドはビルトインコ マンドと同様に振る舞うことができます(範囲指定や、引数を取ることができます。引 数の入力では、ファイル名、バッファ名などを補完できます)。違いは、コマンドが実 行されると、通常の Ex コマンドに変換してから実行されるということです。 まずはユーザマニュアルの|40.2|を参照してください。 *E183* *E841* *user-cmd-ambiguous* すべてのユーザ定義コマンドは大文字で開始する必要があります。これはビルトインコ マンドと混同しないようにするためです。特例として次のようなビルトインコマンドも ありますが: :Next :X これらの名前もユーザー定義コマンドには使えません。":Print" コマンドも存在しま すがこれは非推奨 (deprecated) になっており、上書きすることができます。 ユーザコマンドの開始文字以外は、大文字であっても小文字であっても、数字であって もかまいません。数字を使う場合、数字を引数に取る他のコマンドが曖昧になるかもし れないので注意してください。例えば、"Cc2"コマンドは ":Cc2" という引数なしの ユーザーコマンドとしても、"2"という引数を取った ":Cc" コマンドとしても解釈でき ます。これらの問題を避けるため、コマンド名と引数の間にスペースを挿入することを 勧めます。 ユーザ定義コマンドを使うときに、コマンドの省略形を使うこともできます。しかしな がら、その省略形が唯一でなければエラーが起きます。加えて、ビルトインコマンドが 常に優先されます。 例: :command Rename ... :command Renumber ... :Rena " "Rename" を意味します :Renu " "Renumber" を意味します :Ren " エラー - 曖昧 :command Paste ... :P " ビルトインコマンドの:Print です スクリプトの中で使うときは、ユーザ定義コマンドの完全な名前を使うようにしましょ う。 :com[mand] *:com* *:command* すべてのユーザ定義コマンドを一覧表示します。表示中の行 頭の2文字は次の意味です ! -bang 属性を持つコマンド " -register 属性を持つコマンド b カレントバッファのローカルコマンド (属性に関する詳細は下記参照) :com[mand] {cmd} {cmd} で始まるユーザ定義コマンドを一覧表示します。 *:command-verbose* 'verbose' がゼロ以外のときにコマンド一覧を表示すると、どこで定義されたのかも表 示されます。例: :verbose command TOhtml Name Args Range Complete Definition TOhtml 0 % :call Convert2HTML(<line1>, <line2>) Last set from /usr/share/vim/vim-7.0/plugin/tohtml.vim 詳しくは |:verbose-cmd| を参照してください。 *E174* *E182* :com[mand][!] [{attr}...] {cmd} {rep} ユーザ定義コマンドを定義します。コマンド名は {cmd} で それを置き換えるテキストが {rep} です。{attr} はコマン ド属性(下記参照)です。既にコマンドが存在している場合は エラーになります。! を指定した場合は再定義されます。 :delc[ommand] {cmd} *:delc* *:delcommand* *E184* ユーザ定義コマンド {cmd} を削除します。 :comc[lear] *:comc* *:comclear* すべてのユーザ定義コマンドを削除します。 コマンド属性 ユーザ定義コマンドは、他のビルトインコマンドと同様に扱われます。引数や範囲も指 定できます。引数の入力時にはファイル名やバッファ名などを補完することができま す。どのように動作するかはコマンドを定義するときに指定したコマンド属性に依存し ます。 たくさんの属性がありますが、それらは、引数の扱い方、補完の種類、範囲指定の仕 方、特殊なケース、の4つの分野に分けることができます。以下、分野別に説明しま す。 引数の扱い方 *E175* *E176* *:command-nargs* 属性を指定しなかった場合、ユーザ定義コマンドは引数を取りません(引数が与えられ た場合はエラーになります)。-nargs属性を指定すると、ユーザ定義コマンドが引数指 定できるようになります。次の属性が指定できます: -nargs=0 引数を取らない (デフォルト) -nargs=1 1個の引数が必要 (空白で区切られない) -nargs=* いくつでも引数を取れる (0個以上) 空白で区切られる -nargs=? 0 もしくは 1 個の引数が取れる -nargs=+ 引数が必ず必要。数はいくつでもよい 引数は (エスケープされていない) スペースやタブ文字で区切られます。ただし、引数 を 1 つだけ取る場合は空白は引数の一部として解釈されます。 Note: 引数はVimスクリプトの式としてではなく、テキストとして解釈されることに注 意してください。具体的な例を上げると、"s:var"を引数として渡すと、そのコマンド を実行したスクリプトのローカル変数ではなく、そのコマンドを定義したスクリプトの ローカル変数が使用されます。例: script1.vim: :let s:error = "None" :command -nargs=1 Error echoerr <args> script2.vim: :source script1.vim :let s:error = "Wrong!" :Error s:error script2.vimを実行すると"None"が表示されます。期待した結果とは違うでしょう。 代わりに関数呼び出しを使ってください。 保管の種類 *:command-completion* *E179* *E180* *E181* *:command-complete* 属性を指定しない場合、ユーザ定義コマンドの入力時に引数は補完されません。下記の 属性を1つ以上指定することで、引数が補完されるようになります。 -complete=augroup オートコマンドのグループ -complete=buffer バッファ -complete=color カラースキーム -complete=command Ex コマンド(と、引数) -complete=compiler コンパイラー -complete=cscope |:cscope| サブオプション -complete=dir ディレクトリ -complete=environment 環境変数 -complete=event オートコマンドのイベント -complete=expression Vimの式 -complete=file ファイルとディレクトリ -complete=file_in_path |'path'| 内のファイルとディレクトリ -complete=filetype ファイルタイプ名 |'filetype'| -complete=function 関数 -complete=help ヘルプの主題 -complete=highlight 強調グループ -complete=locale ロケール名 (locale -a の出力) -complete=mapping マップ -complete=menu メニュー -complete=option オプション -complete=shellcmd シェルコマンド -complete=sign |:sign| サブオプション -complete=syntax シンタックスファイル名 |'syntax'| -complete=tag タグ -complete=tag_listfiles CTRL-D を押した時にタグ、ファイル名を表示 -complete=var ユーザ変数 -complete=custom,{func} {func}によるユーザ定義の補完 -complete=customlist,{func} {func}によるユーザ定義の補完 ユーザ定義の補完 *:command-completion-custom* *:command-completion-customlist* *E467* *E468* 補完方法に"custom,{func}"、"customlist,{func}"を指定すると独自の補完を使用でき ます。{func}には次のような関数を指定します。 :function {func}(ArgLead, CmdLine, CursorPos) すべての引数を使う必要はありません。関数の返り値として、補完候補のリストを返し てください。 "custom" を使った場合は、補完候補のリストを一つずつ改行で区切ってください。 "customlist" を使った場合は、補完候補のリストを |List| で返してください。リス ト中の文字列以外の変数は無視されます。 引数には次の意味があります: ArgLead すでに入力されている補完対象の文字列 CmdLine コマンドライン全体 CursorPos カーソル位置 (バイト単位のインデックス) これらの引数を使えば文脈を判断することができるでしょう。"custom" を使った場 合、補完候補のリストからArgLeadにそぐわない候補(ArgLeadで始まらない文字)を取り 除く必要はありません。Vimは補完関数を実行した後にふさわしくない候補を取り除き ます。おそらくその方がほとんどの場面で有用です。"customlist" を使った場合、Vim は補完候補のリストをフィルタしません。補完候補のリストを自分でフィルタしてくだ さい。 次の例はFingerコマンドでユーザ名を補完します :com -complete=custom,ListUsers -nargs=1 Finger !finger <args> :fun ListUsers(A,L,P) : return system("cut -d: -f1 /etc/passwd") :endfun 次の例では、'path' に指定されたディレクトリのファイル名を補完しています: :com -nargs=1 -bang -complete=customlist,EditFileComplete \ EditFile edit<bang> <args> :fun EditFileComplete(A,L,P) : return split(globpath(&path, a:A), "\n") :endfun この例はファイル名にスペースが含まれていると機能しません! 範囲指定 *E177* *E178* *:command-range* *:command-count* 属性を指定しない場合、ユーザ定義コマンドは行番号による範囲指定を受け付けませ ん。-range属性を指定して、コマンドが範囲指定を受け付けるようにできます。任意の カウント値を取るようにすることもできます。この場合、行番号の位置(|:split|コマ ンドのように。-range=N)で指定するか、"count" 引数(|:Next|コマンドのように。 -count=N)で指定します。カウント指定は |<count>| で取得できます。 次の属性が利用できます: -range 範囲指定が可能になります、無指定時は現在行 -range=% 範囲指定が可能になります、無指定時はファイル全体(1,$) -range=N カウント(無指定時はN)を行番号位置に指定できます (例 |:split|)。行番号に 0 を指定可能になる。 -count=N カウント(無指定時はN)を行番号位置か、初期化引数に指定でき ます (例 |:Next|)。-count(無指定時の値なし)とした場合 は-count=0と同じです。 Note: -range=Nと-count=Nは相互に排他的であるということに注意してください。どち らか一方のみを指定することができます。 特殊なケース *:command-bang* *:command-bar* *:command-register* *:command-buffer* 特殊なケースがいくつかあります: -bang コマンドは!修飾子を取ることができます(:qや:wのように) -bar コマンドは"|"を使用して別のコマンドを続けて実行することが できます。引数に"|"を含めることはできなくなります。"がコメ ントの開始になってしまうことにも注意してください。 -register コマンドの1つ目の引数にレジスタ名を指定することができます (:del、:put、:yankのように)。 -buffer コマンドはカレントバッファでのみ利用できます。 ユーザ定義コマンドの定義に-countや-registerが指定された場合に、その省略可能な 引数が与えられた場合、それは引数リストから削除され、それぞれの引数に対応する特 別な文字列が利用できるようになります。 置き換えテキスト ユーザ定義コマンドでは、<...>表記を使った特別な文字列を使用できます。その文字 列はコマンドラインに入力された実際の引数に置き換えられます。その他のテキストは 変更されません。そして特別な文字列を実際の引数で置換したものがExコマンドとして 実行されます。<> 表記が置き換えられないようにするには、最初の < の代わりに <lt> を使ってください。例えば、"<bang>" をリテラル文字として使うには "<lt>bang>" とします。 次のものを使用できます *<line1>* <line1> コマンド範囲の最初の行 *<line2>* <line2> コマンド範囲の最後の行 *<count>* <count> 与えられたカウント('-range'と'-count'属性で記述されている) *<bang>* <bang> ('-bang'属性を参照)コマンドが!修飾子付きで実行された場合に!に 置換されます。指定なしの場合は空文字列になります。 *<reg>* *<register>* <reg> ('-register'属性を参照)レジスタ名に置換されます。指定なしの場 合は空文字列になります。<register>も同義です。 *<args>* <args> 与えられた通りのコマンド引数(上記の通り、カウントやレジスタが 指定された場合は<args>に含まれません)。 <lt> 1つの'<'(小なり)文字。特別な文字列を文字どおりに使用したい場合 に必要となります。例えば<bang>を得るには<lt>bang>とします。 *<q-args>* 特別な文字列の始めの2文字が"q-"なら(例えば<q-args>)、引数は式で使えるように クォートされます("で囲まれる)。これは引数を1つの値として扱います。引数がない場 合は <q-args> は空文字列になります。 *<f-args>* ユーザ定義コマンドの引数を関数に渡すには、<f-args>("function args")が利用でき ます。これはコマンドの引数をスペースやタブ文字で区切り、それぞれの引数を別々に クォート("で囲む)し、カンマで区切ったリストにして<f-args>と置き換えます。下の Mycmdの例をご覧下さい。引数がない場合は <f-args> は取り除かれます。 <f-args> の引数にスペースを含めるには、バックスラッシュを前置します。<f-args> では二つのバックスラッシュ (\\) は一つのバックスラッシュに置換されます。スペー スとバックスラッシュ以外の文字に付いているバックスラッシュはそのまま使われま す。要約: コマンド <f-args> XX ab 'ab' XX a\b 'a\b' XX a\ b 'a b' XX a\ b 'a ', 'b' XX a\\b 'a\b' XX a\\ b 'a\', 'b' XX a\\\b 'a\\b' XX a\\\ b 'a\ b' XX a\\\\b 'a\\b' XX a\\\\ b 'a\\', 'b' 例 " 現在行から最後行までを削除します :com Ddel +,$d " 現在のバッファ名を変更します :com -nargs=1 -bang -complete=file Ren f <args>|w<bang> " 指定された範囲をあるファイルの内容に置き換えます " (1行に書きます) :com -range -nargs=1 -complete=file Replace <line1>-pu_|<line1>,<line2>d|r <args>|<line1>d " 指定された範囲の行数を数える :com! -range -nargs=0 Lines echo <line2> - <line1> + 1 "lines" " ユーザ関数を呼びます(<f-args>の例) :com -nargs=* Mycmd call Myfunc(<f-args>) 次のように実行された場合は: :Mycmd arg1 arg2 次のものを実行します: :call Myfunc("arg1","arg2") " より現実的な例 :function Allargs(command) : let i = 0 : while i < argc() : if filereadable(argv(i)) : execute "e " . argv(i) : execute a:command : endif : let i = i + 1 : endwhile :endfunction :command -nargs=+ -complete=command Allargs call Allargs(<q-args>) Allargsコマンドは、引数としてどのVimコマンドでも取ることができ、引数リスト |argument-list|のすべてのファイルに対して与えられたコマンドを実行します。使い 方の例 ("e"フラグをつけてエラーを無視しており、また "update" コマンドで変更さ れたバッファを書き込んでいるので注意してください): :Allargs %s/foo/bar/ge|update これは、次のものを起動します: :call Allargs("%s/foo/bar/ge|update") スクリプトでユーザ定義コマンドを定義するとき、そのスクリプトのローカル関数や ローカルマップを使用できます。ユーザ定義コマンドはユーザ定義コマンドを定義した スクリプトのコンテキストで実行されます。これはユーザ定義コマンドで|<SID>| を使 用するときに重要です。 vim:tw=78:ts=8:ft=help:norl: top - main help file |