Skip to content

Commit 90d0941

Browse files
Use faster get_complete_context in nvim-0.5
For users using an "autocomplete" package of some kind (so completion on every key press), a slow completion function adds noticeable lag to typing. The use of searchpairpos really slows down the current context implementation. Since nvim-0.5, there's a treesitter package included. Treesitter can incrementally parse the tree, and offers a very fast way to find the root node.
1 parent c9a155b commit 90d0941

File tree

2 files changed

+76
-25
lines changed

2 files changed

+76
-25
lines changed

autoload/fireplace.vim

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -192,37 +192,45 @@ function! s:candidate(val) abort
192192
\ }
193193
endfunction
194194

195-
function! s:get_complete_context() abort
196-
" Find toplevel form
197-
" If cursor is on start parenthesis we don't want to find the form
198-
" If cursor is on end parenthesis we want to find the form
199-
let [line1, col1] = searchpairpos('(', '', ')', 'Wrnb', g:fireplace#skip)
200-
let [line2, col2] = searchpairpos('(', '', ')', 'Wrnc', g:fireplace#skip)
195+
function! s:internal_get_complete_context() abort
196+
" Find toplevel form
197+
" If cursor is on start parenthesis we don't want to find the form
198+
" If cursor is on end parenthesis we want to find the form
199+
let [line1, col1] = searchpairpos('(', '', ')', 'Wrnb', g:fireplace#skip)
200+
let [line2, col2] = searchpairpos('(', '', ')', 'Wrnc', g:fireplace#skip)
201201

202-
if (line1 == 0 && col1 == 0) || (line2 == 0 && col2 == 0)
203-
return ""
204-
endif
202+
if (line1 == 0 && col1 == 0) || (line2 == 0 && col2 == 0)
203+
return ""
204+
endif
205205

206-
if line1 == line2
207-
let expr = getline(line1)[col1-1 : col2-1]
208-
else
209-
let expr = getline(line1)[col1-1 : -1] . ' '
210-
\ . join(getline(line1+1, line2-1), ' ')
211-
\ . getline(line2)[0 : col2-1]
212-
endif
206+
if line1 == line2
207+
let expr = getline(line1)[col1-1 : col2-1]
208+
else
209+
let expr = getline(line1)[col1-1 : -1] . ' '
210+
\ . join(getline(line1+1, line2-1), ' ')
211+
\ . getline(line2)[0 : col2-1]
212+
endif
213213

214-
" Calculate the position of cursor inside the expr
215-
if line1 == line('.')
216-
let p = col('.') - col1
217-
else
218-
let p = strlen(getline(line1)[col1-1 : -1])
219-
\ + strlen(join(getline(line1 + 1, line('.') - 1), ' '))
220-
\ + col('.')
221-
endif
214+
" Calculate the position of cursor inside the expr
215+
if line1 == line('.')
216+
let p = col('.') - col1
217+
else
218+
let p = strlen(getline(line1)[col1-1 : -1])
219+
\ + strlen(join(getline(line1 + 1, line('.') - 1), ' '))
220+
\ + col('.')
221+
endif
222222

223-
return strpart(expr, 0, p) . ' __prefix__ ' . strpart(expr, p)
223+
return strpart(expr, 0, p) . ' __prefix__ ' . strpart(expr, p)
224224
endfunction
225225

226+
if has('nvim-0.5')
227+
let s:lua_impl = luaeval("require'_fireplace'")
228+
else
229+
let s:lua_impl = {}
230+
endif
231+
232+
let s:get_complete_context = get(s:lua_impl, 'get_completion_context', function('s:internal_get_complete_context'))
233+
226234
function! s:complete_extract(msg) abort
227235
let trans = '{"word": (v:val =~# ''[./]'' ? "" : matchstr(a:base, ''^.\+/'')) . v:val}'
228236
let value = get(a:msg, 'value', get(a:msg, 'completions'))

lua/_fireplace.lua

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
local fireplace_impl = {[vim.type_idx]=vim.types.dictionary}
2+
3+
if vim.treesitter then
4+
local has_ts, ts = pcall(require, 'nvim-treesitter.ts_utils')
5+
6+
if has_ts and vim.treesitter.require_language('clojure', nil, true) then
7+
fireplace_impl['get_completion_context'] = function()
8+
vim.treesitter.get_parser(0, 'clojure'):parse()
9+
local node = ts.get_node_at_cursor()
10+
local one_ago = nil
11+
local two_ago = nil
12+
13+
while(node ~= nil) do
14+
two_ago = one_ago
15+
one_ago = node
16+
node = node:parent()
17+
end
18+
19+
local root_node = two_ago or one_ago or node
20+
21+
if root_node ~= nil then
22+
local strs = ts.get_node_text(root_node)
23+
local nrow1,ncol1,nline2,ncol2 = root_node:range()
24+
local crow,ccol = unpack(vim.api.nvim_win_get_cursor(0))
25+
26+
local idx = crow - nrow1
27+
local line = strs[idx]
28+
local coloffset = 0
29+
if crow == nrow1 then
30+
coloffset = ncol1
31+
end
32+
33+
strs[idx] = string.sub(line, 1 + coloffset, ccol + coloffset) .. ' __prefix__ ' .. string.sub(line, ccol+coloffset+1, -1)
34+
35+
return table.concat(strs, "\n")
36+
else
37+
return ""
38+
end
39+
end
40+
end
41+
end
42+
43+
return fireplace_impl

0 commit comments

Comments
 (0)