Vimscriptの基本

vim

参考

非常にわかりやすかったので自分なりにかみ砕いて写経
Vim scriptでプラグインを作ろう~Vimはいいぞ!ゴリラと学ぶVim講座(8)

vimのコメントアウト

"コメント

exコマンドってなんだ

":から始まる文字列
:Command

.vim拡張子について

vimのexコマンドをまとめたファイル

#vimファイルを読み込む(実行する)
:source file

内容

"gorillaと出力する
echo 'gorilla'

使えるデータ型

データ型
整数、少数、16進数 1,1.5,0x1E
文字列 ‘a’,”a”
辞書 {‘name’:’tarou’}
リスト [1,2,3]

文字列

'str'と"str"の違い
""では\tなどの特殊文字が展開される(タブスペース)

文字列の結合

.で結合できる

"aaabbbが出力される
echo 'aaa' . 'bbb'

変数の宣言

変数の命名規則

変数にはアルファベット・数字・アンダースコアが使える
数字から始まる変数は使うことができない

"すべてエラーになる
1str
two-xxx
aaa+bbb

twoでエラーになるのは面白い

宣言

let name = 'tarou'
echo name

代入

let name = 'tarou'
let name = 'suzuki'
echo name

辞書/連想配列

let animal = {'name':'gorilla', 'age':27}
" {'name':'gorilla', 'age':27}
echo animal

"get(辞書名,key,default)
"gorilla
echo get(animal,name,'none')

"keyが存在しない場合はdefault値が返される

辞書に要素を追加する

二種類のやり方がある

let animal = {}
"{dict}.{key} = {value}
let animal.name = 'gorira'

"{dict}[{name]} = {value}
let animal['age'] = 27

辞書から要素を削除する

"{'age': 27 , 'name': 'gorilla'} 
echo animal

"call remove({dict},{key})
call remove(animal, 'age')
"{'name': 'gorilla'} 
echo animal

リスト

異なるデータ型を保持できる

let anko = ['cat',10,{'name':'gorilla'}]

" ['cat',10,{'name':'gorilla'}]
echo anko

要素を取り出す

"list名[id]
"cat
echo anko[0]

"get(list名,id,default値)
"{'name':'gorilla'}
echo get(anko,2,'none')

"keyが存在しない場合はdefault値が返される

listを一つの文字列として返す

let anko = ['hello', 'my' , 'name' ,'is', 'gorilla']

"hello my name is gorilla
echo join(anko,' ')

"hello-my-name-is-gorilla
echo join(anko,'-')

変数のスコープ

接頭辞 スコープ
g: グローバルスコープ
s: スクリプトスコープ・スクリプトファイル内のみ利用可能
l: 関数ローカルスコープ・関数内のみ利用可能
a: 関数の引数・関数内のみ利用可能
v: グローバルスコープ・vimがあらかじめ定義している変数
"グローバルスコープ。あらかじめvimrcなどで指定しておきPluginのon/offに使用したりできる
let g:file_path = '/home....'
"関数にもスコープをあてることができる
function s:hello(msg) abort
    "関数内スコープ
    echo a:msg
    return 'done'
endfunction
"呼び出しもs:...になる
let text = s:hello()

if文

"{expr}=1:True
"{expr}=0:False
if {expr}
    "do something
elseif {expr}
    "do something
else
    "do something
endif 

三項演算子

"aの評価がtrueならb,falseならc
a ? b : c

論理和・論理積

"どちらかがtrueならtrue
echo 1 || 1
"どちらもtrueならtrue
echo 1 && 1

比較演算子

"大文字小文字の区別を無視する
"デフォルトでは無効
set: ignorecase
意味 演算子 ignorecaseに左右されない演算子
等しい == ==#
等しくない != !=#
大きい > >#
大きいか等しい >= >=#
同一インスタンス is is#
異なるインスタンス isnot isnot#

ユーザーの設定によって挙動が変わらないように基本#をつける

バッファ

"スクリプトスコープなのでコマンドで打つ際は注意
let s:session_list_buffer = 'SESSIONS'
"指定した名前でバッファを開く?
execute 'new' s:session_list_buffer

"移行このバッファにおける設定を決めていく
set buftype=nofile

"nnoremap...    ノーマルモードにおいて
            再帰的に実行しないキーマップ
            キー入れ替えなども可能
