Userfunc

Nvim の :help ページは、生成されており、ソースから tree-sitter-vimdoc パーサーを使って生成されています。


関数の定義と使用。
これについては、ユーザーマニュアルの41.7節で紹介されています。
1. 関数の定義
新しい関数を定義できます。これらは組み込み関数のように呼び出すことができます。関数は一連の Ex コマンドを実行します。ノーマルモードコマンドは、:normal コマンドで実行できます。
関数名は、組み込み関数との混同を避けるために、大文字で始める必要があります。異なるスクリプトで同じ名前を使用しないようにするには、スクリプトローカルにします。グローバル関数を使用する場合は、明白で短い名前を避けてください。良い習慣は、関数名をスクリプトの名前で始めることです。例:"HTMLcolor()"。
中括弧を使用することもできます。 curly-braces-names を参照してください。
オートロード機能は、関数が呼び出されたときにのみ定義するのに便利です。
local-function
スクリプトローカルな関数は、"s:" で始める必要があります。ローカルスクリプト関数は、スクリプト内、およびスクリプト内で定義された関数、ユーザーコマンド、自動コマンドからのみ呼び出すことができます。スクリプトで定義されたマッピングから関数を呼び出すことも可能ですが、マッピングがスクリプト外で展開される場合は、"s:" の代わりに <SID> を使用する必要があります。スクリプトローカルな関数のみが存在し、バッファローカルまたはウィンドウローカルな関数はありません。
:fu :function E128 E129 E123 :fu[nction] すべての関数とその引数をリストします。
:fu[nction][!] {name} 関数 {name} を、"!" が指定されていない限り行番号付きでリストします。{name}Dictionary Funcref エントリである可能性があります。
:function dict.init
{name} は式ではないため、関数参照である変数を使用することはできません。変数 "Funcref" で参照される関数をリストするには、この汚いトリックを使用できます。
let g:MyFuncref = Funcref
func g:MyFuncref
unlet g:MyFuncref
:fu[nction] /{pattern} {pattern} に一致する名前を持つ関数をリストします。例: "File" で終わるすべての関数をリストします。
:function /File$
:function-verbose
'verbose' がゼロ以外の場合、関数をリストすると、最後に定義された場所も表示されます。例:
:verbose function SetFileTypeSH
    function SetFileTypeSH(name)
        Last set from /usr/share/vim/vim-7.0/filetype.vim
詳細については、:verbose-cmd を参照してください。
E124 E125 E853 E884 :fu[nction][!] {name}([arguments]) [range] [abort] [dict] [closure] {name} という名前で新しい関数を定義します。関数の本体は、一致する :endfunction まで次の行に続きます。
名前は、英数字と '_' で構成され、大文字または "s:" (上記参照) で始める必要があります。"b:" または "g:" を使用することは許可されていません。(パッチ 7.4.260 以降、関数名にコロンが含まれている場合、たとえば "foo:bar()" に対して E884 が表示されます。そのパッチより前は、エラーは表示されませんでした)。
{name}Dictionary Funcref エントリである可能性があります。
:function dict.init(arg)
"dict" は既存の辞書である必要があります。エントリ "init" がまだ存在しない場合は追加されます。それ以外の場合は、既存の関数を上書きするには [!] が必要です。結果は、番号付き関数への Funcref です。関数は、Funcref でのみ使用でき、参照がなくなると削除されます。E127 E122 この名前の関数が既に存在し、[!] が使用されていない場合、エラーメッセージが表示されます。例外が 1 つあります。スクリプトを再度ソースする場合、そのスクリプトで以前に定義された関数は、サイレントに置き換えられます。[!] を使用すると、既存の関数はサイレントに置き換えられます。それが現在実行中の場合を除き、それはエラーです。注意: ! を賢明に使用してください。注意せずに使用すると、既存の関数が予期せずに置き換えられる可能性があり、デバッグが困難になります。
{arguments} については、function-argument を参照してください。
:func-range a:firstline a:lastline [range] 引数が追加されると、関数は範囲自体を処理することが期待されます。範囲は "a:firstline" と "a:lastline" として渡されます。[range] が除外された場合、":{range}call" は、範囲内の各行に対して、各行の先頭にカーソルを置いて関数を呼び出します。function-range-example を参照してください。カーソルは、すべての Ex コマンドの場合と同様に、範囲の最初の行に移動します。:func-abort
[abort] 引数が追加されると、エラーが検出されるとすぐに関数は中止されます。:func-dict
[dict] 引数が追加された場合、関数は Dictionary のエントリを介して呼び出す必要があります。ローカル変数 "self" は、辞書に設定されます。Dictionary-function を参照してください。:func-closure E932 [closure] 引数が追加された場合、関数は外側のスコープの変数と引数にアクセスできます。これは通常、クロージャーと呼ばれます。この例では、Bar() は Foo() のスコープから "x" を使用します。Foo() が返された後でも参照されたままになります。
:function! Foo()
:  let x = 0
:  function! Bar() closure
:    let x += 1
:    return x
:  endfunction
:  return funcref('Bar')
:endfunction
:let F = Foo()
:echo F()
1
:echo F()
2
:echo F()
3
function-search-undo
最後に使用された検索パターンとやり直しコマンド "." は、関数によって変更されません。これは、:nohlsearch の効果が関数が戻ると元に戻ることも意味します。
:endf :endfunction E126 E193 W22 :endf[unction] [argument] 関数定義の終わり。単独の行に [argument] なしで配置するのが最適です。
[argument] は次のいずれかです。 | command 次に実行するコマンド \n command 次に実行するコマンド " コメントは常に無視されます 他のものはすべて無視され、'verbose' がゼロ以外の場合に警告が表示されます。次のコマンドのサポートは Vim 8.0.0654 で追加されました。それ以前は、引数はすべてサイレントに無視されていました。
:execute コマンド内で関数を定義できるようにするには、:bar の代わりに改行を使用します。
:exe "func Foo()\necho 'foo'\nendfunc"
:delf :delfunction E131 E933 :delf[unction][!] {name} 関数 {name} を削除します。{name}Funcref である Dictionary エントリである可能性もあります。
:delfunc dict.init
これにより、"dict" から "init" エントリが削除されます。関数への参照がなくなると、関数は削除されます。! が付いていると、関数が存在しない場合でもエラーは発生しません。:retu :return E133 :retu[rn] [expr] 関数から戻ります。[expr] が指定されている場合、評価され、関数の結果として返されます。[expr] が指定されていない場合は、数値 0 が返されます。関数が明示的な ":return" なしで終了すると、数値 0 が返されます。到達不能な行のチェックはないため、":return" の後にコマンドが続く場合でも警告はありません。また、次の行に有効なコマンドが含まれているかどうかについてもチェックはありません。行継続のバックスラッシュを忘れると、気づかない可能性があります。
return 'some text'
       .. ' some more text'
エラーなしで "some text" を喜んで返します。本来は
return 'some text'
       \ .. ' some more text'
":return" が :try の後、一致する :finally (存在する場合) の前で使用されている場合、一致する :endtry までの ":finally" に続くコマンドが最初に実行されます。このプロセスは、関数内のすべてのネストされた ":try" に適用されます。関数は最も外側の ":endtry" で戻ります。
function-argument a:var 引数は、その名前を指定することで定義できます。関数では、これは "a:name" ("a:" は引数) として使用できます。a:0 a:1 a:000 E740 ... カンマで区切られた最大 20 個の引数を指定できます。名前付き引数の後には、引数 "..." を指定できます。これは、オプションでさらに引数を続けることができることを意味します。関数では、追加の引数を "a:1"、"a:2" などとして使用できます。"a:0" は追加の引数の数 (0 の可能性があります) に設定されます。"a:000" は、これらの引数を含む List に設定されます。"a:1" は "a:000[0]" と同じであることに注意してください。E742
a: スコープとその中の変数は変更できず、固定されています。ただし、ListDictionary などの複合型を使用する場合は、その内容を変更できます。したがって、List を関数に渡し、関数に項目を追加させることができます。関数が List または Dictionary を変更できないようにする場合は、:lockvar を使用してください。
引数なしで関数を定義することも可能です。その場合でも、() を指定する必要があります。
関数本体内に関数を定義することも許可されています。
optional-function-argument
位置指定された名前付き引数にデフォルト値を指定できます。これにより、関数呼び出しではオプションになります。位置指定された引数が呼び出しで指定されていない場合、デフォルトの式を使用して初期化されます。これは、:function で宣言された関数でのみ機能し、ラムダ式 expr-lambda では機能しません。
function Something(key, value = 10)
   echo a:key .. ": " .. a:value
endfunction
call Something('empty')        "empty: 10"
call Something('key', 20)        "key: 20"
引数のデフォルト式は、関数が定義されたときではなく、関数が呼び出されたときに評価されます。したがって、関数が定義されたときに無効な式を使用することが可能です。また、式は、呼び出し中に引数が指定されていない場合にのみ評価されます。
E989
デフォルト式を持つオプションの引数は、必須の引数の後に記述する必要があります。オプションの名前付き引数のすべて後に "..." を使用できます。
後の引数のデフォルトが前の引数を参照することは可能ですが、その逆は不可能です。すべての引数と同様に、"a:" をプレフィックスとして付ける必要があります。
機能する例
:function Okay(mandatory, optional = a:mandatory)
:endfunction
機能しない例
:function NoGood(first = a:second, second = 10)
:endfunction
"..." を使用しない場合、関数呼び出しの引数の数は、必須の名前付き引数の数以上である必要があります。"..." を使用する場合、引数の数は、必須とオプションの引数の合計より大きくてもかまいません。
local-variables
関数内では、ローカル変数を使用できます。これらは、関数が戻ると消滅します。グローバル変数には "g:" を使用してアクセスする必要があります。関数内では、ローカル変数には何も前置せずにアクセスします。ただし、必要に応じて "l:" を前置することもできます。これは、"version" などの予約名で必要になります。
:function Table(title, ...)
:  echohl Title
:  echo a:title
:  echohl None
:  echo a:0 .. " items:"
:  for s in a:000
:    echon ' ' .. s
:  endfor
:endfunction
この関数は、次のように呼び出すことができます。
call Table("Table", "line1", "line2")
call Table("Empty Table")
複数の値を返すには、Listを返します。
:function Compute(n1, n2)
:  if a:n2 == 0
:    return ["fail", 0]
:  endif
:  return ["ok", a:n1 / a:n2]
:endfunction
この関数は、次のように呼び出すことができます。
:let [success, div] = Compute(102, 6)
:if success == "ok"
:  echo div
:endif
2. 関数の呼び出し
:cal :call E107 E117 :[range]cal[l] {name}([arguments]) 関数を呼び出します。関数の名前と引数は:functionで指定されたとおりです。最大20個の引数が使用できます。戻り値は破棄されます。範囲が指定されていない場合、および範囲を受け入れる関数については、関数は一度だけ呼び出されます。範囲が指定されている場合、関数を実行する前にカーソルは最初の行の先頭に移動します。範囲が指定され、関数自体がそれを処理しない場合、関数は範囲内の各行に対して実行され、カーソルはその行の最初の列に置かれます。カーソルは最後の行に残ります(最後の関数呼び出しによって移動した可能性があります)。引数は各行ごとに再評価されます。したがって、これは機能します:function-range-example
:function Mynumber(arg)
:  echo line(".") .. " " .. a:arg
:endfunction
:1,5call Mynumber(getline("."))
"a:firstline"と"a:lastline"は、いずれにせよ定義され、範囲の開始時または終了時に異なる処理を行うために使用できます。
範囲自体を処理する関数の例
:function Cont() range
:  execute (a:firstline + 1) .. "," .. a:lastline .. 's/^/\t\\ '
:endfunction
:4,8call Cont()
この関数は、範囲内のすべての行(最初の行を除く)の先頭に継続文字 "\" を挿入します。
関数が複合値を返す場合、さらに参照解除できますが、その場合は範囲は使用されません。例
:4,8call GetDict().method()
ここでGetDict()は範囲を取得しますが、method()は取得しません。
E132
ユーザー関数の再帰は、'maxfuncdepth'オプションによって制限されています。
:evalを使用することも可能です。範囲はサポートしていませんが、メソッドチェーンを許可します。例えば、
eval GetList()->Filter()->append('$')
関数は、式を評価する一部として、またはメソッドとして使用されるときに呼び出すこともできます。
let x = GetList()
let y = GetList()->Filter()
3. 関数内のクリーンアップ
:defer
:defer {func}({args}) 現在の関数が終了したときに{func}を呼び出します。{args}はここで評価されます。
関数内のコマンドは、多くの場合、グローバルな影響を与えるため、関数が終了したときに元に戻す必要があります。これをあらゆる状況で処理するのは面倒な場合があります。特に、予期しないエラーが発生した場合。これは、try/finallyブロックで実行できますが、複数ある場合は複雑になります。
はるかに簡単な解決策は、deferを使用することです。エラーが発生した場合でも、関数が戻るときに関数呼び出しをスケジュールします。例
func Filter(text) abort
  call writefile(a:text, 'Tempfile')
  call system('filter < Tempfile > Outfile')
  call Handle('Outfile')
  call delete('Tempfile')
  call delete('Outfile')
endfunc
ここで、何かによって関数が中断された場合、'Tempfile'と'Outfile'は削除されません。:deferを使用してそれを回避できます。
func Filter(text) abort
  call writefile(a:text, 'Tempfile')
  defer delete('Tempfile')
  defer delete('Outfile')
  call system('filter < Tempfile > Outfile')
  call Handle('Outfile')
