diff --git a/doc/eval.jax b/doc/eval.jax index 88a434676..c4cf7f606 100644 --- a/doc/eval.jax +++ b/doc/eval.jax @@ -1,4 +1,4 @@ -*eval.txt* For Vim バージョン 9.2. Last change: 2026 Sep 14 +*eval.txt* For Vim バージョン 9.2. Last change: 2026 Sep 30 VIM リファレンスマニュアル by Bram Moolenaar @@ -176,11 +176,28 @@ Note: " " と "0" も空文字列ではないので、TRUE と見なされる。 *E362* *E891* *E892* *E893* *E894* *E907* *E911* *E914* *E1521* -浮動小数点数が予期されているところでは数値も使用可能だが、それ以外は使用できな -い。 +浮動小数点数と比較する場合や、組み込み関数が浮動小数点数を期待する場合には、代 +わりに数値を使用できる。`v:null` 以外を指定するとエラーになる。例: +>vim + let f = 8.0 + let Fr = function("abs") + echo f == 8 |" 1 + echo f == v:null |" 0 + echo f == v:false |" E362: Using a boolean value as a Float + echo sort([f, Fr], "f") |" E891: Using a funcref as a Float + echo f == "8" |" E892: Using a String as a Float + echo sort([f, []], "f") |" E893: Using a List as a Float + echo sort([f, {}], "f") |" E894: Using a Dictionary as a Float + echo f == v:none |" E907: Using a special value as a Float + echo f == (8, 0) |" E1521: Can only compare Tuple with Tuple +< + Note: `job` を使用すると E911 が発生し、`channel` を使用すると E914 が + 発生する。Vim9 script では、`==` 比較に相当するすべての演算で |E1072| + が発生する。 *no-type-checking* -変数の型を変更しようとしてもエラーは発生しない。 +旧来の Vim script では、変数の型を変更することが許可されている。一方、Vim9 +scriptでは、変数の型を変更しようとすると、型不一致エラー |E1012| が発生する。 1.2 関数への参照 ~ @@ -515,7 +532,7 @@ Blob の場合、一度に 1 バイトが使われる。 :let l = len(list) " リストの項目数 :let big = max(list) " リスト中の最大値 :let small = min(list) " リスト中の最小値 - :let xs = count(list, 'x') " 'x' の出現回数を数える + :let xs = count(list, 'x') " リスト内で 'x' の出現回数を数える :let i = index(list, 'x') " 最初に 'x' が現れる位置のインデックス :let lines = getline(1, 10) " バッファから10行を取得 :call append('$', lines) " バッファに行を追加する @@ -1357,7 +1374,8 @@ NOTE: |Vim9| script では 'ignorecase' を使用しない。 0 リストや Tuple や辞書の中ではこの変換は行われない。 -|Vim9| script では型が一致しなくてはならない。 +|Vim9| script では、数値と浮動小数点数を比較する場合を除き、型が一致している必 +要がある。|vim9-comparators| を参照。 文字列同士を比較した場合、strcmp()やstricmp()によって比較される。これは数値的 に(バイトの値で)比較されるのであって、必ずしも言語に基づく文字種の違いではな @@ -1509,19 +1527,18 @@ expr10 が数値か文字列ならば、この値は文字列 expr10 の第 expr に変換すれば良い。例えばカーソルの下のバイトを得るには: > :let c = getline(".")[col(".") - 1] -|Vim9| script では: *E1147* *E1148* -expr10 が文字列ならば、この値は文字列 expr10 の第 expr1 番目の文字 (合成文字が -ある場合はそれらを全て含む) に相当する文字列となる。バイトインデックスの場合は -|strpart()| を使う。 - -インデックスが0の場合最初のバイトもしくは文字になる。注意: テキストの列番号は0 -始まりである! - -文字列の長さよりも大きなインデックスが指定された場合、結果は空文字列になる。負 -数のインデックスを指定すると、結果は常に空文字列になる(後方互換性のため)。 -最後のバイトもしくは文字を得るには[-1:]を使うこと。 -Vim9 script では負数のインデックスはリストと同様に使用され、終端からのカウント -になる。 +|Vim9| script では: +- expr10 が文字列である場合、結果は expr10 の expr1 番目の単一文字 (合成文字を + 含む) からなる文字列となる。バイト単位のインデックスを使用する場合は、 + |strpart()| を使用すること。 +- インデックス 0 は (合成文字を含めた) 最初の文字を指す。注意: テキストの桁番 + 号は 1 から始まります! +- 文字列の長さがインデックスより小さい場合、結果は空の文字列になる。インデック + スが負の値である場合も、常に空の文字列が返される (理由: 後方互換性のため)。 + 最後の 1 文字 (合成文字を含む) を取得するには、[-1 :] を使用すること。 +- リストと同様に、負のインデックスが使用される (末尾から数える)。 +- `:def` 関数内で、インデックスを使って文字列への代入や変更を行おうとすると、 + |E1148| が発生する。 expr10 がリスト|List|ならばインデックスexpr1の項目が返る。取りうるインデックス の値については|list-index|を参照。インデックスが範囲を超えている場合はエラーと @@ -1690,10 +1707,10 @@ number 整数値 *expr-number* 57005 0b1101111010101101 0o157255 - 0xBE'EF |scriptversion-4| および |Vim9| - 48'879 |scriptversion-4| および |Vim9| - 0o137'357 |scriptversion-4| および |Vim9| - 0b1011'1110'1110'1111 |scriptversion-4| および |Vim9| + 0xBE'EF |scriptversion-4| および |Vim9| script + 48'879 |scriptversion-4| および |Vim9| script + 0o137'357 |scriptversion-4| および |Vim9| script + 0b1011'1110'1110'1111 |scriptversion-4| および |Vim9| script *floating-point-format* 浮動小数点数は次の 2 つの形式で書ける: @@ -1724,8 +1741,8 @@ number 整数値 *expr-number* 1.0E-6 3.1416e+88 - .123 |scriptversion-2| および |Vim9| - 123'456.0 |scriptversion-4| および |Vim9| + .123 |scriptversion-2| 以上および |Vim9| script + 123'456.0 |scriptversion-4| および |Vim9| script 次のものは無効である: 3. {M} が空 @@ -1949,57 +1966,71 @@ function(expr1, ...) 関数呼出 下の点がユーザー定義関数|user-functions|と異なる: 1. ラムダ式の本体は単一の式|expr1|であり、|Ex|コマンド列ではない。 -2. 引数にプリフィックス "a:" を使用しない。例: > - :let F = {arg1, arg2 -> arg1 - arg2} - :echo F(5, 2) -< 3 - -引数は任意である。例: > - :let F = {-> 'error function'} - :echo F('ignored') -< error function - +2. 引数にプリフィックス "a:" を使用しない。例: +>vim + let F = {arg1, arg2 -> arg1 - arg2} + echo F(5, 2) + " 3 +< +引数は任意である。例: +>vim + let F = {-> 'error function'} + echo F('ignored') + " error function +< |Vim9| lambda は、異なる文法を使用するだけでなく、型チェックを追加し、複数の行 に分割できる。|vim9-lambda| を参照。 *closure* ラムダ式は外側のスコープの変数と引数にアクセスできる。これはよくクロージャと呼 ばれる。以下の例ではラムダの中で "i" と "a:arg" が使われているが、これらは関数 -のスコープに既に存在する。これらは関数から抜けても有効であり続ける: > - :function Foo(arg) - : let i = 3 - : return {x -> x + i - a:arg} - :endfunction - :let Bar = Foo(4) - :echo Bar(6) -< 5 - +のスコープに既に存在する。これらは関数から抜けても有効であり続ける: +>vim + function Foo(arg) + let i = 3 + return {x -> x + i - a:arg} + endfunction + let Bar = Foo(4) + echo Bar(6) + " 5 +< Note: これが正しく機能するためには、ラムダが定義される前の外側のスコープ内にそ -れらの変数が存在していなければならない。|:func-closure|も参照。 +れらの変数が存在していなければならない。|:func-closure| も参照。Vim9 script の +クロージャについては、|vim9-closure| を参照。 ラムダとクロージャのサポートは以下のように判定できる: > if has('lambda') -|sort()|, |map()|, |filter()|とともにラムダ式を使う例: > - :echo map([1, 2, 3], {idx, val -> val + 1}) -< [2, 3, 4] > - :echo sort([3,7,2,1,4], {a, b -> a - b}) -< [1, 2, 3, 4, 7] - -ラムダ式は、チャネル、ジョブ、タイマーを使う際にも有用である: > - :let timer = timer_start(500, - \ {-> execute("echo 'Handler called'", "")}, - \ {'repeat': 3}) -< Handler called - Handler called - Handler called - +|sort()|、|map()|、|filter()| でラムダ式を使用する例。旧来の Vim script および +Vim9 script を使用: +>vim + echo sort([3, 2, 1, 4], {a, b -> a - b}) | " [1, 2, 3, 4] + vim9cmd echo [3, 2, 1, 4]->sort((a, b) => a - b) # [1, 2, 3, 4] + + echo map([1, 2, 3], {idx, val -> val + 1}) | " [2, 3, 4] + vim9cmd echo [1, 2, 3]->map((_, val) => val + 1) # [2, 3, 4] + + echo filter([1, 2, 3], {idx, val -> val > 1}) | " [2, 3] + vim9cmd echo [1, 2, 3]->filter((_, val) => val > 1) # [2, 3] + +ラムダ式は、チャネル、ジョブ、およびタイマーにも役立つ: +>vim + echowindow "Handler calling..." + let b:count = 0 + let timer = timer_start(1000, + \ {-> execute("let b:count += 1 | " .. + \ "echowindow 'Handler called ' .. b:count", "")}, + \ {'repeat': 3}) + " Handler called 1 + " Handler called 2 + " Handler called 3 +< Note クロージャが自身の依存するコンテキストから参照されている場合、メモリが使 われたままになり解放されない可能性がある: > function Function() - let x = 0 - let F = {-> x} - endfunction + let x = 0 + let F = {-> x} + endfunction このクロージャが関数スコープの "x" を使用しており、そして同じスコープの "F" が クロージャを参照している。この循環の結果解放されることのないメモリになる。 推奨: このようなことはしないこと。 @@ -2511,6 +2542,15 @@ v:hlsearch 検索による強調表示がオンになっているかどうかを < 関数から戻ったときに値が復元されることに注意すること。 |function-search-undo| + *v:imagebackend* +v:imagebackend 現在使用されている画像バックエンドを示す。'imageprotocol' を参 + 照。以下のいずれかの値をとる: + "none" 画像バックエンドは使用されていない + "gui" GUI 固有の画像バックエンドが使用されている + "kitty" kitty グラフィックスプロトコルが使用されて + いる + "sixel" sixel グラフィックスが使用されている + *v:insertmode* *insertmode-variable* v:insertmode 自動コマンドイベント|InsertEnter|と|InsertChange|用。 値は次のどれか: @@ -3023,25 +3063,32 @@ Vimはこれを見つけると、まず波括弧の中の式を評価し、そ いは、"adjective" に "quiet" が代入されていたとすれば "my_quiet_variable" とな る。 -これの応用の1つは、オプション値によって支配される変数の集合を作ることである。 -例えば次の文 > - echo my_{&background}_message - -は現在の 'background' の値に応じて "my_dark_message" か "my_light_message" の -中身を表示する。 - +その用途の 1 つとして、オプションの値によって制御される一連の変数を定義するこ +とが挙げられる。'background' オプションを使用した例を以下に示す: +>vim + let my_light_msg = 'Do you like your light background?' + let my_dark_msg = 'Do you like your dark background?' + echo my_{&background}_msg +< 波括弧を複数使うこともできる: > echo my_{adverb}_{adjective}_message -ネストさせることもできる: > +...ネストさせることもできる: > echo my_{ad{end_of_word}}_message ここで "end_of_word" は "verb" か "jective" のどちらかである。 -しかし、波括弧の中の式を評価した結果が有効な変数名とならなければならない。 -つまり、次は無効である: > - :let foo='a + b' - :echo c{foo}d -というのは、展開の結果が "ca + bd" となるからで、これは有効な名前ではない。 - +ただし、波括弧内の式は、有効な単一の変数名として評価される必要がある。したがっ +て、以下の例の展開は無効である。"ca + bd" は有効な単一の変数名ではないからであ +る。 +>vim + let foo='a + b' + echo c{foo}d + " E121: Undefined variable: ca + bd +< +波括弧も |register-variable| と一緒に使用することはできない。例えば: +>vim + let i = 'a' + let @{i} = false |" E15: invalid expression +< *curly-braces-function-names* 同様の方法で評価した名前により関数を定義したり呼び出したりできる。 例: > @@ -3380,8 +3427,8 @@ text... < は、以下と同義である: > :let x = 1 :lockvar! x -< NOTE: Vim9 script では `:const` とは異なった動きをする、 - |vim9-const| を参照。 +< NOTE: Vim9 script では `:const` とは異なった動きをする。 + |vim9-declaration| および |vim9-const| を参照。 これは、変数が変更されないことを確実にしたいときに便利 である。 この値がリストか辞書のリテラルならその項目もまた変更で @@ -3596,6 +3643,7 @@ text... |Vim9| script では、スクリプトの可読性を向上させるた め、`:continue` を短縮することはできない。 + *:break* *:brea* *E587* :brea[k] `:while` または `:for` ループの内側で使われたときは、 対応する `:endwhile` または `:endfor` の後のコマンドま @@ -4127,15 +4175,26 @@ Note "v:exception"、"v:stacktrace" および "v:throwpoint" は最も直近に Caught "oops" in function Foo, line 10 Nothing caught -実用的な例: 次のコマンド ":LineNumber" は、それが呼び出されたスクリプトや関数 -中の行番号を表示する: > - - :function! LineNumber() - : return substitute(v:throwpoint, '.*\D\(\d\+\).*', '\1', "") - :endfunction - :command! LineNumber try | throw "" | catch | echo LineNumber() | endtry -< - *try-nested* +Vim9 script の実用的な例: 以下の "LineNumber" コマンドは、そのコマンドが使用さ +れたスクリプトや関数内での行番号を表示する: +>vim9 + vim9script + def Thrower(): void + echo "In Thrower()" + throw 'This line is the throwpoint.' + enddef + const TLN: func = (): string => # TLN is 'Thrown Line Number' + substitute(v:throwpoint, '.*\D\(\d\+\).*', '\1', "") + command! LineNumber { + try + Thrower() + catch + echo $"Error on line {TLN()}" + endtry + } + # Echoes "In Thrower()" then "Error on line 2": + LineNumber +< *try-nested* try条件文によって捕捉されない例外はそれを囲むtry条件文によって捕捉することがで きる: > @@ -4910,24 +4969,29 @@ matchstr()やsubstitute()を使えば実現できる。以下の例は、"foobar はMichael Geddesによる)。 -辞書からscriptnamesを取り出す ~ +辞書から scriptnames を取り出す ~ *scriptnames-dictionary* `:scriptnames` コマンドを使用すると、読み込まれたすべてのスクリプトファイルの -リストを取得できる。 `getscriptinfo()` 関数もあるが、返される情報はまったく同 -じではない。リストを操作する必要がある場合は、このコードをベースとして使用でき -る: > - - # SNR によってインデックス付けされたスクリプト辞書を作成または更新し、それ - # を返す。 - def Scripts(scripts: dict = {}): dict - for info in getscriptinfo() - if scripts->has_key(info.sid) - continue - endif - scripts[info.sid] = info.name - endfor - return scripts - enddef +リストを取得できる。`getscriptinfo()` 関数もありますが、返される情報は完全に同 +じではない。リストを使用する必要がある場合は、この Vim9 script をベースとして +使用できる。これは、各スクリプトの `` とファイルパスを含む辞書を作成する +ものである: +>vim9 + vim9script + # SNR をキーとするスクリプトの辞書を構築し、それを返す。 + def Scripts(scripts: dict = {}): dict + for info in getscriptinfo() + if scripts->has_key(info.sid) + continue + endif + scripts[info.sid] = info.name + endfor + return scripts + enddef + # 使用例: 読み込まれた vimrc および gvimrc (存在する場合) の SNR を表 + # 示する + echo Scripts()->filter((_, v) => v =~ '\v[._]g?vimrc') +< ============================================================================== 10. Vim scriptバージョン *vimscript-version* *vimscript-versions* @@ -5291,7 +5355,8 @@ Vim のクリップボード機能にプロバイダを統合するには、す set clipmethod^=test < *clipboard-providers-wsl* -Windows WSL の場合は、このスクリプトを試すこと: >vim9 +Windows WSL の場合は、このスクリプトを試すこと: +>vim9 vim9script def Copy(_: string, _: string, lines: list) @@ -5308,5 +5373,5 @@ Windows WSL の場合は、このスクリプトを試すこと: >vim9 paste: { "*": Paste, "+": Paste } } set clipmethod^=wslclip - +< vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/en/eval.txt b/en/eval.txt index 651a6967f..b3a6798d1 100644 --- a/en/eval.txt +++ b/en/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 9.2. Last change: 2026 Sep 14 +*eval.txt* For Vim version 9.2. Last change: 2026 Sep 30 VIM REFERENCE MANUAL by Bram Moolenaar @@ -182,10 +182,29 @@ to Float, printf() for Float to String and float2nr() for Float to Number. *E362* *E891* *E892* *E893* *E894* *E907* *E911* *E914* *E1521* -When expecting a Float a Number can also be used, but nothing else. +When comparing with a Float, or when a builtin function expects a Float, a +Number can be used instead. Aside from `v:null`, anything else gives an +error. Examples: +>vim + let f = 8.0 + let Fr = function("abs") + echo f == 8 |" 1 + echo f == v:null |" 0 + echo f == v:false |" E362: Using a boolean value as a Float + echo sort([f, Fr], "f") |" E891: Using a funcref as a Float + echo f == "8" |" E892: Using a String as a Float + echo sort([f, []], "f") |" E893: Using a List as a Float + echo sort([f, {}], "f") |" E894: Using a Dictionary as a Float + echo f == v:none |" E907: Using a special value as a Float + echo f == (8, 0) |" E1521: Can only compare Tuple with Tuple +< + Note: Using a `job` gives E911 and using a `channel` gives E914. + In Vim9 script, all the `==` comparison equivalents give |E1072|. *no-type-checking* -You will not get an error if you try to change the type of a variable. +Changing the type of a variable is allowed in legacy Vim script. In Vim9 +script, type mismatch error |E1012| is given when attempting to change the +type of a variable. 1.2 Function references ~ @@ -524,12 +543,12 @@ String. Example: > List functions ~ *E714* Functions that are useful with a List: > - :let r = call(funcname, list) " call a function with an argument list + :let r = call(funcname, list) " call a function with argument list :if empty(list) " check if list is empty :let l = len(list) " number of items in list :let big = max(list) " maximum value in list :let small = min(list) " minimum value in list - :let xs = count(list, 'x') " count nr of times 'x' appears in list + :let xs = count(list, 'x') " count nr times 'x' appears in list :let i = index(list, 'x') " index of first 'x' in list :let lines = getline(1, 10) " get ten text lines from buffer :call append('$', lines) " append text lines in buffer @@ -1392,7 +1411,8 @@ because 'x' converted to a Number is zero. However: > 0 Inside a List or Tuple or Dictionary this conversion is not used. -In |Vim9| script the types must match. +In |Vim9| script, except when comparing a number with a float, the types must +match - see |vim9-comparators|. When comparing two Strings, this is done with strcmp() or stricmp(). This results in the mathematical difference (comparing byte values), not @@ -1551,18 +1571,19 @@ recognize multibyte encodings, see `byteidx()` for an alternative, or use byte under the cursor: > :let c = getline(".")[col(".") - 1] -In |Vim9| script: *E1147* *E1148* -If expr10 is a String this results in a String that contains the expr1'th -single character (including any composing characters) from expr10. To use -byte indexes use |strpart()|. - -Index zero gives the first byte or character. Careful: text column numbers -start with one! - -If the length of the String is less than the index, the result is an empty -String. A negative index always results in an empty string (reason: backward -compatibility). Use [-1:] to get the last byte or character. -In Vim9 script a negative index is used like with a list: count from the end. +In |Vim9| script: +- If expr10 is a String this results in a String that contains the expr1'th + single character (including any composing characters) from expr10. To use + byte indexes use |strpart()|. +- Index zero gives the first character (including any composing character). + Careful: text column numbers start with one! +- If the length of the String is less than the index, the result is an empty + String. A negative index always results in an empty string (reason: + backward compatibility). Use [-1 :] to get the last character (including + any composing character). +- A negative index is used like with a list: count from the end. +- Attempting to assign to or modify a string with an index within a `:def` + function gives |E1148|. If expr10 is a |List| then it results the item at index expr1. See |list-index| for possible index values. If the index is out of range this @@ -1735,10 +1756,10 @@ Examples: 57005 0b1101111010101101 0o157255 - 0xBE'EF |scriptversion-4| and |Vim9| - 48'879 |scriptversion-4| and |Vim9| - 0o137'357 |scriptversion-4| and |Vim9| - 0b1011'1110'1110'1111 |scriptversion-4| and |Vim9| + 0xBE'EF |scriptversion-4| and |Vim9| script + 48'879 |scriptversion-4| and |Vim9| script + 0o137'357 |scriptversion-4| and |Vim9| script + 0b1011'1110'1110'1111 |scriptversion-4| and |Vim9| script *floating-point-format* Floating point numbers can be written in two forms: @@ -1769,8 +1790,8 @@ Examples: 1.0E-6 3.1416e+88 - .123 |scriptversion-2| and |Vim9| - 123'456.0 |scriptversion-4| and |Vim9| + .123 |scriptversion-2| or higher and |Vim9| script + 123'456.0 |scriptversion-4| and |Vim9| script These are INVALID: 3. empty {M} @@ -2006,16 +2027,18 @@ the following ways: 1. The body of the lambda expression is an |expr1| and not a sequence of |Ex| commands. -2. The prefix "a:" should not be used for arguments. E.g.: > - :let F = {arg1, arg2 -> arg1 - arg2} - :echo F(5, 2) -< 3 - -The arguments are optional. Example: > - :let F = {-> 'error function'} - :echo F('ignored') -< error function - +2. The prefix "a:" should not be used for arguments. E.g.: +>vim + let F = {arg1, arg2 -> arg1 - arg2} + echo F(5, 2) + " 3 +< +The arguments are optional. Example: +>vim + let F = {-> 'error function'} + echo F('ignored') + " error function +< The |Vim9| lambda does not only use a different syntax, it also adds type checking and can be split over multiple lines, see |vim9-lambda|. @@ -2023,41 +2046,53 @@ checking and can be split over multiple lines, see |vim9-lambda|. Lambda expressions can access outer scope variables and arguments. This is often called a closure. Example where "i" and "a:arg" are used in a lambda while they already exist in the function scope. They remain valid even after -the function returns: > - :function Foo(arg) - : let i = 3 - : return {x -> x + i - a:arg} - :endfunction - :let Bar = Foo(4) - :echo Bar(6) -< 5 - +the function returns: +>vim + function Foo(arg) + let i = 3 + return {x -> x + i - a:arg} + endfunction + let Bar = Foo(4) + echo Bar(6) + " 5 +< Note that the variables must exist in the outer scope before the lambda is -defined for this to work. See also |:func-closure|. +defined for this to work. See also |:func-closure|. For Vim9 script +closures, see |vim9-closure|. Lambda and closure support can be checked with: > if has('lambda') -Examples for using a lambda expression with |sort()|, |map()| and |filter()|: > - :echo map([1, 2, 3], {idx, val -> val + 1}) -< [2, 3, 4] > - :echo sort([3,7,2,1,4], {a, b -> a - b}) -< [1, 2, 3, 4, 7] - -The lambda expression is also useful for Channel, Job and timer: > - :let timer = timer_start(500, - \ {-> execute("echo 'Handler called'", "")}, - \ {'repeat': 3}) -< Handler called - Handler called - Handler called - +Examples, using legacy Vim script and Vim9 script, for using a lambda +expression with |sort()|, |map()| and |filter()|: +>vim + echo sort([3, 2, 1, 4], {a, b -> a - b}) | " [1, 2, 3, 4] + vim9cmd echo [3, 2, 1, 4]->sort((a, b) => a - b) # [1, 2, 3, 4] + + echo map([1, 2, 3], {idx, val -> val + 1}) | " [2, 3, 4] + vim9cmd echo [1, 2, 3]->map((_, val) => val + 1) # [2, 3, 4] + + echo filter([1, 2, 3], {idx, val -> val > 1}) | " [2, 3] + vim9cmd echo [1, 2, 3]->filter((_, val) => val > 1) # [2, 3] + +The lambda expression is also useful for Channel, Job and timer: +>vim + echowindow "Handler calling..." + let b:count = 0 + let timer = timer_start(1000, + \ {-> execute("let b:count += 1 | " .. + \ "echowindow 'Handler called ' .. b:count", "")}, + \ {'repeat': 3}) + " Handler called 1 + " Handler called 2 + " Handler called 3 +< Note that it is possible to cause memory to be used and not freed if the closure is referenced by the context it depends on: > function Function() - let x = 0 - let F = {-> x} - endfunction + let x = 0 + let F = {-> x} + endfunction The closure uses "x" from the function scope, and "F" in that same scope refers to the closure. This cycle results in the memory not being freed. Recommendation: don't do this. @@ -2581,6 +2616,14 @@ v:hlsearch Variable that indicates whether search highlighting is on. < Note that the value is restored when returning from a function. |function-search-undo|. + *v:imagebackend* +v:imagebackend Indicates the current image backend being used, see + 'imageprotocol'. It may have one of the following values: + "none" no image backend being used + "gui" GUI specific image backend being used + "kitty" kitty graphics protocol being used + "sixel" sixel graphics being used + *v:insertmode* *insertmode-variable* v:insertmode Used for the |InsertEnter| and |InsertChange| autocommand events. Values: @@ -3106,36 +3149,42 @@ name. So in the above example, if the variable "adjective" was set to "adjective" was set to "quiet", then it would be to "my_quiet_variable". One application for this is to create a set of variables governed by an option -value. For example, the statement > - echo my_{&background}_message - -would output the contents of "my_dark_message" or "my_light_message" depending -on the current value of 'background'. - +value. An example with the 'background' option: +>vim + let my_light_msg = 'Do you like your light background?' + let my_dark_msg = 'Do you like your dark background?' + echo my_{&background}_msg +< You can use multiple brace pairs: > echo my_{adverb}_{adjective}_message -..or even nest them: > +...or even nest them: > echo my_{ad{end_of_word}}_message where "end_of_word" is either "verb" or "jective". However, the expression inside the braces must evaluate to a valid single -variable name, e.g. this is invalid: > - :let foo='a + b' - :echo c{foo}d -.. since the result of expansion is "ca + bd", which is not a variable name. - +variable name. So, the following example's expansion is invalid because +"ca + bd" is not a valid single variable name: > +>vim + let foo='a + b' + echo c{foo}d + " E121: Undefined variable: ca + bd +< +Curly braces also cannot be used with a |register-variable|. For example: +>vim + let i = 'a' + let @{i} = false |" E15: invalid expression +< *curly-braces-function-names* -You can call and define functions by an evaluated name in a similar way. -Example: > - :let func_end='whizz' - :call my_func_{func_end}(parameter) - -This would call the function "my_func_whizz(parameter)". - -This does NOT work: > - :let i = 3 - :let @{i} = '' " error - :echo @{i} " error +You can call and define functions by an evaluated name in a similar way as +with a variable. This only works in legacy Vim script, not in |Vim9| script. +Example: +>vim + let low_line = '_' + function F_curly() + return 'F{low_line}curly() is a working curly-braces-function-name' + endfunction + echo F{low_line}curly() +< ============================================================================== 7. Commands *expression-commands* @@ -3476,7 +3525,7 @@ text... :let x = 1 :lockvar! x < NOTE: in Vim9 script `:const` works differently, see - |vim9-const| + |vim9-declaration| and |vim9-const|. This is useful if you want to make sure the variable is not modified. If the value is a List or Dictionary literal then the items also cannot be changed: > @@ -3700,6 +3749,7 @@ text... In |Vim9| script `:continue` cannot be shortened, to improve script readability. + *:break* *:brea* *E587* :brea[k] When used inside a `:while` or `:for` loop, skips to the command after the matching `:endwhile` or @@ -4267,15 +4317,26 @@ This displays > Caught "oops" in function Foo, line 10 Nothing caught -A practical example: The following command ":LineNumber" displays the line -number in the script or function where it has been used: > - - :function! LineNumber() - : return substitute(v:throwpoint, '.*\D\(\d\+\).*', '\1', "") - :endfunction - :command! LineNumber try | throw "" | catch | echo LineNumber() | endtry -< - *try-nested* +A practical Vim9 script example: The following command, "LineNumber", +displays the line number in the script or function where it has been used: +>vim9 + vim9script + def Thrower(): void + echo "In Thrower()" + throw 'This line is the throwpoint.' + enddef + const TLN: func = (): string => # TLN is 'Thrown Line Number' + substitute(v:throwpoint, '.*\D\(\d\+\).*', '\1', "") + command! LineNumber { + try + Thrower() + catch + echo $"Error on line {TLN()}" + endtry + } + # Echoes "In Thrower()" then "Error on line 2": + LineNumber +< *try-nested* An exception that is not caught by a try conditional can be caught by a surrounding try conditional: > @@ -5067,23 +5128,28 @@ The input is in the variable "line", the results in the variables "file", "lnum" and "col". (idea from Michael Geddes) -getting the scriptnames in a Dictionary ~ +Getting the scriptnames in a Dictionary ~ *scriptnames-dictionary* The `:scriptnames` command can be used to get a list of all script files that have been sourced. There is also the `getscriptinfo()` function, but the -information returned is not exactly the same. In case you need to manipulate -the list, this code can be used as a base: > - - # Create or update scripts dictionary, indexed by SNR, and return it. - def Scripts(scripts: dict = {}): dict - for info in getscriptinfo() - if scripts->has_key(info.sid) - continue - endif - scripts[info.sid] = info.name - endfor - return scripts - enddef +information returned is not exactly the same. If you need to use the list, +this Vim9 script can be used as a base. It builds a dictionary with each +script's `` and filepath: +>vim9 + vim9script + # Build a scripts dictionary, indexed by SNR, and return it. + def Scripts(scripts: dict = {}): dict + for info in getscriptinfo() + if scripts->has_key(info.sid) + continue + endif + scripts[info.sid] = info.name + endfor + return scripts + enddef + # Example usage: echo the SNRs of the loaded vimrc and gvimrc (if any) + echo Scripts()->filter((_, v) => v =~ '\v[._]g?vimrc') +< ============================================================================== 10. Vim script versions *vimscript-version* *vimscript-versions* @@ -5451,7 +5517,8 @@ Below is a sample script that makes use of the clipboard provider feature: >vim set clipmethod^=test < *clipboard-providers-wsl* -For Windows WSL, try this script: >vim9 +For Windows WSL, try this script: +>vim9 vim9script def Copy(_: string, _: string, lines: list) @@ -5468,5 +5535,5 @@ For Windows WSL, try this script: >vim9 paste: { "*": Paste, "+": Paste } } set clipmethod^=wslclip - +< vim:tw=78:ts=8:noet:ft=help:norl: