feat(lsp): add snippet support and refactor completion into Item class
This commit is contained in:
@@ -22,24 +22,20 @@ local function fence(ft, text)
|
||||
return string.format("```%s\n%s\n```", ft, text)
|
||||
end
|
||||
|
||||
---@param item lsp.CompletionItem
|
||||
---@param item ow.lsp.completion.Item
|
||||
---@param ft string
|
||||
---@return string? content
|
||||
---@return integer? width
|
||||
local function build_content(item, ft)
|
||||
local signature = item.detail
|
||||
or vim.tbl_get(item, "labelDetails", "description")
|
||||
local doc = item.documentation
|
||||
if type(doc) == "table" then
|
||||
doc = doc.value
|
||||
end
|
||||
|
||||
local sections = {}
|
||||
if signature then
|
||||
table.insert(sections, fence(ft, signature))
|
||||
if item.detail then
|
||||
table.insert(sections, fence(ft, item.detail))
|
||||
end
|
||||
if doc then
|
||||
table.insert(sections, doc)
|
||||
if item.snippet then
|
||||
table.insert(sections, fence(ft, item.snippet))
|
||||
end
|
||||
if item.doc then
|
||||
table.insert(sections, item.doc)
|
||||
end
|
||||
if #sections == 0 then
|
||||
return nil, nil
|
||||
@@ -59,7 +55,7 @@ end
|
||||
---@field private winid integer?
|
||||
---@field private bufnr integer?
|
||||
---@field private pending ow.lsp.completion.PendingResolve?
|
||||
---@field private resolved { word: string, item: lsp.CompletionItem }?
|
||||
---@field private resolved { word: string, item: ow.lsp.completion.Item }?
|
||||
local Popup = {}
|
||||
Popup.__index = Popup
|
||||
|
||||
@@ -73,12 +69,8 @@ function Popup.new()
|
||||
}, Popup)
|
||||
end
|
||||
|
||||
--- Most recently resolved completion item for the given selection `word`,
|
||||
--- or `nil` if we don't have one cached. Servers like rust-analyzer fill in
|
||||
--- `additionalTextEdits` only in the resolve response, so on accept we want
|
||||
--- the resolved version rather than the original one in `user_data`.
|
||||
---@param word string
|
||||
---@return lsp.CompletionItem?
|
||||
---@return ow.lsp.completion.Item?
|
||||
function Popup:resolved_for(word)
|
||||
if self.resolved and self.resolved.word == word then
|
||||
return self.resolved.item
|
||||
@@ -99,8 +91,7 @@ function Popup:close()
|
||||
self.winid = nil
|
||||
end
|
||||
|
||||
--- Build content for `item` and show, or close if there's nothing to render.
|
||||
---@param item lsp.CompletionItem
|
||||
---@param item ow.lsp.completion.Item
|
||||
---@param ft string
|
||||
---@param pum ow.lsp.completion.Pum
|
||||
function Popup:show(item, ft, pum)
|
||||
@@ -112,11 +103,8 @@ function Popup:show(item, ft, pum)
|
||||
end
|
||||
end
|
||||
|
||||
--- Cancel any in-flight resolve, dispatch a fresh one for `item`, and on
|
||||
--- response render the resolved popup. If the user moved the selection
|
||||
--- before the response landed (word mismatch), do nothing.
|
||||
---@param client vim.lsp.Client
|
||||
---@param item lsp.CompletionItem
|
||||
---@param item ow.lsp.completion.Item
|
||||
---@param ft string
|
||||
---@param pum ow.lsp.completion.Pum
|
||||
---@param word string
|
||||
@@ -126,7 +114,7 @@ function Popup:dispatch_resolve(client, item, ft, pum, word, buf)
|
||||
self.resolved = nil
|
||||
local _, request_id = client:request(
|
||||
vim.lsp.protocol.Methods.completionItem_resolve,
|
||||
item,
|
||||
item.raw,
|
||||
function(err, result)
|
||||
self.pending = nil
|
||||
if err or not result then
|
||||
@@ -136,8 +124,9 @@ function Popup:dispatch_resolve(client, item, ft, pum, word, buf)
|
||||
if (vim.tbl_get(cur, "completed", "word") or "") ~= word then
|
||||
return
|
||||
end
|
||||
self.resolved = { word = word, item = result }
|
||||
self:show(result, ft, pum)
|
||||
item:apply_resolved(result)
|
||||
self.resolved = { word = word, item = item }
|
||||
self:show(item, ft, pum)
|
||||
end,
|
||||
buf
|
||||
)
|
||||
@@ -146,7 +135,7 @@ function Popup:dispatch_resolve(client, item, ft, pum, word, buf)
|
||||
end
|
||||
end
|
||||
|
||||
---@param direction string single-line scroll keycode (<C-e> or <C-y>)
|
||||
---@param direction string single-line scroll keycode (<C-e> or <C-y>)
|
||||
function Popup:scroll_line(direction)
|
||||
self:scroll(direction, 1)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user