📖
VimのBigQuery簡易プラグインを作ってる(1)
作りたいもの・機能
- (Must)vim上で編集しているStandard SQLの必要な処理バイト数がわかる
- (Must)vim上で編集しているStandard SQLがエラーが返るかどうかわかる
- (Must)エラー文を手元で確認できるようにする
- (Want)Standard SQLの補完機能(関数やDBのカラム名)
この記事で書く内容
- (Must)vim上で編集しているStandard SQLの必要な処理バイト数がわかる
- (Must)vim上で編集しているStandard SQLがエラーが返るかどうかわかる
現在のプラグイン全貌(bqrunner.vim)
├── README.md
├── test.bq
├── doc
├── autoload # こっちに主に処理を書く
│ └── bqrunner.vim
└── plugin # こっちはプラグインのコマンド定義
└── bqrunner.vim
現段階ではプラグインにするほどのものではないが,今後Standard SQLの補完機能などを実装するとなるともうちょっとコードが大きくなりそう.
DryRunの実行と結果の格納
autoload/bqrunner.vim
fun! bqrunner#dry_run(file) abort
let l:command = 'cat ' . a:file . ' | bq query --dry_run --use_legacy_sql=false --'
let l:result = system(l:command)
let w:bqrunner_is_query_success = s:is_query_success(l:result)
if w:bqrunner_is_query_success
let l:bytes = s:get_bytes_from_result(l:result)
let w:bqrunner_dry_run_bytes = s:convert_bytes_unit(l:bytes)
else
let w:bqrunner_error_msg = l:result
endif
endf
fun! s:is_query_success(result) abort
return match(a:result, "successfully") != -1 ? 1 : 0
endf
fun! s:get_bytes_from_result(result) abort
return matchstr(a:result, '[0-9]\+')
endf
fun! s:convert_bytes_unit(bytes) abort
if type(a:bytes) == 1
let l:num_bytes = str2float(a:bytes)
else
let l:num_bytes = a:bytes
endif
let l:thousand = 0
while l:num_bytes > 1000.0
let l:num_bytes = l:num_bytes / 1000.0
let l:thousand += 1
endw
let l:units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
return printf('%.2f %s', l:num_bytes, l:units[l:thousand])
endf
やっていることはすごく単純で,bqコマンドを使って編集しているファイルの内容でDry Runを実行&結果を現在のウィンドウ範囲の変数に格納している.
変数の定義はplugin/bqrunner.vim
で行っている.
plugin/bqrunner.vim
if exists('g:bqrunner_loaded')
finish
endif
let g:bqrunner_loaded = 1
let w:bqrunner_is_query_success = -1
let w:bqrunner_dry_run_bytes = ''
let w:bqrunner_error_msg = ''
command! DryRun call bqrunner#dry_run(@%)
augroup bqrunner_dryrun
autocmd!
autocmd BufRead,BufWritePost *.bq DryRun
augroup END
ここまでで「クエリが成功しているか」と「必要になる処理バイト数」(あとエラー文)を変数に格納できたので,あとは任意の場所に表示するだけ.
今回はvim-airlineというPowerlineの右端に表示してみる.
ステータスと処理バイト数の表示(vim-airline拡張)
とりあえず先に現段階の完成図.
クエリが成功した場合
クエリが失敗した(存在しないカラムの指定)の場合
今回はvim-airlineの拡張として特定ディレクトリ配下にファイルを作った.(これはvim-airlineのexampleとして形式がおいてあったのでそれにしたがって作った)
vim-airline/autoload/airline/extensions/bqrunner.vim
" MIT License. Copyright (c) 2013-2021 Bailey Ling et al.
" vim: et ts=2 sts=2 sw=2
scriptencoding utf-8
if !get(g:, 'bqrunner_loaded', 0)
finish
endif
let s:spc = g:airline_symbols.space
" First we define an init function that will be invoked from extensions.vim
function! airline#extensions#bqrunner#init(ext)
" Here we define a new part for the plugin. This allows users to place this
" extension in arbitrary locations.
call airline#parts#define_raw('dryrun', '%{airline#extensions#bqrunner#get_dryrun_status()}')
" Next up we add a funcref so that we can run some code prior to the
" statusline getting modifed.
call a:ext.add_statusline_func('airline#extensions#bqrunner#apply')
" You can also add a funcref for inactive statuslines.
" call a:ext.add_inactive_statusline_func('airline#extensions#example#unapply')
endfunction
" This function will be invoked just prior to the statusline getting modified.
function! airline#extensions#bqrunner#apply(...)
" First we check for the filetype.
" Let's say we want to append to section_c, first we check if there's
" already a window-local override, and if not, create it off of the global
" section_c.
let w:airline_section_x = get(w:, 'airline_section_x', g:airline_section_x)
" Then we just append this extenion to it, optionally using separators.
let w:airline_section_x = '%{airline#extensions#bqrunner#get_dryrun_status()}' . s:spc.g:airline_right_alt_sep.s:spc . w:airline_section_x
endfunction
" Finally, this function will be invoked from the statusline.
function! airline#extensions#bqrunner#get_dryrun_status()
let l:is_query_success = get(w:, 'bqrunner_is_query_success', -1)
if l:is_query_success == 1
return "\<Char-0xf058> " . get(w:, 'bqrunner_dry_run_bytes', '')
elseif l:is_query_success == 0
return "\<Char-0xf071> "
else
return ""
endif
endfunction
(g|w):airline_section_x
というのがPowerline右側のファイルタイプ表示の部分で,この拡張によってそこの左に「✅ 〇〇 KB」のような感じで表示される.
次やること
- (Must)エラー文を手元で確認できるようにする
たぶんQuickfixあたりに表示して,トグルで表示切り替えできるようにするのが便利そうかな.
Discussion