vim-jp / vimdoc-ja / userfunc

userfunc - Vim日本語ドキュメント

メインヘルプファイルに戻る English | 日本語 | 編集
userfunc.txt  For Vim バージョン 9.1.  Last change: 2023 May 23


                  VIM REFERENCE MANUAL    by Bram Moolenaar


関数の定義と使用。

これはユーザーマニュアルの第 07.2 章で紹介されている。

1. 関数の定義                           define-function
2. 関数呼び出し                         :call
3. 関数内でのクリーンアップ             :defer
4. 自動的に読み込まれる関数             autoload-functions

==============================================================================

1. 関数の定義
                                                define-function
ユーザーは自分で新しい関数を定義することができる。その関数は組込み関数とまった
く同じように呼び出せる。関数は一連のExコマンドを実行する。ノーマルモードコマン
ドはコマンド:normalによって実行できる。

関数名は組込み関数との混同を避ける為、大文字で始まらなければならない。他のスク
リプトで同じ関数名を使用してしまうことを避けるためスクリプトローカルにする。グ
ローバル関数を使用するなら重複を避ける為に、露骨に短い名前は避けるべきである。
関数名を例えば "HTMLcolor()" のように、スクリプトの名前から始めるというのは良
い習慣である。

旧来のスクリプトでは波括弧変数というものもある(curly-braces-names を参照)。

また、オートロード autoload 機構を使うと、関数が呼ばれたときだけ定義すること
ができる。

                                                        local-function
旧来のスクリプトのローカルな関数の名前は "s:" で始めなければならない。スクリプ
トローカルな関数は、そのスクリプトの中の関数から、またはそのスクリプト内で定義
されたユーザー定義コマンド、自動コマンドからしか呼ぶことができない。そのスクリ
プト内で定義されたマッピングにより呼ぶこともできるが、スクリプトの外部でマッピ
ングが展開された場合は "s:" の代わりに <SID> をつけなければならない。
ローカル関数はスクリプトローカル関数だけである。バッファローカル関数やウィンド
ウローカル関数というものはない。

Vim9 script では、関数はデフォルトでスクリプトローカルであり、グローバルな関
数を定義するにはプリフィックス "g:" を付ける。

                                :fu :function E128 E129 E123 E454
:fu[nction]             全ての関数と、その引数を表示する。

:fu[nction] {name}      関数{name}の定義を表示する。
                        {name}は辞書Dictionaryの要素のFuncrefであってもよ
                        い:
                                :function dict.init
                        Note {name} は式ではないため、関数参照である変数は使用
                        できないことに注意。この汚いトリックを使用すると、変数
                        "Funcref" で参照される関数をリストできる:
                                let g:MyFuncref = Funcref
                                func g:MyFuncref
                                unlet g:MyFuncref

:fu[nction] /{pattern}  {pattern}にマッチする名前の関数を表示する。"File" で終
                        わる関数を全て表示する例:
                                :function /File$

                                                        :function-verbose
'verbose' が 0 でないとき、これらのコマンドで関数を表示すると、それがどこで定
義されたかも表示する。例:

    :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 と一致するまで続く。
                                                                E1267
                        関数名はアルファベットと数字と '_' からなり、通常の関
                        数はアルファベットの大文字、スクリプトローカル関数は
                        "s:" で始まらなければならない。Note: "b:" や "g:" は
                        使用できない (7.4.260 からは関数名にコロンが含まれる場
                        合は E884 エラーが発生する。例 "foo:bar()"。このパッチ
                        以前はエラーにはならない)。

                        {name}は辞書Dictionaryの要素のFuncrefであってもよ
                        い:
                                :function dict.init(arg)
                        "dict" は既に定義されている辞書でなければならない。そ
                        の要素 "init" がまだ存在しないならば追加される。存在す
                        る場合は、既存の関数を上書きするためには [!] をつけな
                        ければならない。この値は番号つきの関数を指すFuncref
                        である。この関数はFuncrefを通してのみ呼ぶことができ、
                        そこへの参照がなくなると削除される。
                                                                E127 E122
                        この名前で定義される関数が既に定義済みで [!] が使用さ
                        れなかった場合、エラーとなる。1つの例外がある: スクリ
                        プトを再読み込みすると、そのスクリプトで以前に定義され
                        ていた関数は、静かに置き換えられる。
                        [!] が使用されていれば、それまで存在していた関数は、速
                        やかに新しいものへ置換えられる。
                        NOTE: ! は十分に注意して使用すること。注意せずに使用し
                        た場合は既存の関数を期待せず置き換える可能性があり、デ
                        バッグが難しくなる。
                        NOTE: Vim9 scriptのスクリプトローカル関数は、削除また
                        は再定義はできない。

                        引数{arguments}についてはfunction-argumentを参照。

                                        :func-range a:firstline a:lastline
                        引数[range]を追加した場合、関数は「範囲」を管理するこ
                        とができる。「範囲」は "a:firstline" と "a:lastline"
                        によって渡される。[range]がなかった場合、
                        ":{range}call" が「範囲」を指定されて実行されると、1行
                        1行について、カーソルをその行の先頭に置いた状態で関数
                        を呼び出すことになる。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
                        関数の実行によって、最後に使用されたサーチパターン、及
                        びredoコマンドの "." の内容は変更されない。したがって、
                        関数内で:nohlsearch を行っても、関数から戻ると検索結
                        果のハイライトが元に戻ることになる。

                        :endf :endfunction E126 E193 W22 E1151
:endf[unction] [argument]
                        関数定義の終了。最も良いのは、[argument] 無しに行内に
                        これ自身のみを書くこと。

                        [argument] として可能なものは以下のとおり:
                                | コマンド      次に実行するコマンド
                                \n コマンド     次に実行するコマンド
                                " コメント      常に無視される
                                その他          無視される、'verbose' が非ゼロ
                                                のときは警告が表示される
                        後ろに続くコマンドのサポートは Vim 8.0.0654 で追加され
                        ており、それ以前ではいかなる引数も黙って無視される。

                        コマンド :execute の内部で関数の定義を可能にするに
                        は、:bar の代わりに改行を使用する:
                                :exe "func Foo()\necho 'foo'\nendfunc"

                                :delf :delfunction E131 E933 E1084
:delf[unction][!] {name}
                        関数{name}を削除する。
                        {name}は辞書Dictionaryの要素のFuncrefであってもよ
                        い:
                                :delfunc dict.init
                        この例は "dict" から要素 "init" を削除する。この関数へ
                        の参照がなくなると、関数は削除される。
                        ! が付いていると、関数が存在していなくてもエラーが発生
                        しない。
                                                        :retu :return E133
:retu[rn] [expr]        関数から戻る。"[expr]" が与えられた場合、それは評価さ
                        れ関数の結果として返される。"[expr]" が与えられない場
                        合、数値 0 が返される。関数が明示的な ":return" を伴わ
                        ずに終了した場合、数値 0 が返される。

                        :def 関数内で到達不可能なコードが :return の後に続く
                        場合、E1095 が与えられる。
                        旧来のスクリプトでは、到達不可能な行のチェックは行われ
                        ないため、コマンドが :return の後に続く場合でも警告
                        は出ない。また、次の行に有効なコマンドが含まれているか
                        どうかはチェックされない。行継続のバックスラッシュ
                        を忘れると気付かれない可能性がある:
                                return 'some text'
                                       .. ' some more text'
                        エラーなしで "some text" を喜んで返す。それは次のよう
                        になるはずだった:
                                return 'some text'
                                       \ .. ' some more text'

                        :try:finallyの間で ":return" が実行された場合、
                        ":finally" から対応する:endtryまでのコマンドがまず実
                        行される。":try" がネストしている場合、それらの全てに
                        対してこのプロセスが適用される。そして最も外側の
                        ":endtry" にて関数を抜ける。

                                                function-argument a:var
引数は、与えられた名前によって定義される。関数の中では "a:name" ("a:" を引数
に接頭)のようにして参照することができる。(:def 関数では、"a:" は使用されない)
                                        a:0 a:1 a:000 E740 ...
