Skip to content

Instantly share code, notes, and snippets.

@wordijp
Last active January 15, 2021 16:59
Show Gist options
  • Save wordijp/42645dd9b6d3bb517aed0385afbbb51d to your computer and use it in GitHub Desktop.
Save wordijp/42645dd9b6d3bb517aed0385afbbb51d to your computer and use it in GitHub Desktop.
VimScriptの変数をJSON化してインタラクティブに確認する
" 変数をJSON化(非可逆)して、インタラクティブに確認出来る jid コマンドを使って確認する
" use) call Jid({'hello': 'world', 'age': 17})
" ターミナル版
function! Jid(dic)
call s:_jid_core(a:dic, 0)
endfunction
" ポップアップ版
" NOTE: 1つまで、2つ以上同時に出すとエラーになる
function! Jid_popup(dic)
call s:_jid_core(a:dic, 1)
endfunction
" ---
function! s:_jid_core(dic, popup)
let l:temp = tempname()
execute ":redir! > " . l:temp
silent! echon s:_json_encode_irreversible(0, a:dic)
redir END
" NOTE: popup化する時はterm_startでhidden: 1
let l:id = term_start([&shell], #{ hidden: a:popup ? 1 : 0, term_finish: 'close' })
call term_sendkeys(l:id, "cat ".l:temp." | jid -M\<CR>")
if a:popup
call popup_create(l:id, #{ border: [], minwidth: winwidth(0)/2, minheight: &lines/2 })
endif
endfunction
" JSON化(非可逆)する
" NOTE: json_encodeはFuncrefやchannelなどが非対応なので、自前でJSON化
" 確認用にしか使わないのでそれっぽく見れればおk
" original) https://github.com/mattn/webapi-vim/blob/master/autoload/webapi/json.vim :webapi#json#encode()
function! s:_json_encode_irreversible(depth, val) abort
if type(a:val) == 0
return a:val
elseif type(a:val) == 1
let json = '"' . escape(a:val, '\"') . '"'
let json = substitute(json, "\r", '\\r', 'g')
let json = substitute(json, "\n", '\\n', 'g')
let json = substitute(json, "\t", '\\t', 'g')
"let json = substitute(json, '\([[:cntrl:]]\)', '\=printf("\x%02d", char2nr(submatch(1)))', 'g')
return iconv(json, &encoding, "utf-8")
"return json_encode(a:val)
elseif type(a:val) == 2
return '"' . s:string_fn(a:val) . '"'
elseif type(a:val) == 3
if a:depth > 7 | return '["%%MAX_DEPTH%%:' . a:depth . '"]' | endif
return '[' . join(map(copy(a:val), 's:_json_encode_irreversible(a:depth+1, v:val)'), ',') . ']'
elseif type(a:val) == 4
" NOTE: 深すぎるとmaxfuncdepthを超えるエラーが出る
if a:depth > 7 | return '{"%%MAX_DEPTH%%":' . a:depth . '}' | endif
return '{' . join(map(keys(a:val), 's:_json_encode_irreversible(a:depth+1, v:val).":".s:_json_encode_irreversible(a:depth+1, a:val[v:val])'), ',') . '}'
elseif type(a:val) == 5
return a:val
elseif type(a:val) == 6
if a:val == v:true
return 'true'
elseif a:val == v:false
return 'false'
endif
throw 'unknown type 5 value:'.string(a:val)
elseif type(a:val) == 7
if a:val == v:null
return 'null'
elseif a:val == v:none
return '"v:none"'
endif
throw 'unknown type 7 value:'.string(a:val)
elseif type(a:val) == 8
return '"' . "job('" . string(a:val) . "')" . '"'
elseif type(a:val) == 9
return '"' . "ch('" . string(a:val) . "')" . '"'
elseif type(a:val) == 10
return '"' . "blob('" . string(a:val). "')" . '"'
else
throw 'unknown type:'.type(a:val)
endif
endfunction
function! s:string_fn(fn)
let l:sfn = string(a:fn)
let l:start = stridx(l:sfn, "'")
let l:end = l:start+1 + stridx(l:sfn[l:start+1:], "'")
if l:sfn[l:end:] == "')"
return l:sfn
else
" NOTE: 長いと見辛いので省略
return l:sfn[:l:end] . ', ...)'
endif
endfunction
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment