Skip to content

Instantly share code, notes, and snippets.

@pit-ray
Last active January 12, 2025 06:14
Show Gist options
  • Select an option

  • Save pit-ray/6a34f79b32134c1440403ab8bdbc8d01 to your computer and use it in GitHub Desktop.

Select an option

Save pit-ray/6a34f79b32134c1440403ab8bdbc8d01 to your computer and use it in GitHub Desktop.
vim9.txtの要約

vim9.txtの要約

Vim9 scriptを書くための必要最低限の情報をまとめました。

Vim9 Scriptを使うには

  • 以下の場所で使用可能
    • :defで定義された関数の中
    • vim9scriptで始まるスクリプトファイルの中
    • vim9cmdが先頭についたコマンド
  • Vim9 scriptのファイル内でfunctionを定義すれば従来の記法が使える

文法

基本仕様

  • 行継続文字\は不要
  • コメントは#で始める (#{はダメ)
  • 再読み込みすると関数や変数がクリアされる
  • エラーが出ると中断する
  • 変数と関数のデフォルトスコープは,スクリプトローカル

変数

  • 変数の宣言はvar,代入にコマンド不要
  • 変数はコードブロック内のみ生存する
  • =前後はスペース必須,リストのスライス:の周りにスペース必須
  • finalで変数の変更不可,値の変更可
    final mylist = [1, 2]
    mylist = [3, 4]  # Error!
    mylist[0] = 0    # OK!
  • constで変更不可
  • 初期値なしの場合
    型名 初期値
    bool false
    string,list,dict
    number,any ゼロ
  • アンパック代入でアンダースコアを使える
    var [a, _, c] = theList  # 2つ目無視
    var [a, b; _] = longList # 2つめ以降無視
    var [v1: number, v2] = GetValues()  # 型も指定できる

  • 辞書リテラルのキーは文字列
    var dict = {key: value}
    var dict = {'key with space': value}
    var dict = {"key\twith\ttabs": value}
    var dict = {'': value}  # 空のキー
    var dict = {00123: 'without'}   # {'00123': }と等価
    var dict = {[000456]: 'with'}   # {'456': }と等価 ([]はいったん式として評価する)
  • ignorecaseは文字列の比較に作用しないので=~=~#と等価
  • 現状はisis notは文字列に対して常にfalse
  • 文字列の結合には..を使う
    'hello ' .. 'world' == 'hello world'
    'hello ' .. 123 == 'hello 123'
    'hello ' .. v:true == 'hello true'
  • 文字列に対するインデックスは文字列が得られる
    echo 'bar'[1]  # a
    echo 'bar'[-1] # r
  • <number>のようにして型キャスト

条件式

  • 単に値を評価する場合と,??!を使用している場合とで扱いが異なる
    if 0       # false
    if 1       # true
    if 99      # エラー
    if "0"     # エラー
    if "99"    # エラー
    if !99     # false
    if !!99    # true
    if !99.9   # false
    if !"aaa"  # false
    if ![]     # true
    if !![]    # false
  • trueとv:true,falseとv:false,nullとv:nullは同じ
  • nullとnumber, float, boolの比較は常にfalse

関数

  • defで関数がコンパイル対象になる (タイミング: 最初に呼び出されるとき, defcompileコマンド)
  • 関数名は大文字で始めなければいけない
  • call, eval, function不要
  • 使用される前に定義されてなければならない (グローバル関数g:は別)
  • range, abort, dict, closureは無く,常にクロージャになれる
  • 引数の型戻り値の型を宣言しなくてはならない
    • any型は実行時に型チェック
  • 引数を参照する際はa:は不要 (a:a:000は無い)
  • 可変長引数は最後の引数に名前とリスト型
    def MyFunc(...itemlist: list<number>)
      for item in itemlist
         ...
  • デフォルト値を使いたい場合,v:noneを渡す
    def MyFunc(one = `one`, last = `last`)
       ...
    enddef
    MyFunc(v:none, `LAST`)  # 第一引数はデフォルト値になる
  • map(numberList, (_, v) => v * 2)のように_で引数を無視できる
  • ネストした関数は関数のブロックにローカル
    def Function()
      def NestedFunction()
        echo `inner`
      enddef
      var F = function(NestedFunction)  # 文字列は渡さない
    enddef

ラムダ式

  • =>を使う
    var Lambda = (arg) => expression
    var Lambda = (arg): type => expression
  • 任意の引数を受け入れる場合は..._を使う
    var Callback = (..._) => 'anything'
    echo Callback(1, 2, 3) # anythingが表示
  • {}で複数のステートメントOK (以下のように{の後ろと}の前で改行)
    var d = mapnew(dict, (k, v): string => {
        ({key: 42})  # ステートメントブロックと誤認されないためにカッコ
        return 'value'
      })

Forループ

  • ループ変数は先に宣言してはいけない
    for i in [1, 2, 3]
      echo i
    endfor

import/export

  • exportをつけて,importまたはimport autoloadでスクリプト間で関数を参照できる

    export側 (myscript.vim)

    def ScriptLocalFunction()
    def g:GlobalFunction()
    export def ImportableFunction()   # import,import autoloadで読み込む

    import側 (main.vim)

    import 'myscript.vim'
    import 'myscript.vim' as that
    
    myscript.ImportableFunction()
    that.ImportableFunction()  
  • import autoloadで遅延読み込みをする

    export側 autoload/for/search.vim

    export def Stuff(arg: string)
    

    import側 plugin/anyname.vim

    import autoload `for/search.vim`
    search.Stuff('aaa')
  • exportは定数,変数,def関数,クラスに可能

テクニック

  • hasで存在を確認したうえで利用する関数は,コンパイルエラーになる場合がある → executeを使うとよい

参考

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment