Remove VS.LSP.CompletionItem
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
let s:Position = vital#cmp#import('VS.LSP.Position')
|
||||
let s:TextEdit = vital#cmp#import('VS.LSP.TextEdit')
|
||||
let s:CompletionItem = vital#cmp#import('VS.LSP.CompletionItem')
|
||||
|
||||
"
|
||||
" cmp#apply_text_edits
|
||||
@@ -9,24 +7,3 @@ function! cmp#apply_text_edits(bufnr, text_edits) abort
|
||||
call s:TextEdit.apply(a:bufnr, a:text_edits)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" cmp#confirm
|
||||
"
|
||||
function! cmp#confirm(args) abort
|
||||
call s:CompletionItem.confirm({
|
||||
\ 'suggest_position': s:Position.vim_to_lsp('%', [line('.'), a:args.suggest_offset]),
|
||||
\ 'request_position': s:Position.vim_to_lsp('%', [line('.'), a:args.request_offset]),
|
||||
\ 'current_position': s:Position.vim_to_lsp('%', [line('.'), col('.')]),
|
||||
\ 'current_line': getline('.'),
|
||||
\ 'completion_item': a:args.completion_item,
|
||||
\ 'expand_snippet': s:get_expand_snippet(),
|
||||
\ })
|
||||
endfunction
|
||||
|
||||
"
|
||||
" get_expand_snippet
|
||||
"
|
||||
function! s:get_expand_snippet() abort
|
||||
return { args -> luaeval('require"cmp"._expand_snippet(_A)', args) }
|
||||
endfunction
|
||||
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not modify the code nor insert new lines before '" ___vital___'
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_cmp#VS#LSP#CompletionItem#import() abort', printf("return map({'_vital_depends': '', 'confirm': '', '_vital_loaded': ''}, \"vital#_cmp#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
" ___vital___
|
||||
"
|
||||
" _vital_loaded
|
||||
"
|
||||
function! s:_vital_loaded(V) abort
|
||||
let s:Position = a:V.import('VS.LSP.Position')
|
||||
let s:TextEdit = a:V.import('VS.LSP.TextEdit')
|
||||
let s:Text = a:V.import('VS.LSP.Text')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _vital_depends
|
||||
"
|
||||
function! s:_vital_depends() abort
|
||||
return ['VS.LSP.Position', 'VS.LSP.TextEdit', 'VS.LSP.Text']
|
||||
endfunction
|
||||
|
||||
"
|
||||
" confirm
|
||||
"
|
||||
" @param {LSP.Position} args.suggest_position
|
||||
" @param {LSP.Position} args.request_position
|
||||
" @param {LSP.Position} args.current_position
|
||||
" @param {string} args.current_line
|
||||
" @param {LSP.CompletionItem} args.completion_item
|
||||
" @param {(args: { body: string; insert_text_mode: number; }) => void?} args.expand_snippet
|
||||
"
|
||||
" # Pre-condition
|
||||
"
|
||||
" - You must pass `current_position` that represents the position when `CompleteDone` was fired.
|
||||
" - You must pass `current_line` that represents the line when `CompleteDone` was fired.
|
||||
" - You must call this function after the commit characters has been inserted.
|
||||
"
|
||||
" # The positoins
|
||||
"
|
||||
" 0. The example case
|
||||
"
|
||||
" call getbufl|<C-x><C-o><C-n><C-y> -> call getbufline|
|
||||
"
|
||||
" 1. suggest_position
|
||||
"
|
||||
" call |getbufline
|
||||
"
|
||||
" 2. request_position
|
||||
"
|
||||
" call getbufl|ine
|
||||
"
|
||||
" 3. current_position
|
||||
"
|
||||
" call getbufline|
|
||||
"
|
||||
"
|
||||
function! s:confirm(args) abort
|
||||
let l:suggest_position = a:args.suggest_position
|
||||
let l:request_position = a:args.request_position
|
||||
let l:current_position = a:args.current_position
|
||||
let l:current_line = a:args.current_line
|
||||
let l:completion_item = a:args.completion_item
|
||||
let l:ExpandSnippet = get(a:args, 'expand_snippet', v:null)
|
||||
|
||||
" 1. Prepare for alignment to VSCode behavior.
|
||||
let l:expansion = s:_get_expansion({
|
||||
\ 'suggest_position': l:suggest_position,
|
||||
\ 'request_position': l:request_position,
|
||||
\ 'current_position': l:current_position,
|
||||
\ 'current_line': l:current_line,
|
||||
\ 'completion_item': l:completion_item,
|
||||
\ })
|
||||
if !empty(l:expansion)
|
||||
" Remove commit characters if expansion is needed.
|
||||
if getline('.') !=# l:current_line
|
||||
call setline(l:current_position.line + 1, l:current_line)
|
||||
call cursor(s:Position.lsp_to_vim('%', l:current_position))
|
||||
endif
|
||||
|
||||
" Restore state of the timing when `textDocument/completion` was sent.
|
||||
call s:TextEdit.apply('%', [{
|
||||
\ 'range': { 'start': l:request_position, 'end': l:current_position },
|
||||
\ 'newText': ''
|
||||
\ }])
|
||||
endif
|
||||
|
||||
" 2. Apply additionalTextEdits
|
||||
if type(get(l:completion_item, 'additionalTextEdits', v:null)) == type([])
|
||||
call s:TextEdit.apply('%', l:completion_item.additionalTextEdits)
|
||||
endif
|
||||
|
||||
" 3. Apply expansion
|
||||
if !empty(l:expansion)
|
||||
let l:current_position = s:Position.cursor() " Update current_position to after additionalTextEdits.
|
||||
let l:range = {
|
||||
\ 'start': extend({
|
||||
\ 'character': l:current_position.character - l:expansion.overflow_before,
|
||||
\ }, l:current_position, 'keep'),
|
||||
\ 'end': extend({
|
||||
\ 'character': l:current_position.character + l:expansion.overflow_after,
|
||||
\ }, l:current_position, 'keep')
|
||||
\ }
|
||||
|
||||
" Snippet.
|
||||
if l:expansion.is_snippet && !empty(l:ExpandSnippet)
|
||||
call s:TextEdit.apply('%', [{ 'range': l:range, 'newText': '' }])
|
||||
call cursor(s:Position.lsp_to_vim('%', l:range.start))
|
||||
call l:ExpandSnippet({ 'body': l:expansion.new_text, 'insert_text_mode': get(l:completion_item, 'insertTextMode', 2) })
|
||||
|
||||
" TextEdit.
|
||||
else
|
||||
call s:TextEdit.apply('%', [{ 'range': l:range, 'newText': l:expansion.new_text }])
|
||||
|
||||
" Move cursor position to end of new_text like as snippet.
|
||||
let l:lines = s:Text.split_by_eol(l:expansion.new_text)
|
||||
let l:cursor = copy(l:range.start)
|
||||
let l:cursor.line += len(l:lines) - 1
|
||||
let l:cursor.character = strchars(l:lines[-1]) + (len(l:lines) == 1 ? l:cursor.character : 0)
|
||||
call cursor(s:Position.lsp_to_vim('%', l:cursor))
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _get_expansion
|
||||
"
|
||||
function! s:_get_expansion(args) abort
|
||||
let l:current_line = a:args.current_line
|
||||
let l:suggest_position = a:args.suggest_position
|
||||
let l:request_position = a:args.request_position
|
||||
let l:current_position = a:args.current_position
|
||||
let l:completion_item = a:args.completion_item
|
||||
|
||||
let l:is_snippet = get(l:completion_item, 'insertTextFormat', 1) == 2
|
||||
if type(get(l:completion_item, 'textEdit', v:null)) == type({})
|
||||
let l:inserted_text = strcharpart(l:current_line, l:request_position.character, l:current_position.character - l:request_position.character)
|
||||
let l:overflow_before = l:request_position.character - l:completion_item.textEdit.range.start.character
|
||||
let l:overflow_after = l:completion_item.textEdit.range.end.character - l:request_position.character
|
||||
let l:inserted = ''
|
||||
\ . strcharpart(l:current_line, l:request_position.character - l:overflow_before, l:overflow_before)
|
||||
\ . strcharpart(l:current_line, l:request_position.character, strchars(l:inserted_text) + l:overflow_after)
|
||||
let l:new_text = l:completion_item.textEdit.newText
|
||||
if s:_trim_tabstop(l:new_text) !=# l:inserted
|
||||
" The LSP spec says `textEdit range must contain the request position.`
|
||||
return {
|
||||
\ 'overflow_before': max([0, l:overflow_before]),
|
||||
\ 'overflow_after': max([0, l:overflow_after]),
|
||||
\ 'new_text': l:new_text,
|
||||
\ 'is_snippet': l:is_snippet,
|
||||
\ }
|
||||
endif
|
||||
else
|
||||
let l:inserted = strcharpart(l:current_line, l:suggest_position.character, l:current_position.character - l:suggest_position.character)
|
||||
let l:new_text = get(l:completion_item, 'insertText', v:null)
|
||||
let l:new_text = !empty(l:new_text) ? l:new_text : l:completion_item.label
|
||||
if s:_trim_tabstop(l:new_text) !=# l:inserted
|
||||
return {
|
||||
\ 'overflow_before': l:request_position.character - l:suggest_position.character,
|
||||
\ 'overflow_after': 0,
|
||||
\ 'new_text': l:new_text,
|
||||
\ 'is_snippet': l:is_snippet,
|
||||
\ }
|
||||
endif
|
||||
endif
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _trim_tabstop
|
||||
"
|
||||
function! s:_trim_tabstop(text) abort
|
||||
return substitute(a:text, '\%(\$0\|\${0}\)$', '', 'g')
|
||||
endfunction
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
cmp
|
||||
5828301d6bae0858e9ea21012913544f5ef8e375
|
||||
2755f0c8fbd3442bcb7f567832e4d1455b57f9a2
|
||||
|
||||
VS.LSP.CompletionItem
|
||||
VS.LSP.Position
|
||||
VS.LSP.TextEdit
|
||||
|
||||
@@ -205,9 +205,9 @@ core.confirm = vim.schedule_wrap(function(e, option, callback)
|
||||
local has_cursor_line_text_edit = (function()
|
||||
local minrow = math.min(pre.cursor.row, new.cursor.row)
|
||||
local maxrow = math.max(pre.cursor.row, new.cursor.row)
|
||||
for _, text_edit in ipairs(text_edits) do
|
||||
local srow = text_edit.range.start.line + 1
|
||||
local erow = text_edit.range['end'].line + 1
|
||||
for _, te in ipairs(text_edits) do
|
||||
local srow = te.range.start.line + 1
|
||||
local erow = te.range['end'].line + 1
|
||||
if srow <= minrow and maxrow <= erow then
|
||||
return true
|
||||
end
|
||||
@@ -235,30 +235,48 @@ core.confirm = vim.schedule_wrap(function(e, option, callback)
|
||||
completion_item.textEdit.range = e:get_insert_range()
|
||||
end
|
||||
|
||||
-- First, emulates vim's `<C-y>` behavior and then confirms LSP functionalities.
|
||||
if #(misc.safe(e:get_completion_item().additionalTextEdits) or {}) > 0 then
|
||||
vim.fn['cmp#apply_text_edits'](pre.bufnr, e:get_completion_item().additionalTextEdits)
|
||||
end
|
||||
|
||||
local range = types.lsp.Range.to_vim(pre.bufnr, e:get_insert_range())
|
||||
-- First, emulates vim's `<C-y>` behavior and then confirms LSP functionalities.
|
||||
local range = types.lsp.Range.to_vim(pre.bufnr, completion_item.textEdit.range)
|
||||
local before_text = string.sub(pre.cursor_line, range.start.col, pre.cursor.col - 1)
|
||||
local after_text = string.sub(pre.cursor_line, pre.cursor.col, pre.cursor.col + (range['end'].col - e.context.cursor.col) - 1)
|
||||
local before_len = vim.fn.strchars(before_text)
|
||||
local after_len = vim.fn.strchars(after_text)
|
||||
local keys = string.rep('<C-g>U<Right>', after_len) .. string.rep('<BS>', before_len + after_len) .. e:get_word()
|
||||
local keys = '<C-g>u' .. string.rep('<C-g>U<Right>', after_len) .. string.rep('<BS>', before_len + after_len)
|
||||
if not completion_item.insertTextFormat == types.lsp.InsertTextFormat.Snippet then
|
||||
keys = keys .. completion_item.textEdit.newText
|
||||
else
|
||||
keys = keys .. e:get_word()
|
||||
end
|
||||
keymap.feedkeys(
|
||||
keys,
|
||||
'n',
|
||||
vim.schedule_wrap(function()
|
||||
vim.fn['cmp#confirm']({
|
||||
request_offset = e.context.cursor.col,
|
||||
suggest_offset = e:get_offset(),
|
||||
completion_item = completion_item,
|
||||
})
|
||||
|
||||
-- execute
|
||||
local execute = function()
|
||||
e:execute(function()
|
||||
if callback then
|
||||
callback()
|
||||
end
|
||||
end)
|
||||
end
|
||||
if completion_item.insertTextFormat == types.lsp.InsertTextFormat.Snippet then
|
||||
keymap.feedkeys(
|
||||
'<C-g>U' .. string.rep('<BS>', vim.fn.strchars(e:get_word())),
|
||||
'n',
|
||||
vim.schedule_wrap(function()
|
||||
config.get().snippet.expand({
|
||||
body = completion_item.textEdit.newText,
|
||||
insert_text_mode = completion_item.insertTextMode,
|
||||
})
|
||||
execute()
|
||||
end)
|
||||
)
|
||||
else
|
||||
execute()
|
||||
end
|
||||
end)
|
||||
)
|
||||
end)
|
||||
|
||||
@@ -190,13 +190,19 @@ end
|
||||
---@return vim.CompletedItem
|
||||
entry.get_vim_item = function(self, suggeset_offset)
|
||||
return self.cache:ensure({ 'get_vim_item', suggeset_offset }, function()
|
||||
local diff = vim.str_byteindex(self.context.cursor_line, self:get_replace_range()['end'].character)
|
||||
local item = config.get().formatting.format(self, suggeset_offset)
|
||||
item.word = str.remove_suffix(item.word, string.sub(self.context.cursor_line, self.context.cursor.col, diff))
|
||||
item.equal = 1
|
||||
item.empty = 1
|
||||
item.dup = self.completion_item.dup or 1
|
||||
item.user_data = { cmp = self.id }
|
||||
|
||||
for i = 1, #item.word - 1 do
|
||||
if str.has_prefix(self.context.cursor_after_line, string.sub(item.word, i, #item.word)) then
|
||||
item.word = string.sub(item.word, 1, i - 1)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return item
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -55,13 +55,6 @@ cmp.close = function()
|
||||
core.reset()
|
||||
end
|
||||
|
||||
---Internal expand snippet function.
|
||||
---TODO: It should be removed when we remove `autoload/cmp.vim`.
|
||||
---@param args cmp.SnippetExpansionParams
|
||||
cmp._expand_snippet = function(args)
|
||||
return config.get().snippet.expand(args)
|
||||
end
|
||||
|
||||
---Handle events
|
||||
autocmd.subscribe('InsertEnter', function()
|
||||
core.prepare()
|
||||
|
||||
Reference in New Issue
Block a user