Skip to content
This repository was archived by the owner on Oct 13, 2021. It is now read-only.

Commit a639df2

Browse files
committed
feat: better api for custom complete source
fix: lua check fix: some api changes
1 parent 62b5375 commit a639df2

File tree

5 files changed

+55
-94
lines changed

5 files changed

+55
-94
lines changed

lua/completion.lua

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
local vim = vim
22
local api = vim.api
3+
local match = require'completion.matching'
34
local source = require 'source'
45
local signature = require'completion.signature_help'
56
local hover = require'completion.hover'
@@ -182,6 +183,14 @@ M.customize_buf_label = function(label)
182183
api.nvim_buf_set_var(0, "completion_buf_customize_lsp_label", label)
183184
end
184185

186+
M.insertCompletionItems = function(complete_items, prefix, item)
187+
match.matching(complete_items, prefix, item)
188+
end
189+
190+
M.addCompletionSource = function(key, complete_item)
191+
source.addCompleteItems(key, complete_item)
192+
end
193+
185194
M.on_attach = function(opt)
186195
api.nvim_command [[augroup CompletionCommand]]
187196
api.nvim_command("autocmd! * <buffer>")

lua/completion/matching.lua

Lines changed: 18 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,13 @@
11
local vim = vim
2+
local util = require'completion.util'
23
local M = {}
34

4-
-- Levenshtein algorithm for fuzzy matching
5-
-- https://gist.github.com/james2doyle/e406180e143da3bdd102
6-
local function fuzzy_score(str1, str2)
7-
local len1 = #str1
8-
local len2 = #str2
9-
local matrix = {}
10-
local cost
11-
local min = math.min;
12-
13-
-- quick cut-offs to save time
14-
if (len1 == 0) then
15-
return len2
16-
elseif (len2 == 0) then
17-
return len1
18-
elseif (str1 == str2) then
19-
return 0
20-
end
21-
22-
-- initialise the base matrix values
23-
for i = 0, len1, 1 do
24-
matrix[i] = {}
25-
matrix[i][0] = i
26-
end
27-
for j = 0, len2, 1 do
28-
matrix[0][j] = j
29-
end
30-
31-
-- actual Levenshtein algorithm
32-
for i = 1, len1, 1 do
33-
for j = 1, len2, 1 do
34-
if (str1:byte(i) == str2:byte(j)) then
35-
cost = 0
36-
else
37-
cost=1
38-
end
39-
matrix[i][j] = min(matrix[i-1][j] + 2, matrix[i][j-1], matrix[i-1][j-1] + cost)
40-
end
41-
end
42-
43-
-- return the last value - this is the Levenshtein distance
44-
return matrix[len1][len2]
45-
end
46-
475
local function fuzzy_match(prefix, word)
486
if vim.g.completion_matching_ignore_case == 1 then
497
prefix = string.lower(prefix)
508
word = string.lower(word)
519
end
52-
local score = fuzzy_score(prefix, word)
10+
local score = util.fuzzy_score(prefix, word)
5311
if score < 1 then
5412
return true, score
5513
else
@@ -82,10 +40,24 @@ local function exact_match(prefix, word)
8240
end
8341
end
8442

85-
M.matching_strategy = {
43+
local matching_strategy = {
8644
fuzzy = fuzzy_match,
87-
substr = substring_match,
45+
substring = substring_match,
8846
exact = exact_match
8947
}
9048

49+
M.matching = function(complete_items, prefix, item)
50+
local matcher_list = vim.b.completion_matching_strategy_list or vim.g.completion_matching_strategy_list
51+
local matching_piroity = 1
52+
for _, method in ipairs(matcher_list) do
53+
local is_match, score = matching_strategy[method](prefix, item.word)
54+
if is_match then
55+
item.user_data.matching_piroity = matching_piroity
56+
item.score = score
57+
util.addCompletionItems(complete_items, item)
58+
break
59+
end
60+
end
61+
end
62+
9163
return M

lua/completion/util.lua

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,19 @@ function M.sort_completion_items(items)
3030
end
3131

3232
function M.addCompletionItems(item_table, item)
33+
-- word cannot be nil
34+
if item.word == nil then return end
3335
table.insert(item_table, {
3436
word = item.word,
35-
abbr = item.abbr,
36-
kind = item.kind,
37-
menu = item.menu,
38-
info = item.info,
37+
abbr = item.abbr or '',
38+
kind = item.kind or '',
39+
menu = item.menu or '',
40+
info = item.info or '',
41+
priority = item.priority or 1,
3942
icase = 1,
4043
dup = 1,
4144
empty = 1,
42-
user_data = item.user_data,
45+
user_data = item.user_data or {},
4346
})
4447
end
4548

lua/source/lsp.lua

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,22 +58,12 @@ local function text_document_completion_list_to_complete_items(result, prefix)
5858
}
5959
}
6060
local kind = protocol.CompletionItemKind[completion_item.kind]
61-
item.kind = customize_label[kind] or kind or ''
61+
item.kind = customize_label[kind] or kind
6262
item.abbr = completion_item.label
63-
item.priority = vim.g.completion_items_priority[item.kind] or 1
63+
item.priority = vim.g.completion_items_priority[item.kind]
6464
item.menu = completion_item.detail or ''
65-
local matching_piroity = 1
6665

67-
local matcher_list = vim.b.completion_matching_strategy_list or vim.g.completion_matching_strategy_list
68-
for _, method in ipairs(matcher_list) do
69-
local is_match, score = match.matching_strategy[method](prefix, item.word)
70-
item.score = score
71-
if is_match then
72-
item.user_data.matching_piroity = matching_piroity
73-
util.addCompletionItems(matches, item)
74-
break
75-
end
76-
end
66+
match.matching(matches, prefix, item)
7767
end
7868
end
7969

lua/source/snippet.lua

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
local vim = vim
22
local api = vim.api
3+
local match = require'completion.matching'
34
local M = {}
45

56

6-
local getUltisnipItems = function(prefix, score_func)
7+
local getUltisnipItems = function(prefix)
78
if vim.fn.exists("*UltiSnips#SnippetsInCurrentScope") == 0 then return {} end
89
local snippetsList = api.nvim_call_function('UltiSnips#SnippetsInCurrentScope', {})
910
local complete_items = {}
@@ -16,51 +17,37 @@ local getUltisnipItems = function(prefix, score_func)
1617
if key == true then
1718
key = 'true'
1819
end
19-
local score = score_func(prefix, key)
20+
local item = {}
21+
item.word = key
22+
item.kind = 'UltiSnips'
23+
item.priority = priority
2024
local user_data = {hover = val}
21-
if score < #prefix/2 then
22-
table.insert(complete_items, {
23-
word = key,
24-
kind = 'UltiSnips',
25-
score = score,
26-
priority = priority,
27-
icase = 1,
28-
dup = 1,
29-
empty = 1,
30-
user_data = vim.fn.json_encode(user_data)
31-
})
32-
end
25+
item.user_data = user_data
26+
match.matching(complete_items, prefix, item)
3327
end
3428
return complete_items
3529
end
3630

37-
local getNeosnippetItems = function(prefix, score_func)
31+
local getNeosnippetItems = function(prefix)
3832
if vim.fn.exists("*neosnippet#helpers#get_completion_snippets") == 0 then return {} end
3933
local snippetsList = api.nvim_call_function('neosnippet#helpers#get_completion_snippets', {})
4034
local complete_items = {}
4135
if vim.tbl_isempty(snippetsList) == 0 then
4236
return {}
4337
end
44-
local priority = vim.g.completion_items_priority['Neosnippet'] or 1
38+
local priority = vim.g.completion_items_priority['Neosnippet']
4539
for key, val in pairs(snippetsList) do
4640
if key == true then
4741
key = 'true'
4842
end
4943
local user_data = {hover = val.description}
50-
local score = score_func(prefix, key)
51-
if score < #prefix/2 then
52-
table.insert(complete_items, {
53-
word = key,
54-
kind = 'Neosnippet',
55-
score = score,
56-
priority = priority,
57-
icase = 1,
58-
dup = 1,
59-
empty = 1,
60-
user_data = vim.fn.json_encode(user_data)
61-
})
62-
end
63-
end
44+
local item = {}
45+
item.word = key
46+
item.kind = 'Neosnippet'
47+
item.priority = priority
48+
item.user_data = user_data
49+
match.matching(complete_items, prefix, item)
50+
end
6451
return complete_items
6552
end
6653

0 commit comments

Comments
 (0)