引数はコンマで区切ることで、最大20まで与えることができる。最後の引数を "..."
にすることで、可変長の引数を使用できる。関数の中では "a:1" や "a:2" のようにし
て可変長の引数にアクセスできる。"a:0" は可変長引数が幾つあるかを示している (0
であること、つまり引数がそれ以上ないこともある)。"a:000" は全引数を持つリスト
Listを示している。Note "a:1" は "a:000[0]" と同じである。
                                                        E742 E1090
a: のスコープとこれらの変数は固定されており、変更できない。
しかしリストListや辞書Dictionaryのような複合型が使用された場合は、その内容
を変更できる。よって関数にリストListを渡し、そこに要素を追加させることができ
る。関数にリストや辞書を変更させたくない場合は:lockvarを使うこと。

関数を引数無しで定義することも可能である。その時でも()は付けなければならない。

関数の中で別の関数を定義することも可能である。


                                                optional-function-argument
名前付き固定引数にデフォルト値を指定できる。これにより、関数呼び出しではオプ
ションになる。呼び出し時に固定引数が指定されていない場合は、デフォルトの式を使
用して初期化される。これは :function もしくは :def で宣言された関数に対し
てのみ機能し、ラムダ式 expr-lambda には機能しない。

例:
  function Something(key, value = 10)
     echo a:key .. ": " .. a:value
  endfunction
  call Something('empty')       "empty: 10"
  call Something('key', 20)     "key: 20"

引数のデフォルト式は、関数の定義時ではなく、関数呼び出し時に評価される。した
がって、関数が定義された時点では無効な式を使用することが可能である。式はまた、
呼び出し中に引数が指定されていない場合にのみ評価される。
                                                none-function_argument
デフォルトの式を使うために v:none を渡すことができる。Note これは、引数にデ
フォルトの式がある場合、v:none を通常の値として渡すことができないことを意味す
る。

例:
  function Something(a = 10, b = 20, c = 30)
  endfunction
  call Something(1, v:none, 3)      " b = 20

                                                                E989
デフォルト式を持つオプション引数は、必須引数の後になければならない。オプション
の名前付き引数すべての後に "..." を使用できる。

後の引数のデフォルトが前の引数を参照することは可能だが、その逆はできない。すべ
ての引数と同様に、それらには "a:" を前に付ける必要がある。

動作する例:
  :function Okay(mandatory, optional = a:mandatory)
  :endfunction
動作しない例:
  :function NoGood(first = a:second, second = 10)
  :endfunction

"..." が使われていない時は、関数呼び出しの時の引数の数は必須の名前付きの引数の
数と少なくとも同じでなければならない。"..." を使った時には引数の数は必須および
オプショナル引数の合計より大きくなるだろう。

                                                        local-variables
関数の中でローカル変数を使うこともできる。これらは関数から戻ると消滅する。
グローバル変数にアクセスするためには "g:" を付ける必要がある。

例:
  :function Table(title, ...)
  :  echohl Title
  :  echo a:title
  :  echohl None
  :  echo a:0 .. " items:"
  :  for s in a:000
  :    echon ' ' .. s
  :  endfor
  :endfunction

この関数は次のように呼ぶことができる:
  let lines = Table("Table", "line1", "line2")
  let lines = 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
:[range]cal[l] {name}([arguments])
                関数を呼び出す。関数の名前と引数は :function によって指定さ
                れるものである。引数は最大20まで使用可能。戻り値は破棄される。
                Vim9 script では、:call の使用はオプションで、次の2行は同
                じものになる:
                        call SomeFunc(arg)
                        SomeFunc(arg)
                「範囲」を受け付ける関数に「範囲」を指定しなかった場合、関数は
                カーソルの現在位置について一度だけ呼び出される。
                「範囲」を受け付けない関数に「範囲」を指定した場合、その範囲の
                一行ずつについて関数が呼び出される。その時カーソルは当該行の先
                頭に設定される。カーソルは「範囲」の最下行の左端になる(恐らく
                最後の関数呼出しの結果、動いた先である)。引数は各呼出しについ
                て繰り返し評価される。それは次の例で確かめることができる:
                                                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()には渡されない。

                                                                E117
関数が見つからない時は、"E117: Unknown function" というエラーになる。関数が
autoload パスまたは autoload インポートを使用していて、スクリプトが Vim9
script の場合は、関数がエクスポートされていないことが原因である可能性もある。

                                                                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

