dev (#1)
* dev * Improve sync design * Support buffer local mapping * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * stylua * tmp * tmp * tmp * tmp * tmp * tmp * tmp * integration * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * update * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp * tmp
This commit is contained in:
185
autoload/vital/_cmp/VS/LSP/TextEdit.vim
Normal file
185
autoload/vital/_cmp/VS/LSP/TextEdit.vim
Normal file
@@ -0,0 +1,185 @@
|
||||
" ___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#TextEdit#import() abort', printf("return map({'_vital_depends': '', 'apply': '', '_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:Text = a:V.import('VS.LSP.Text')
|
||||
let s:Position = a:V.import('VS.LSP.Position')
|
||||
let s:Buffer = a:V.import('VS.Vim.Buffer')
|
||||
let s:Option = a:V.import('VS.Vim.Option')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _vital_depends
|
||||
"
|
||||
function! s:_vital_depends() abort
|
||||
return ['VS.LSP.Text', 'VS.LSP.Position', 'VS.Vim.Buffer', 'VS.Vim.Option']
|
||||
endfunction
|
||||
|
||||
"
|
||||
" apply
|
||||
"
|
||||
function! s:apply(path, text_edits) abort
|
||||
let l:current_bufname = bufname('%')
|
||||
let l:current_position = s:Position.cursor()
|
||||
|
||||
let l:target_bufnr = s:_switch(a:path)
|
||||
call s:_substitute(l:target_bufnr, a:text_edits, l:current_position)
|
||||
let l:current_bufnr = s:_switch(l:current_bufname)
|
||||
|
||||
if l:current_bufnr == l:target_bufnr
|
||||
call cursor(s:Position.lsp_to_vim('%', l:current_position))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _substitute
|
||||
"
|
||||
function! s:_substitute(bufnr, text_edits, current_position) abort
|
||||
try
|
||||
" Save state.
|
||||
let l:Restore = s:Option.define({
|
||||
\ 'foldenable': '0',
|
||||
\ })
|
||||
let l:view = winsaveview()
|
||||
|
||||
" Apply substitute.
|
||||
let [l:fixeol, l:text_edits] = s:_normalize(a:bufnr, a:text_edits)
|
||||
for l:text_edit in l:text_edits
|
||||
let l:start = s:Position.lsp_to_vim(a:bufnr, l:text_edit.range.start)
|
||||
let l:end = s:Position.lsp_to_vim(a:bufnr, l:text_edit.range.end)
|
||||
let l:text = s:Text.normalize_eol(l:text_edit.newText)
|
||||
execute printf('noautocmd keeppatterns keepjumps silent %ssubstitute/\%%%sl\%%%sc\_.\{-}\%%%sl\%%%sc/\=l:text/%se',
|
||||
\ l:start[0],
|
||||
\ l:start[0],
|
||||
\ l:start[1],
|
||||
\ l:end[0],
|
||||
\ l:end[1],
|
||||
\ &gdefault ? 'g' : ''
|
||||
\ )
|
||||
call s:_fix_cursor_position(a:current_position, l:text_edit, s:Text.split_by_eol(l:text))
|
||||
endfor
|
||||
|
||||
" Remove last empty line if fixeol enabled.
|
||||
if l:fixeol && getline('$') ==# ''
|
||||
noautocmd keeppatterns keepjumps silent $delete _
|
||||
endif
|
||||
catch /.*/
|
||||
echomsg string({ 'exception': v:exception, 'throwpoint': v:throwpoint })
|
||||
finally
|
||||
" Restore state.
|
||||
call l:Restore()
|
||||
call winrestview(l:view)
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _fix_cursor_position
|
||||
"
|
||||
function! s:_fix_cursor_position(position, text_edit, lines) abort
|
||||
let l:lines_len = len(a:lines)
|
||||
let l:range_len = (a:text_edit.range.end.line - a:text_edit.range.start.line) + 1
|
||||
|
||||
if a:text_edit.range.end.line < a:position.line
|
||||
let a:position.line += l:lines_len - l:range_len
|
||||
elseif a:text_edit.range.end.line == a:position.line && a:text_edit.range.end.character <= a:position.character
|
||||
let a:position.line += l:lines_len - l:range_len
|
||||
let a:position.character = strchars(a:lines[-1]) + (a:position.character - a:text_edit.range.end.character)
|
||||
if l:lines_len == 1
|
||||
let a:position.character += a:text_edit.range.start.character
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _normalize
|
||||
"
|
||||
function! s:_normalize(bufnr, text_edits) abort
|
||||
let l:text_edits = type(a:text_edits) == type([]) ? a:text_edits : [a:text_edits]
|
||||
let l:text_edits = s:_range(l:text_edits)
|
||||
let l:text_edits = sort(l:text_edits, function('s:_compare'))
|
||||
let l:text_edits = reverse(l:text_edits)
|
||||
return s:_fix_text_edits(a:bufnr, l:text_edits)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _range
|
||||
"
|
||||
function! s:_range(text_edits) abort
|
||||
let l:text_edits = []
|
||||
for l:text_edit in a:text_edits
|
||||
if type(l:text_edit) != type({})
|
||||
continue
|
||||
endif
|
||||
if l:text_edit.range.start.line > l:text_edit.range.end.line || (
|
||||
\ l:text_edit.range.start.line == l:text_edit.range.end.line &&
|
||||
\ l:text_edit.range.start.character > l:text_edit.range.end.character
|
||||
\ )
|
||||
let l:text_edit.range = { 'start': l:text_edit.range.end, 'end': l:text_edit.range.start }
|
||||
endif
|
||||
let l:text_edits += [l:text_edit]
|
||||
endfor
|
||||
return l:text_edits
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _compare
|
||||
"
|
||||
function! s:_compare(text_edit1, text_edit2) abort
|
||||
let l:diff = a:text_edit1.range.start.line - a:text_edit2.range.start.line
|
||||
if l:diff == 0
|
||||
return a:text_edit1.range.start.character - a:text_edit2.range.start.character
|
||||
endif
|
||||
return l:diff
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _fix_text_edits
|
||||
"
|
||||
function! s:_fix_text_edits(bufnr, text_edits) abort
|
||||
let l:max = s:Buffer.get_line_count(a:bufnr)
|
||||
|
||||
let l:fixeol = v:false
|
||||
let l:text_edits = []
|
||||
for l:text_edit in a:text_edits
|
||||
if l:max <= l:text_edit.range.start.line
|
||||
let l:text_edit.range.start.line = l:max - 1
|
||||
let l:text_edit.range.start.character = strchars(get(getbufline(a:bufnr, '$'), 0, ''))
|
||||
let l:text_edit.newText = "\n" . l:text_edit.newText
|
||||
let l:fixeol = &fixendofline && !&binary
|
||||
endif
|
||||
if l:max <= l:text_edit.range.end.line
|
||||
let l:text_edit.range.end.line = l:max - 1
|
||||
let l:text_edit.range.end.character = strchars(get(getbufline(a:bufnr, '$'), 0, ''))
|
||||
let l:fixeol = &fixendofline && !&binary
|
||||
endif
|
||||
call add(l:text_edits, l:text_edit)
|
||||
endfor
|
||||
|
||||
return [l:fixeol, l:text_edits]
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _switch
|
||||
"
|
||||
function! s:_switch(path) abort
|
||||
let l:curr = bufnr('%')
|
||||
let l:next = bufnr(a:path)
|
||||
if l:next >= 0
|
||||
if l:curr != l:next
|
||||
execute printf('noautocmd keepalt keepjumps %sbuffer!', bufnr(a:path))
|
||||
endif
|
||||
else
|
||||
execute printf('noautocmd keepalt keepjumps edit! %s', fnameescape(a:path))
|
||||
endif
|
||||
return bufnr('%')
|
||||
endfunction
|
||||
|
||||
Reference in New Issue
Block a user