"nmap...        ノーマルモードにおいて
            再帰的に実行するキーマップ
            設定したいキーに他の設定があった場合それを呼び出す
            下記のようにした際に無限ループが発生する
            :nmap j gj
            :nmap gj j


"<silent>...    キーマップで実行されるコマンドがコマンドラインに表示されない
"<buffer>...    現在のbufferにのみキーマップを適用する
"<Plug>...      キーを割り当てない・関数のように後から設定できる?
":<C-u><CR>...  コマンドラインでCtrl-u / Enterを押したとき
"bwipeout!...   bwコマンドbdがlsから消えるのに対して実際に削除されるコマンド
nnoremap <silent> <buffer>
            \ <Plug>(session-close)
            \ :<C-u>bwipeout!<CR>

"trim()...      文字列から文字を取り除く
nnoremap <silent> <buffer>
            \ <Plug>(session-open)
            \ :<C-u>call session#load_session(trim(getline('.')))<CR>

"決めた設定に対して代入のような動作?
nmap <buffer> q <Plug>(session-close)
nmap <buffer> <CR> <Plug>(session-open) 

ウィンドウ

"すでに表示されている指定されたバッファーを開く(vim8.0以降追加機能
win_gotoid(id)
"読み込まれているが表示されていないバッファーを開く
win_getid('buffer名')

テキスト

テキストを取得

"n行のテキストを出力
echo getline(n)
"nからm行までのテキストを出力
echo getline(n,m)
"現在のカーソルがある行のテキストを出力
echo getline('.')

テキストを挿入

"行番号n+1にtextが挿入される。
"call append('行番号','text')

テキストを上書き

"もともとその行にあった文字列は消える。
"n行にstrが挿入される
call setline(n,str)

"listを挿入することもできる
"n行目からname
"n+1行目にage...をそれぞれ挿入(上書き)する
call setline(n,['name','age','add'])

カーソル

現在のカーソル位置を取得

:echo line(".")
:echo col(".")
"タプルで取得
:echo getpos(".")

カーソルを移動させる

:call cursor( n , m )

:let c = getpos(".")
:call setpos( '.' , c )

関数

"基本の形
function! Echo(msg) abort
    echo a:msg
endfunction
function{!} 関数名(引数) {abort}
    処理    echo {a:} msg
    戻り値  return 'str'
endfuntion

{!}...      同名の関数がある場合上書きするオプション
{abort}...  関数内でエラーが起きた場合処理を終了するオプション
            vimのデフォルトでは処理が継続される
{a:}...     関数内スコープの引数a:引数名

呼び出し方

function! MyName() abort
    return 'SUZUKI'
endfunction

echo MyName()

EXコマンドの実行

"execute {expr}
"{expr}の実行結果をEXコマンドとして実行できる
"複数の引数がある場合スペースで結合される

"anko
execute 'echo "anko"'
"gorilla godzilla
execute 'echo' '"gorilla"' '"godzilla"'

外部コマンドの実行

"system(command)
"system(command,option)

"my name is gorilla
echo system('echo "my name is gorilla")

"どちらも可能
echo system('ls -la')
echo system('ls','-la')

Lambdaってなんだ

vim8.0で追加された機能

{引数 -> 式}で表現できる

"式を入れて計算できるようにするlambda
let F = { a,b -> a + b }
"3
echo F(1,2)

"javaでありがちなfilterとして機能するlambda
"PATHはdirectory
"取得したものがdirctoryじゃなければtrue
let F = { file -> !isdirectory(PATH . '/' . file ) }
"readdirは指定したディレクトリ内のファイルリストを得る
"引数として取得物(file名が送られている
let xxx = readdir("PATH",F)

現在実行中のファイルパスを取得する

"現在実行中スクリプトがあるディレクトリ
let s:dir = expand('<sfile>:p:h')
let s:py_path = s:dir . '/' . 'xxx.py'
"のxxx.pyを実行する
execute ':pyfile ' . s:py_path
"現在触っているファイルのカレントパス取得
:echo expand("%")
"現在触っているファイルのフルパスを取得
:echo expand("%:p")
"現在触っているファイルのカレントパスを拡張子抜きで取得
:echo expand("%:r")
"現在触っているファイル拡張子を取得
:echo expand("%:e")
"ファイルを指定して取得
:let = file_path
:echo fnamemodify(file_path , ":p" )