Added custom suggestions support to autocomplete
`autocomplete.add()` can now be used to add additional auto complete suggestions with descriptions
This commit is contained in:
parent
2f659d5180
commit
af36658e68
|
@ -8,9 +8,22 @@ local translate = require "core.doc.translate"
|
||||||
local RootView = require "core.rootview"
|
local RootView = require "core.rootview"
|
||||||
local DocView = require "core.docview"
|
local DocView = require "core.docview"
|
||||||
|
|
||||||
local max_suggestions = 6
|
config.autocomplete_max_suggestions = 6
|
||||||
|
|
||||||
local symbols = {}
|
local autocomplete = {}
|
||||||
|
autocomplete.map = {}
|
||||||
|
|
||||||
|
|
||||||
|
local mt = { __tostring = function(t) return t.text end }
|
||||||
|
|
||||||
|
function autocomplete.add(t)
|
||||||
|
local items = {}
|
||||||
|
for text, info in pairs(t.items) do
|
||||||
|
info = (type(info) == "string") and info
|
||||||
|
table.insert(items, setmetatable({ text = text, info = info }, mt))
|
||||||
|
end
|
||||||
|
autocomplete.map[t.name] = { files = t.files or ".*", items = items }
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
core.add_thread(function()
|
core.add_thread(function()
|
||||||
|
@ -35,8 +48,9 @@ core.add_thread(function()
|
||||||
end
|
end
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
|
local symbols = {}
|
||||||
|
|
||||||
-- lift all symbols from all docs
|
-- lift all symbols from all docs
|
||||||
local t = {}
|
|
||||||
for _, doc in ipairs(core.docs) do
|
for _, doc in ipairs(core.docs) do
|
||||||
-- update the cache if the doc has changed since the last iteration
|
-- update the cache if the doc has changed since the last iteration
|
||||||
if not cache_is_valid(doc) then
|
if not cache_is_valid(doc) then
|
||||||
|
@ -47,16 +61,13 @@ core.add_thread(function()
|
||||||
end
|
end
|
||||||
-- update symbol set with doc's symbol set
|
-- update symbol set with doc's symbol set
|
||||||
for sym in pairs(cache[doc].symbols) do
|
for sym in pairs(cache[doc].symbols) do
|
||||||
t[sym] = true
|
symbols[sym] = true
|
||||||
end
|
end
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- update symbols list
|
-- update symbols list
|
||||||
symbols = {}
|
autocomplete.add { name = "open-docs", items = symbols }
|
||||||
for sym in pairs(t) do
|
|
||||||
table.insert(symbols, sym)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- wait for next scan
|
-- wait for next scan
|
||||||
local valid = true
|
local valid = true
|
||||||
|
@ -76,7 +87,6 @@ end)
|
||||||
local partial = ""
|
local partial = ""
|
||||||
local suggestions_idx = 1
|
local suggestions_idx = 1
|
||||||
local suggestions = {}
|
local suggestions = {}
|
||||||
local last_active_view
|
|
||||||
local last_line, last_col
|
local last_line, last_col
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,6 +96,33 @@ local function reset_suggestions()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function update_suggestions()
|
||||||
|
local doc = core.active_view.doc
|
||||||
|
local filename = doc and doc.filename or ""
|
||||||
|
|
||||||
|
-- get all relevant suggestions for given filename
|
||||||
|
local items = {}
|
||||||
|
for _, v in pairs(autocomplete.map) do
|
||||||
|
if common.match_pattern(filename, v.files) then
|
||||||
|
for _, item in pairs(v.items) do
|
||||||
|
table.insert(items, item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- fuzzy match, remove duplicates and store
|
||||||
|
items = common.fuzzy_match(items, partial)
|
||||||
|
local j = 1
|
||||||
|
for i = 1, config.autocomplete_max_suggestions do
|
||||||
|
suggestions[i] = items[j]
|
||||||
|
while items[j] and items[i].text == items[j].text do
|
||||||
|
items[i].info = items[i].info or items[j].info
|
||||||
|
j = j + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
local function get_partial_symbol()
|
local function get_partial_symbol()
|
||||||
local doc = core.active_view.doc
|
local doc = core.active_view.doc
|
||||||
local line2, col2 = doc:get_selection()
|
local line2, col2 = doc:get_selection()
|
||||||
|
@ -96,7 +133,6 @@ end
|
||||||
|
|
||||||
local function get_active_view()
|
local function get_active_view()
|
||||||
if getmetatable(core.active_view) == DocView then
|
if getmetatable(core.active_view) == DocView then
|
||||||
last_active_view = core.active_view
|
|
||||||
return core.active_view
|
return core.active_view
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -115,8 +151,12 @@ local function get_suggestions_rect(av)
|
||||||
local th = font:get_height()
|
local th = font:get_height()
|
||||||
|
|
||||||
local max_width = 0
|
local max_width = 0
|
||||||
for i, sym in ipairs(suggestions) do
|
for _, s in ipairs(suggestions) do
|
||||||
max_width = math.max(max_width, font:get_width(sym))
|
local w = font:get_width(s.text)
|
||||||
|
if s.info then
|
||||||
|
w = w + style.font:get_width(s.info) + style.padding.x
|
||||||
|
end
|
||||||
|
max_width = math.max(max_width, w)
|
||||||
end
|
end
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -134,12 +174,16 @@ local function draw_suggestions_box(av)
|
||||||
|
|
||||||
-- draw text
|
-- draw text
|
||||||
local font = av:get_font()
|
local font = av:get_font()
|
||||||
local th = font:get_height()
|
local lh = font:get_height() + style.padding.y
|
||||||
local x, y = rx + style.padding.x, ry + style.padding.y
|
local y = ry + style.padding.y / 2
|
||||||
for i, sym in ipairs(suggestions) do
|
for i, s in ipairs(suggestions) do
|
||||||
local color = (i == suggestions_idx) and style.accent or style.text
|
local color = (i == suggestions_idx) and style.accent or style.text
|
||||||
renderer.draw_text(font, sym, x, y, color)
|
common.draw_text(font, color, s.text, "left", rx + style.padding.x, y, rw, lh)
|
||||||
y = y + th + style.padding.y
|
if s.info then
|
||||||
|
color = (i == suggestions_idx) and style.text or style.dim
|
||||||
|
common.draw_text(style.font, color, s.info, "right", rx, y, rw - style.padding.x, lh)
|
||||||
|
end
|
||||||
|
y = y + lh
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -158,10 +202,7 @@ RootView.on_text_input = function(...)
|
||||||
-- update partial symbol and suggestions
|
-- update partial symbol and suggestions
|
||||||
partial = get_partial_symbol()
|
partial = get_partial_symbol()
|
||||||
if #partial >= 3 then
|
if #partial >= 3 then
|
||||||
local t = common.fuzzy_match(symbols, partial)
|
update_suggestions()
|
||||||
for i = 1, max_suggestions do
|
|
||||||
suggestions[i] = t[i]
|
|
||||||
end
|
|
||||||
last_line, last_col = av.doc:get_selection()
|
last_line, last_col = av.doc:get_selection()
|
||||||
else
|
else
|
||||||
reset_suggestions()
|
reset_suggestions()
|
||||||
|
@ -211,7 +252,7 @@ command.add(predicate, {
|
||||||
["autocomplete:complete"] = function()
|
["autocomplete:complete"] = function()
|
||||||
local doc = core.active_view.doc
|
local doc = core.active_view.doc
|
||||||
local line, col = doc:get_selection()
|
local line, col = doc:get_selection()
|
||||||
local text = suggestions[suggestions_idx]
|
local text = suggestions[suggestions_idx].text
|
||||||
doc:insert(line, col, text)
|
doc:insert(line, col, text)
|
||||||
doc:remove(line, col, line, col - #partial)
|
doc:remove(line, col, line, col - #partial)
|
||||||
doc:set_selection(line, col + #text - #partial)
|
doc:set_selection(line, col + #text - #partial)
|
||||||
|
@ -238,3 +279,6 @@ keymap.add {
|
||||||
["down"] = "autocomplete:next",
|
["down"] = "autocomplete:next",
|
||||||
["escape"] = "autocomplete:cancel",
|
["escape"] = "autocomplete:cancel",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return autocomplete
|
||||||
|
|
Loading…
Reference in a new issue