Vimscript は、Vimテキストエディタをカスタマイズおよび拡張するための組み込みスクリプト言語です。
入門
let name = "John"
echo "Hello, " . name
スクリプトファイル(script.vim)に保存して (:source script.vim) で読み込むか、ノーマルモードから直接 :let や :echo を使って実行できます。
実践的なサンプルコード
function! SuperTab()
let l:part = strpart(getline('.'), col('.') - 2, 1)
if (l:part =~ '^\W\?$')
return "\<Tab>"
else
return "\<C-n>"
endif
endfunction
imap <Tab> <C-R>=SuperTab()<CR>
変数
定義
let var = "hello"
変数のスコープ接頭辞
let g:ack_options = '-s -H' " g: global
let s:ack_program = 'ack' " s: local (to script)
let l:foo = 'bar' " l: local (to function)
let a:arg = 'baz' " a: function argument
s: プレフィックスはスクリプトローカルな関数名にも使用できます。詳細は :help local-variables を参照してください。
その他のスコープ
let w:foo = 'bar' " w: window local
let b:state = 'on' " b: buffer local
let t:state = 'off' " t: tab page local
echo v:version " v: vim internal variable
let @/ = '' " @ register
echo $PATH " $ environment variable
Vimオプション
echo 'tabstop is ' . &tabstop
if &insertmode
echo &g:option
echo &l:option
式の中でオプション値を取得・変更するには、オプション名の先頭に & を付与します。
算術・文字列演算子
a + b " Numbers only!
'hello ' . name " String concatenation
let var -= 2
let var += 5
let var .= 'string'
文字列
文字列構文
let str = "String"
let str = "String with \n newline"
let literal = 'literal, no \ escaping'
let literal = 'that''s enough'
echo "result = " . res
文字列関数
strlen(str)
len(str)
strchars(str)
split("one two three") "=> ['one', 'two', 'three']
split("one.two.three", '.') "=> ['one', 'two', 'three']
join(['a', 'b'], ',') "=> 'a,b'
tolower('Hello')
toupper('Hello')
関数
関数定義
function! s:Initialize(cmd, args)
echo "Command: " . a:cmd
return 1
endfunction
関数の上書き定義
function! MyFunc()
echo "Function defined or replaced"
endfunction
function!(! 付き)を使用すると、同名の既存関数をエラーなしで上書き再定義できます。
名前空間とオートロード (Autoload)
function! myplugin#hello()
" autoload/myplugin.vim
endfunction
関数の呼び出し
call s:Initialize()
call s:Initialize("hello", 123)
戻り値の取得
let result = s:Initialize()
エラー発生時の中断 (abort)
function! MyFunction() abort
endfunction
可変長引数 (Variadic Arguments)
function! Infect(...)
echo a:0
echo a:1
echo a:2
for item in a:000
echon ' ' . item
endfor
endfunction
call Infect('jake', 'bella')
ループと制御構文
ループ (Loops)
for s in list
echo s
continue
break
endfor
while x < 5
let x += 1
endwhile
カスタムコマンド (Custom Commands)
コマンドの定義
command! Save :set fo=want tw=80 nowrap
ユーザー定義コマンドは大文字で始める必要があります。! を付けることで既存コマンドを上書きできます。
コマンドから関数を呼び出す
command! Save call <SID>Foo()
function! s:Foo()
endfunction
コマンド引数
command! -nargs=? Save call script#foo(<args>)
| 引数指定子 | 説明 |
|---|---|
-nargs=0 |
引数なし(デフォルト) |
-nargs=1 |
ちょうど1つの引数(スペースを含むことが可能) |
-nargs=? |
0個または1個の引数 |
-nargs=* |
空白で区切られた0個以上の引数 |
-nargs=+ |
空白で区切られた1個以上の引数 |
条件分岐 (Conditionals)
If / Elseif / Else
let char = getchar()
if char == "\<LeftMouse>"
elseif char == "\<RightMouse>"
else
endif
真偽判定 (Truthiness)
if 1 "=> True
if 0 "=> False
if "1" "=> True
if "456" "=> True
if "xfz" "=> False
Vimscriptには独立した真偽値型はありません。0 が偽であり、0以外の整数は真として評価されます。
比較演算子
if 3 > 2
if a && b
if (a && b) || (c && d)
if !c
文字列の大文字・小文字の区別
if name ==# 'John' " case-sensitive
if name ==? 'John' " case-insensitive
if name == 'John' " &ignorecase
同一性比較
if a is b
if a isnot b
a と b がメモリ上の同一オブジェクトインスタンスを参照しているかを判定します。
正規表現パターンマッチ
"hello" =~ 'xx*'
"hello" !~ 'xx*'
"hello" =~ '\v<\d+>'
\v を指定すると 'very magic' 構文が有効になり、多くの特殊文字をエスケープなしで利用できます。
1行での複数文記述
if empty(a:path) | return [] | endif
let status = a ? b : c
| を使うことで、複数の文を1行にまとめて記述できます。
データ構造
リスト (Lists)
let mylist = [1, "two", 3, "four"]
let first = mylist[0]
let last = mylist[-1]
let second = get(mylist, 1)
let fallback = get(mylist, 10, "NONE")
リスト操作
len(mylist)
empty(mylist)
let sortedlist = sort(copy(mylist))
let shortlist = mylist[2:-1]
let shortlist = mylist[2:]
let single = mylist[2:2]
let longlist = mylist + [5, 6]
let mylist += [7, 8]
call add(mylist, 9)
関数型リストメソッド
call map(files, "bufname(v:val)")
call filter(files, 'v:val != ""')
辞書 (Dictionaries)
let colors = {
\ "apple": "red",
\ "banana": "yellow"
}
echo colors["apple"]
echo get(colors, "apple")
辞書操作
call remove(colors, "apple")
if has_key(dict, 'foo')
if empty(dict)
let k = keys(dict)
let v = values(dict)
let n = len(dict)
echo max(dict)
echo min(dict)
call extend(s:fruits, { "cherry": "red" })
for key in keys(mydict)
echo key . ': ' . mydict[key]
endfor
スコープ接頭辞(s:, g:, l:, b:)自体も辞書オブジェクトとしてアクセス可能です:
let script_keys = keys(s:)
数値と算術演算
let int = 1000
let hex = 0xff
let oct = 0755
let fl = 100.1
let sci = 5.4e4
3 / 2 "=> 1
3 / 2.0 "=> 1.5
sqrt(100)
floor(3.5)
ceil(3.3)
abs(-3.4)
Vim固有の機能
コマンドの動的実行 (execute)
execute "vsplit"
execute "edit " . fnameescape(filename)
ノーマルモードのキー入力実行 (normal)
normal G
normal! G
execute "normal! gg/foo\<cr>dd"
ファイル名展開 (expand)
echo expand("%") " path/file.txt
echo expand("%:t") " file.txt
echo expand("%:p:h") " /home/user/path
echo expand("%:r") " path/file
echo expand("%:e") " txt
出力制御とメッセージ表示
silent g/pattern/p
echo 'Simple text'
echomsg 'Persistent text recorded in :messages'
echoerr 'Error message'
echohl WarningMsg | echomsg "=> Warning!" | echohl None
設定オプション
set number
set nonumber
set number!
set numberwidth=5
set guioptions+=e
内省と機能判定 (Introspection)
has("clipboard")
executable("python3")
globpath(&rtp, "syntax/c.vim")
exists("$ENV")
exists(":command")
exists("variable")
exists("+option")
キーマッピング (Key Mappings)
モード指定
[nvixso](nore)map
主なマッピングオプション
| フラグ | 意味 |
|---|---|
<buffer> |
現在のバッファのみに限定 |
<silent> |
コマンドラインへのエコー表示を抑制 |
<nowait> |
より長いマッピング候補を待たずに即時実行 |
シンタックスハイライトとConceal
ハイライトグループ
hi Comment term=bold gui=bold ctermfg=4 guifg=#80a0ff
hi def link markdownH1 htmlH1
ファイルタイプ検出 (Filetype Detection)
augroup filetypedetect
au! BufNewFile,BufRead *.json setf javascript
augroup END
au Filetype markdown setlocal spell
文字列隠蔽・置換表示 (Conceal)
set conceallevel=2
syn match newLine "<br>" conceal cchar=}
hi newLine guifg=green
多重読み込み防止 (Include Guards)
if exists('g:loaded_myplugin')
finish
endif
let g:loaded_myplugin = 1