endfunc
"Outfile"の削除は、system()が失敗した場合でも作成される可能性があるため、system()の呼び出し前にスケジュールされていることに注意してください。
遅延関数は逆順に呼び出され、最後に追加されたものが最初に実行されます。役に立たない例
func Useless() abort
  for s in range(3)
    defer execute('echomsg "number ' .. s .. '"')
  endfor
endfunc
これで、:messagesは「number 2 number 1 number 0」と表示されます。
遅延関数の戻り値は破棄されます。関数に続けて、"->func"や".member"などのものを付けることはできません。現在:defer GetArg()->TheFunc()`は機能しませんが、今後のバージョンで機能する可能性があります。
エラーは報告されますが、遅延関数の実行を中断したり、遅延関数外の実行を変更したりすることはありません。
範囲は受け付けられません。関数は追加引数を持つ部分的なものにできますが、辞書にはできません。E1300
4. 関数の自動読み込み
autoload-functions
多くの関数または大きな関数を使用する場合、それらが使用されたときにのみ自動的に定義することが可能です。2つの方法があります。autocommandを使用する方法と、'runtimepath'の「autoload」ディレクトリを使用する方法です。
autocommandの使用
これはユーザーマニュアルのセクション41.14で紹介されています。
autocommandは、長いVimスクリプトファイルであるプラグインがある場合に役立ちます。autocommandを定義し、:finishですぐにスクリプトを終了できます。これにより、Vimの起動が速くなります。autocommandは、同じファイルを再度読み込み、:finishコマンドをスキップするように変数を設定する必要があります。
定義される関数に一致するパターンで、FuncUndefined autocommandイベントを使用します。例
:au FuncUndefined BufNet* source ~/vim/bufnetfuncs.vim
ファイル「~/vim/bufnetfuncs.vim」は、「BufNet」で始まる関数を定義する必要があります。また、FuncUndefinedも参照してください。
autoloadスクリプトの使用
autoload E746 これはユーザーマニュアルのセクション41.15で紹介されています。
「autoload」ディレクトリ内のスクリプトを使用する方が簡単ですが、正確なファイル名を使用する必要があります。自動読み込み可能な関数の名前は次のようになります。
:call filename#funcname()
そのような関数が呼び出され、まだ定義されていない場合、Vimは'runtimepath'内の「autoload」ディレクトリで「filename.vim」という名前のスクリプトファイルを検索します。たとえば、「~/.config/nvim/autoload/filename.vim」などです。そのファイルは、次のように関数を定義する必要があります。
function filename#funcname()
   echo "Done!"
endfunction
ファイルが存在しない場合、Vimは'packpath'(「start」の下)も検索して、パッケージがまだ'runtimepath'に追加されていないときに、vimrcからパッケージの関数を呼び出すことを許可します(packagesを参照)。
ファイル名と関数名の#の前に使用される名前は完全に一致する必要があり、定義された関数は呼び出される名前とまったく同じ名前を持っている必要があります。
サブディレクトリを使用することも可能です。関数名内のすべての#はパス区切り文字のように機能します。したがって、関数を呼び出すとき
:call foo#bar#func()
Vimは'runtimepath'内のファイル「autoload/foo/bar.vim」を探します。
これは、まだ設定されていない変数を読み取るときにも機能します。
:let l = foo#bar#lvar
ただし、autoloadスクリプトがすでに読み込まれている場合、不明な変数に対して再度読み込まれることはありません。
そのような変数に値を代入しても、特別なことは何も起こりません。これは、autoloadスクリプトが読み込まれる前に設定を渡すために使用できます。
:let foo#bar#toggle = 1
:call foo#bar#func()
間違いを犯し、autoloadスクリプトで定義されるはずの関数を呼び出したが、スクリプトが実際にその関数を定義していない場合、見つからない関数のエラーメッセージが表示されることに注意してください。autoloadスクリプトを修正しても、自動的に再度読み込まれることはありません。Vimを再起動するか、手動でスクリプトをsourceしてください。
また、2つのスクリプトファイルがあり、一方のスクリプトがもう一方のスクリプト内の関数を呼び出し、その逆もまた同様である場合、使用される関数が定義される前は機能しないことに注意してください。トップレベルでautoload機能を使用することは避けてください。
ヒント:スクリプトを配布する場合は、distribute-scriptを読んでください。
メイン
コマンドインデックス
クイックリファレンス