Note system() を呼ぶ前で "Outfile" 削除がスケジュールされているが、
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つの方法がある: 自動コマンドによ
る方法と、'runtimepath' 内の "autoload" ディレクトリによる方法である。

Vim9 script ではインポートされたスクリプトの自動読み込みメカニズムもある、
import-autoload を参照。

自動コマンドを使う方法

これはユーザーマニュアルのセクション 51.4 で説明されている。

自動コマンドは、長いVim scriptファイルのプラグインに対して有用である。自動コマ
ンドを定義し、すぐに :finish でそのスクリプトを抜ける。こうするとVimの起動が
速くなる。その後自動コマンドにより :finish コマンドをスキップする変数を定義
し、そのファイルが再び読み込まれる。

定義すべき関数名にマッチするパターンを指定して自動コマンドイベント
FuncUndefinedを使う。例:

        :au FuncUndefined BufNet* source ~/vim/bufnetfuncs.vim

ファイル "~/vim/bufnetfuncs.vim" は "BufNet" で始まる関数を定義しなければなら
ない。FuncUndefinedも参照。


オートロードスクリプトの使い方
                                                        autoload E746
これはユーザーマニュアルのセクション 52.2 で説明されている。

"autoload" ディレクトリのスクリプトを使う方法はより簡単である。しかし完全に正
しいファイル名を使う必要がある。オートロードされる関数は次のような名前を持つ:

        :call filename#funcname()

これらの関数は常にグローバルで、Vim9 script なら "g:" が必要:
        :call g:filename#funcname()

このような関数が呼ばれ、それがまだ定義されていなかった場合、Vimは 'runtimepath'
内の "autoload" ディレクトリから "filename.vim" というスクリプトファイルを探
す。例えば "~/.vim/autoload/filename.vim" のように。そしてこのファイルは次のよ
うな関数を定義していなければならない:

        function filename#funcname()
           echo "Done!"
        endfunction

ファイルが存在しない場合、'runtimepath' にまだ追加されていないパッケージの関数
も .vimrc から呼び出せるようにするため、Vim は 'packpath' ("start" の下) も検
索する (packages を参照)。

このファイル名と関数の # の前の部分は完全に一致しなければならない。そして定義
された関数は呼ばれた関数と完全に同じ名前でなければならない。
Vim9 script ではプリフィックス "g:" を使わなくてはならない:
        function g:filename#funcname()

もしくはコンパイル済み関数:
        def g:filename#funcname()

サブディレクトリを使うこともできる。関数名の中の # はパスのセパレータのように
解釈される。つまり、次の関数を呼ぶと:

        :call foo#bar#func()

Vimは 'runtimepath' からファイル "autoload/foo/bar.vim" を探す。

これはまだ定義されていない変数を参照するときにも使える:

        :let l = foo#bar#lvar

しかしこのオートロードスクリプトがすでに読み込まれている場合、未知の変数があっ
てもこのスクリプトは再読み込みされない。

この変数に値を代入するときは、何も特別なことはない。この方法は、オートロードス
クリプトが読み込まれる前に設定を渡すために使うことができる:

        :let foo#bar#toggle = 1
        :call foo#bar#func()

Note オートロードスクリプト内で定義されるはずの関数を間違って呼んだ時にスクリ
プト内で関数が定義されなかった場合、その存在しない関数のエラーメッセージが表示
される。オートロードスクリプトを修正しても自動で再読み込みされることはない。
Vim を再スタートするか手動でスクリプトを読み込ませること。

また、2つのスクリプト間で、互いに自分が定義される前に相手を呼ぶような関数があ
ると、これは動作しない。
トップレベルでオートロード機能を使うのは避けること。

Vim9 scriptでは、"#" 文字を関数名内に含んで定義すると、エラー E1263 が発生
する。"#" を含まない名前を利用し :export を使用しなくてはならない。

Hint: たくさんのファイルからなるスクリプトを配布する場合には、vimballユーティ
リティを使うとそれらをまとめることができる。ユーザーマニュアルの
distribute-scriptも参照。


 vim:tw=78:ts=8:noet:ft=help:norl: