Skip to content

Commit

Permalink
Add g:jsonpath_use_python option which enables python implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
mogelbrod committed May 17, 2020
1 parent a735e5a commit dcf2442
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 5 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ au FileType json noremap <buffer> <silent> <expr> <leader>p jsonpath#echo()
au FileType json noremap <buffer> <silent> <expr> <leader>g jsonpath#goto()
```

### Python support in vim

While not required it is recommended to use a Vim environment with the
`+python3` feature enabled, since the plugin provides a python implementation
that is much faster than the vimscript variant. You can check the availability
using:
```vim
:echo has("python3")
```

## Mappings

Mappings are not provided by default but can easily be added to your `.vimrc`.
Expand Down
53 changes: 48 additions & 5 deletions autoload/jsonpath.vim
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
" autoload/jsonpath.vim
" Author: Victor Hallberg <https://hallberg.cc>

if exists("g:autoloaded_jsonpath")
if exists('g:autoloaded_jsonpath')
finish
endif
let g:autoloaded_jsonpath = 1

let s:plugin_dir = expand('<sfile>:p:h:h')

let s:escapes = {
\ 'b': "\b",
\ 'f': "\f",
Expand Down Expand Up @@ -45,12 +47,27 @@ function! jsonpath#scan_buffer(search_for, ...) "{{{
endif
let is_searching = !empty(search_for)

let to_column = max([0, get(a:, 2)])

let to_line = get(a:, 1)
if to_line < 1 || to_line > line('$')
let to_line = line('$')
let to_column = strchars(getline('$'))
endif

let to_column = max([0, get(a:, 2)])
if g:jsonpath_use_python
if has('python3')
return jsonpath#scan_buffer_python(search_for, to_line, to_column)
endif

echom 'g:jsonpath_use_python set but python not found, falling back to vimscript'
endif

return jsonpath#scan_buffer_vimscript(search_for, to_line, to_column)
endfunction "}}}

function! jsonpath#scan_buffer_vimscript(search_for, to_line, to_column) "{{{
let is_searching = !empty(a:search_for)

" Parser state
let stack = []
Expand All @@ -63,7 +80,7 @@ function! jsonpath#scan_buffer(search_for, ...) "{{{

try
let lnr = 1
while lnr <= to_line "{{{
while lnr <= a:to_line "{{{
let line = getline(lnr)
let line_length = len(line)
let cnr = 1
Expand Down Expand Up @@ -129,13 +146,13 @@ function! jsonpath#scan_buffer(search_for, ...) "{{{
\})

" Check if the sought search_for path has been reached?
if stack_modified == 1 && is_searching && s:is_equal_lists(stack, search_for)
if stack_modified == 1 && is_searching && s:is_equal_lists(stack, a:search_for)
return [bufnr('%'), lnr, cnr, 0]
endif
endif

" Abort if end position has been reached
if !parsing_key && lnr >= to_line && cnr + 1 >= to_column
if !parsing_key && lnr >= a:to_line && cnr + 1 >= a:to_column
let finished = !is_searching " search failed if we reached end
break
endif
Expand Down Expand Up @@ -185,6 +202,32 @@ function! jsonpath#scan_buffer(search_for, ...) "{{{
return []
endfunction "}}}

function! jsonpath#scan_buffer_python(search_for, to_line, to_column) "{{{
py3 << EOF
import sys
import vim
sys.path.insert(0, vim.eval('s:plugin_dir'))
import jsonpath

stream = jsonpath.CountingLines(vim.current.buffer)
result = jsonpath.scan_stream(
stream,
path=vim.eval('a:search_for'),
line=int(vim.eval('a:to_line')),
column=int(vim.eval('a:to_column')),
)
EOF

let result = py3eval('result')
if empty(result)
return []
elseif !empty(a:search_for)
return [bufnr('%'), result[0], result[1], 0]
endif

return result
endfunction "}}}

" Attempts to place the cursor on identifier for the given path
function! jsonpath#goto(...) "{{{
let search_for = get(a:, 1)
Expand Down
17 changes: 17 additions & 0 deletions doc/jsonpath.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ INTRODUCTION *jsonpath*

This plugin provides ways of navigating JSON document buffers.

While not required it is recommended to use a Vim environment with the
|+python3| feature enabled, since the python implementation is much faster
than the vimscript variant. You can check the availability using: >
:echo has("python3")
<

*jsonpath-dot-notation*
Paths should be entered (and will be output) using dot notation, consisting of
properties separated by dots (configurable, see |g:jsonpath_delimeter|).
Expand Down Expand Up @@ -63,6 +69,17 @@ Set using >
let g:jsonpath_register = '*'
<

|g:jsonpath_use_python| *g:jsonpath_use_python*
Type: |int|
Default: `has('python3')`

Set this value to `0` to prevent the plugin from using python to scan the
buffer. This option should generally be left alone as the python
implementation is much faster.
Override using >
let g:jsonpath_use_python = 0
<

==============================================================================
COMMANDS *jsonpath-commands*

Expand Down
4 changes: 4 additions & 0 deletions plugin/jsonpath.vim
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ if !exists('g:jsonpath_delimeter')
let g:jsonpath_delimeter = '.'
endif

if !exists('g:jsonpath_use_python')
let g:jsonpath_use_python = has('python3')
endif

command! -nargs=? JsonPath call jsonpath#command(<q-args>)

" au FileType json noremap <buffer> <silent> <expr> <leader>g jsonpath#goto()
Expand Down

0 comments on commit dcf2442

Please sign in to comment.