この記事では、Vimの優れたアドオンを作成したい人が知っておく必要のあるVimLのいくつかの機能について説明します。 この記事を理解するには、vimscriptの知識が必要です。少なくとも1つのアドオンを作成することをお勧めします。 独自のサプリメントを書きたくない人にとって、この記事はほとんどの場合役に立たないでしょう。
バインディング
再バインド
ありふれたよく知られていることから始めましょう:再バインド。 Vimには、
*map
および
*noremap
2つの主要なコマンドファミリがあります。 1つ目では右側を再定義できますが、2つ目ではできません。 さらに、ユーザーがどのバインディングを持っているのかわからないため、2番目のみを使用する必要があります。 古典的な例:
壊れますnoremap : ; noremap ; :
nmap <F4> :PluginToggle<CR>
しかしではない nnoremap <F4> :PluginToggle<CR>
。 留意すべきその他のコマンド: -
*map
/*noremap
、*abbrev
/*noreabbrev
、*menu
/*noremenu
-
normal
/normal!
-
call feedkeys(string)
/call feedkeys(string, 'n')
また、 「remap」設定の存在に注意することもできます。これにより、
*map
すべてのコマンドが、対応する
*noremap
と同じ方法で動作するようになります。 使用できません
nnoremap <Plug>PluginAction :DoAction<CR> if !hasmapto('<Plug>PluginAction') nmap <Leader>a <Plug>PluginAction endif
ユーザーがlhsをオーバーライドできるようにし、この設定を有効にしているユーザーをサポートするには、代わりにフォームへのバインディングのすべての定義をリストする必要があります execute 'nnoremap '.get(g:, 'plugin_action_key', '<Leader>a').' :DoAction<CR>'
Vimの古いバージョンと互換性があります if !exists('g:plugin_action_key') let g:plugin_action_key='<Leader>a' endif execute 'nnoremap '.g:plugin_action_key.' :DoAction<CR>'
特殊文字
- バインディングの左部分として<Esc>を使用すると、矢印とファンクションキーを使用できなくなります。 でも
nmap <Esc> <Esc>
- バインディング-式の右側にバイト0x80が存在すると、それが台無しになる可能性があります。 エラーは既知であり、 文書化されています 。
ファイル(<script>)バインディング
Vimには、バインディングの右側を、同じファイルで定義されているバインディングのみでオーバーライドする機能があります。 ユーザーがバインディングを使用してバインディングの左側をオーバーライドする場合に、限られた有用性(より正確には、その欠如)を残します
nnoremap <Plug>PluginAction :DoAction<CR> if !hasmapto('<Plug>PluginAction') nmap <Leader>a <Plug>PluginAction endif
または execute 'nnoremap '.get(g:, 'plugin_action_key', '<Leader>a').' :DoAction<CR>'
この方法を使用すべきでない別の考慮事項があります:コマンド用 nnoremap <script> lhs rhs
そして nnoremap lhs rhs
maparg('lhs', 'n', 0, 1)
を呼び出すと、同じ辞書が返されます。 つまり、別の開発者が、たとえば、同じ
lhs
で一時的に別のバインディングを作成してから古いバインディングを復元したい場合、ファイルバインディングは正しく復元されません。
設定
Vimには、簡単にあなたの人生を台無しにする多くの設定があります:互換性設定
最も破壊的な設定は'compatible'です。 原則として、それを処理するための最も正しい方法は、ダウンロードを拒否することです。おそらくメッセージが表示されます。
if &compatible finish endif
アドオンに対する2番目に破壊的な効果は「cpoptions」設定です:これを使用すると、コマンドの一部が次の行に転送されないようにしたり、バインディングを作成する コマンド の 動作を 変更し たり、正規表現の 動作を 変更したり できます。 通常、これは部分的に使用して処理されます let s:saved_cpo=&cpo set cpo&vim <...> let &cpo=s:saved_cpo unlet s:saved_cpo
ただし、正規表現の動作が変更されると、何もできなくなります。 関数に影響を与えないことは良いことです(ユーザー定義関数ではなく、 match *() 、 replace()などの組み込み関数を意味します)。
大文字と小文字を区別しない
もう1つの「楽しい」設定は'ignorecase'です。 ただし、互換性の設定とは異なり、単純なルールに従ってそれに対処するのは非常に簡単です。
- 文字列を比較するときは、常に接尾辞
#
(大文字と小文字を考慮)または?
(したがって、無視します)。 助けて - コマンド:タグで正規表現を使用する場合、および
/
および?
検索する場合、関数match() 、 matchend() 、 matchlist() 、 matchstr() 、およびsubstitution()で 検索コマンドが範囲の一部である場合を含め、\C
または\c
を明示的に指定する必要があります。
呼び出し:tag name
する必要がある場合は、:tag name
を:tag /\V\C\^name\$
に変換する必要があります。 - コマンド:s 、: smおよび:snoでは 、 フラグ
i
またはI
を指定する必要がありますI
- アクション
*
および#
何もできません。 代わりに使用できますlet @/='\V\C\<'.escape(expand('<cword>'), '\/').'\>' call histadd('/', @/) normal! n
- 1つの良いニュース:: 構文コマンドで何もする必要はありません。
魔法と繰り返し
- 「マジック」設定も正規表現に影響しますが、幸いなことに、ほとんどの場合無視されます。
/
および?
検索するときに、修飾子\M
、\m
、\v
または\V
いずれかを指定するだけ?
( 検索コマンドが範囲の一部である場合を含む)、および:sの代わりに: smまたは:snoも使用します。 - sに影響する別の設定は'gdefault'です。
g
フラグの動作をまったく逆に変更します。 それに対処する唯一の方法は、使用することですlet saved_gdefault=&gdefault set nogdefault " Do sm// commands here let &gdefault=saved_gdefault
ワイルドファイル
expand() 、 glob()またはglobpath()を使用する場合、オプションの引数の最初に1つを指定する必要があります。指定しない場合、 「wildignore」および「 suffixes」の設定が考慮され、出力から一部のファイルが除外される場合があります。 ただし、逆に有用な場合もあります。
その他の設定
- 「非表示」をオンにして生活することに慣れている場合は、デフォルトではインストールされないことに注意してください。 これは、アドオンが別のバッファに切り替える機能に影響する場合があります。 これを防ぐには、 「bufhidden」セットを使用して非表示にすることができます。
- 'autochdir'は、ユーザーが別のバッファーに移動したときに現在のディレクトリを変更します。 これは予想外であり、サプリメントを破壊する場合があります。
- 'cdpath'は、 :cdおよび:lcdコマンドの動作を変更します。ただし、ディレクトリが絶対的な方法で指定されている場合、または現在のディレクトリ(明示的な
./
)または現在のディレクトリ(../
)を基準に指定されている場合を除きます。 - 「revins」は入力の方向を変更します。 彼女のために、あなたは使用すべきではありません
execute 'normal! A'.text
let lines=split(text, "\n", 1) let lines[0]=getline('.').lines[0] call setline('.', remove(lines, 0)) if !empty(lines) call append('.', lines) endif
- 'selection' 、 'selectmode'および'virtualedit'もあなたの人生を台無しにする可能性があります。 標準の「設定を保存し、独自の値を設定し、実行し、元に戻す」よりも良いことを行うことはほとんど不可能です。
- 「シェル」を変更すると、他の
shell*
設定にも簡単に影響します。ドキュメントによると、一部の設定は、以前に明示的に変更された場合、 「シェル」の変更によって自動的に変更されません。 「あなたは成功しません。 - 'startofline'は、いくつかのアクションを実行するときにカーソルの位置を変更します。 重要な場合は、それらの後に明示的に設定する必要があります。
- 'wrapscan'は、検索コマンドの動作を変更します
/
および?
検索コマンドが範囲の一部である場合を含む。 search()を使用して、動作または標準の「保存、変更、完了、復元」を明示的に設定できます。
ローカル設定
また、以下に注意する必要があります。setlocalは、排他的にグローバルな設定を変更しようとしても例外をスローしません。 したがって、ヘルプを使用して設定を変更する前に、ドキュメントを調べてからグローバル設定の使用を拒否するか、 BufLeaveイベントで設定を復元し、 BufEnterイベントで値を設定する必要はありません 。
奇妙なファイル名
- * nixシステムのexpand() 、 glob()、またはglobpath()関数は、ピリオドで始まるファイル名を返しません。 そして、
glob('{*,.*}', 1, 1)
の形式の構造を使用する場合、loadで特別なディレクトリを受け取ります.
(現在のディレクトリ)および..
(現在のディレクトリが置かれているディレクトリ)。これらは多くの場合、単に無視する必要があります。 - globpath()を除き、 expand()およびglob()関数は2番目のオプションの引数をサポートするようになり、リストとして結果を返すように強制します。 POSIXではファイル名に新しい行を含めることができるため、* nixシステムで使用します。 これらの関数に追加の引数がないようにvimが十分に古く、そのようなファイルをサポートしたい場合(「野生で」見たことがないことに注意してください)、これを行うための方法の例を次に示します。
ページネーションとコメント
改行と垂直バーの意味、およびコメントを使用する機能は、コンテキストに非常に敏感です。- 組み込みコマンドが引数として式を使用する場合(例:echo )、ダブルストロークは文字列リテラルの開始と見なされ、改行と垂直バーが2つのコマンドを分離します(ただし、文字列リテラル内にある場合はそうではありません)。 チームでこの効果を達成することはできません。
- しかし、それがバインディング/略語-式である場合ではなく、パーサーの観点から実際に式を受け入れません。
- ファイルからの読み取り/を使用した関数の作成の場合
execute "function Abc()\n DoSomething\nendfunction"
- チームが垂直バーを引数の一部と見なす場合、改行文字も引数の一部になります(上記を除く)。
- 新しい行の先頭にあるバックスラッシュは、コマンドの一部の転送を示します。 ファイルを実行する前にコマンドを使用するかのように動作します
%s/\n\s*\\//
- ただし、ファイルが実行されている場合のみ。 転送を適用できる場所は他にありません。
- バインディング/略語/メニューを作成するコマンドは特別です。ダブルストロークはそれらの一部と見なされますが、文字列リテラルを開始せず、それでも垂直バーはコマンドを中断します。 チームでこの効果を達成することもできません。
-
endfunction
を別の行に配置することはできません。function
コマンドの後のパーサーは、function
属するすべての行を愚かに単にかみendfunction
、新しい行にあるendfunction
コマンドに遭遇するまでそれらを配列に格納します。
* Cmd
正しい(Buf |ファイル)(読み取り|書き込み)Cmdの作成は、一見思われるよりもはるかに複雑です。 実際のところ、vimはエンコーディングの自動検出や行の折り返し方法、または++ optの簡単なサポートを提供していません。 gzipで圧縮されたファイルを読み取る標準のアドオンを見ると、解凍されたコンテンツを一時ファイルに保存してから:readを使用してこのファイルを読み取ることがわかります。 これにより、設定'fileformats'および'fileencodings'を使用して行の折り返しとエンコードの方法を推測する必要がなくなりますが、KOI8-Rでエンコードされた圧縮ファイルを開きますfileencodings=utf8,cp1251
場合、 CP1251でエンコード。 アドオンでこれを実行したくない場合は、サービスにv:cmdargがあります。 この変数には常にユーザーデータ++設定が短い形式で含まれているため、++ encおよび++エンコーディングをサポートする必要はありません。 ここに例があります (読み取り、次の関数は書き込み)( 「fileformats」と「fileencodings」はここでは無視されます)が、場合によってはv:cmdargは単に:read with :executeに接続できます。 注:readは、シェルコマンド出力の読み取り時に++設定を無視します。
致命的でないエラー
コマンドのリストを読んだばかりの人には、コマンド:echoerrがエラーを表示する良い方法のように思えるかもしれません。 実際、これはそうではありません。表示されたエラーがプログラムの実行を中断しないようにする方法はありません。 このコマンドにプログラムの実行の中断を保証することができますが、代わりに try echoerr 'Error' endtry
あなたは簡単に書くでしょう echoerr 'Error' " some code here
ブロック内にコードを配置するかどうかに応じて、「コード」が実行されるかどうかに関連する奇妙な問題をデバッグする必要があるという事実に備えて:try
。
:try
ブロックの中に、決して実行されないコードのみを配置することはできないことを考慮して
:try
ユーザーは、次のように記述してコードを正確に配置する理由を複数持つことができます。
プログラムを中断せずにエラーを表示する必要がある場合は、
echohl ErrorMsg echomsg 'Error' echohl None
。 実行を中断する必要がある場合は、 throwがあります。 そして、 :throw
によって生成されたエラーメッセージにまったく満足していない場合のみ
try echoerr 'Error' endtry
。 シンプル:echoerr
いいえ、忘れる必要があります。
テキストファイルではない
ファイルを操作し、Vimでゼロを含むか新しい行で終了しない可能性のあるコマンドを出力すると、その正確さを維持する必要がある場合に多くの「楽しい」分を提供できます。 以下にいくつかの事実を示します。- VimLでは、シェルの外部からコマンドを実行する方法はまったくありません。 つまり、アドオンの作業は、
shell
開始する設定の正確性(またはユーザーが他のプログラミング言語をサポートするアセンブリを持っているかどうか)に常に依存します。 - system()は、その引数に新しい行が存在することを公式にサポートしていません。
- 純粋なVimLでコマンド出力を完全に変更せずに取得する唯一の方法は、コマンド出力を一時ファイルに書き込み、追加引数
'b'
指定してreadfile()を使用して読み取ることです。 「shellredir」設定を使用して、別のコンピューターでお金を稼ぐ可能性を高めることをお勧めします。 例 。 - NULLバイトをレジスタに書き込み、それをバッファに書き込んでバッファからコピーすることを保存する方法はありません。 実験を行うことができます:
enew call setline('.', "a\nb") yank put call setreg('"', getreg('"'), getregtype('"')) put
"\n"
を選んだ理由を確認してください)。 表示される内容は次のとおりです。a^@b a^@b a b
- :readはゼロを正しく読み取るように見えますが、それを使用するときに出力の最後に新しい行があるかどうかを知ることはできません。 そして、 'binary'をインストールする必要があります:readは自分自身をあまり賢く考えず、
\n
前に\n
\r
かみません。
不平等
Vimには、同等性をチェックするための6つの演算子と、不平等をチェックするための同じ数の演算子があります。-
==
、==?
、==#
(不等式:!!=*
)。 スカラー型は、必要に応じて(引数が異なる型である場合)、文字列を整数に、整数を浮動小数点数に、そのままで比較します。 文字列を浮動小数点数と比較する場合、文字列はまず整数にキャストされ、次に整数が浮動小数点数にキャストされます。 したがって、"42"==42.0
ですが、"42.1"!=42.1
および"42.1"==42.0
です。
非スカラー型。この演算子は再帰的にバイパスします。
関数リンク、リスト、および辞書を他のタイプと比較すると、エラーがスローされます(ブロック内の例外になります:try
)。 -
is
、is?
、is#
(不等式:isnot*
)です。 スカラー型を比較するとき、それはtype(a)==type(b) && a==b
(もちろん対応する接尾辞付きtype(a)==type(b) && a==b
と同じように動作します。 非スカラー型(関数参照もスカラー型)を比較する場合、Pythonのis
演算子と同様に、まず型をチェックし、次にID(つまり、引数がメモリ内の同じオブジェクトを参照しているかどうか)をチェックします。 エラーをスローしたり、引数を別の型にキャストしたりすることはありません。
したがって、推奨される使用規則:
- スカラー型の比較で
is#
使用しis?
、isnot#
またはisnot?
(違いは設定/ケースを無視セクションで説明されています)。 - 非スカラー型の比較では、アイデンティティではなく値の等価性を見つける必要がある場合、
==#
、==?
を使用する必要があり==?
、!=#
または!=?
。 - 演算子
==
、is
isnot
!=
およびisnot
を完全に忘れてはなりません。
私が順守し、セットの文字数を減らすことができるルールの別のセットがあります:
- 引数の1つが数値定数であり、コードのそれ以降のもう1つが数値としてのみ使用される場合、
==
を使用できます。 - 引数の1つが数値定数の場合、
is
を使用できます。 - 次に、前のリストのルールを使用します。
==#
数値を「特別な引数」として使用する必要があるかどうかを考えたくないので、文字列には適用しません(None
代わりに0
など)。
機能
Vimの興味深い機能の1つは、関数を参照する変数を使用することです。 既にそのような変数を取得できると聞いた場合 let Func=function("tr")
、変数名が大文字で始まることもおそらくご存知でしょう。さもないと、Vimがエラーを表示するからです。 ただし、あまり知られていないもう1つの事実があります。そのため、変数に関数参照を割り当てないでください。「Func」関数をどこかで定義した場合、Vimもエラーを表示します。 関数参照を使用する安全な方法は2つしかありません。それを引数として渡し、複雑な構造を使用する:辞書またはリスト: let d={} let d.func=function("tr")
同様に function Apply(func, list) return call(a:func, a:list, {}) endfunction echo Apply(function("tr"), ["abc", "a", "d"])
a:func()
関数を定義
a:func()
可能性があるにもかかわらず、完全に安全です。
特殊キャラクター!
ご覧のとおり、ファイル名の代わりに%記号を使用すると便利です。たとえば、次のようになります。 nnoremap <F4> :!python %<CR>
? これはVimのもう1つの便利な機能であり、うまく機能していれば便利です。 ファイル名にはスペース/ストローク/ドル(* sh)を使用し、ファイル名の代わりに、このバインディングのインタープリターは何でも取得できます。 Vimには%:t
[ail](名前の最後の部分のみを残す)のような現在のファイル名に対する多くの修飾子がありますが、修飾子
%:E
[ scape ]はshellescape()を介してファイル名を実行します。 したがって、呼び出しのコンテキストを忘れずに、すべてを自分でスクリーニングする必要があります: system()を使用する場合、 shellescape()は、1つ目の引数または2つ目の代わりにゼロで呼び出す必要があり、 :! 、 :読んでください! 、 :書く! およびその他の感嘆符-2つの引数と1つが2番目の引数です。 例:
nnoremap <F4> :execute '!python' shellescape(@%, 1)<CR> nnoremap <F5> :call system('javac '.shellescape(expand('%')))<CR>
正規表現機能
-
[^\na]
はおなじみの投稿ですか? VimL正規表現では、これは完全にあなたが考えているものではないことを意味します。このコレクションは、任意の文字と改行に一致します。 事実は、このレコードはそれほど落胆しない\_[^a]
と同じことを意味し\_[^a]
。つまり、コレクションに新しい行を追加a
ます。この場合、a
以外のすべての文字で構成されます。 -
substitute(str, reg, '\=expr', flags)
は、正規表現をexpr
の評価結果、または=expr
置き換えることができます。\=
, , ‐ , Vim . substitute() :s . -
^
« » , (\(\)
,\%(\)
) (\|
).$
, , . - , , ( , match*() , substitute() =~* ) «/ ». , . —
\n
, « », « ». : , . Vim « » — char*.
Vim , . : . , ,
-complete=dir
-complete=file
, :
command -complete=dir -nargs=1 -bar Echo :echo [<f-args>] command -nargs=1 EchoN :echo [<f-args>]
:Echo abc E172: :EchoN abc ['ab c'] :Echo * E77: :Echo $HOME ['/home/zyx'] :Echo `date` ['. . 28 17:17:47 MSK 2012']
。 , , , . , . , . .