I'm editing a very large, nested JSON doc (rightscale api incase you're interested) in vim and would love to know the current json-path (like xpath for json) Something like:
Given the JSON:
{
"leve1": {
"level2": {
"level3": {
"name": "goes here"
}
}
}
}
With my cursor between "name": and "goes here" i'd like a command (or status line) that shows me:
level1/level2/level3/name
or similar.
Does anything like this exist?
I recently wrote a plugin for this called vim-jsonpath. It currently provides the following commands (that of course can be mapped):
:JsonPath
: Echoes the path to the identifier under the cursor.:JsonPath path.to.prop
: Searches the active buffer for the given path, placing the cursor on it if found.I've written two mappings that use the fold information (so they should work with any structure, not just JSON). For your example, they output
{ / "leve1": { / "level2": { / "level3": {
and (long version):
1 {
2 "leve1": {
3 "level2": {
4 "level3": {
Here is the scriptlet. It depends on my ingo-library plugin.
" [count]z? Print all lines (with numbers) that start a fold where
" the current line is contained in (for [count] upper
" levels). When a line consists of just a symbol like "{",
" the preceding non-empty line is printed, too.
" [count]z/ Like z?, but use a short output format with all line
" contents concatenated, and without line numbers and
" symbols.
if ! exists('g:PrintFoldHierarchySymbolLinePattern')
let g:PrintFoldHierarchySymbolLinePattern = '^\s*{\s*$'
endif
function! s:PrintFoldHierarchy( count, isJoin )
if foldclosed('.') != -1
return 0
endif
let l:save_view = winsaveview()
let l:levels = []
let l:lnum = line('.')
while (a:count ? len(l:levels) < a:count : 1)
silent! normal! [z
if line('.') == l:lnum
break
endif
let l:lnum = line('.')
call insert(l:levels, l:lnum)
if getline(l:lnum) =~# g:PrintFoldHierarchySymbolLinePattern
let l:precedingLnum = prevnonblank(l:lnum - 1)
if l:precedingLnum > 0
if a:isJoin
let l:levels[0] = l:precedingLnum
else
call insert(l:levels, l:precedingLnum)
endif
endif
endif
endwhile
call winrestview(l:save_view)
if a:isJoin
echo
let l:isFirst = 1
for l:lnum in l:levels
if l:isFirst
let l:isFirst = 0
else
echohl SpecialKey
echon ' / '
echohl None
endif
echon ingo#str#Trim(getline(l:lnum))
endfor
else
for l:lnum in l:levels
echohl LineNr
echo printf('%' . (ingo#window#dimensions#GetNumberWidth(1) - 1) . 'd ', l:lnum)
echohl None
echon getline(l:lnum)
endfor
endif
return 1
endfunction
nnoremap <silent> z? :<C-u>if ! <SID>PrintFoldHierarchy(v:count, 0)<Bar>execute "normal! \<lt>C-\>\<lt>C-n>\<lt>Esc>"<Bar>endif<CR>
nnoremap <silent> z/ :<C-u>if ! <SID>PrintFoldHierarchy(v:count, 1)<Bar>execute "normal! \<lt>C-\>\<lt>C-n>\<lt>Esc>"<Bar>endif<CR>
You can put that into your ~/.vimrc
(or a separate ~/.vim/plugin/PrintFoldHierarchy.vim
), and invoke the mappings from normal mode via z?
and z/
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With