Skip to content

Commit

Permalink
Always use substitute method in TextEdit
Browse files Browse the repository at this point in the history
  • Loading branch information
hrsh7th committed Jan 6, 2021
1 parent 761ac6d commit 34d81d2
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 144 deletions.
3 changes: 1 addition & 2 deletions autoload/lsp/internal/linked_editing_range.vim
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ function! lsp#internal#linked_editing_range#_enable() abort
\ lsp#callbag#pipe(
\ lsp#callbag#fromEvent(['TextChanged', 'TextChangedI', 'TextChangedP']),
\ lsp#callbag#filter({ -> g:lsp_linked_editing_range_enabled }),
\ lsp#callbag#delay(0),
\ lsp#callbag#subscribe({ -> s:sync() })
\ ),
\ )
Expand Down Expand Up @@ -60,7 +59,7 @@ function! lsp#internal#linked_editing_range#prepare() abort
endfunction

function! s:enabled(...) abort
return g:lsp_linked_editing_range_enabled && s:TextEdit.is_text_mark_preserved() && s:TextMark.is_available()
return g:lsp_linked_editing_range_enabled && s:TextMark.is_available()
endfunction

function! s:request_sync() abort
Expand Down
152 changes: 12 additions & 140 deletions autoload/vital/_lsp/VS/LSP/TextEdit.vim
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_lsp#VS#LSP#TextEdit#import() abort', printf("return map({'set_method': '', '_vital_depends': '', 'get_method': '', 'is_text_mark_preserved': '', 'apply': '', 'get_methods': '', 'delete': '', '_vital_loaded': ''}, \"vital#_lsp#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
execute join(['function! vital#_lsp#VS#LSP#TextEdit#import() abort', printf("return map({'_vital_depends': '', 'apply': '', 'delete': '', '_vital_loaded': ''}, \"vital#_lsp#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
"
Expand All @@ -23,61 +23,6 @@ function! s:_vital_depends() abort
return ['VS.LSP.Text', 'VS.LSP.Position', 'VS.Vim.Option']
endfunction

"
" Current selected method.
"
let s:_method = 'auto'

"
" This dict contains some logics for patching text.
"
let s:_methods = {}

"
" set_method
"
function! s:set_method(method) abort
if !has_key(s:_methods, a:method)
let s:_method = 'auto'
elseif a:method ==# 'nvim_buf_set_text' && !exists('*nvim_buf_set_text')
let s:_method = 'auto'
elseif a:method ==# 'normal' && has('nvim')
let s:_method = 'auto'
else
let s:_method = a:method
endif
endfunction

"
" get_method
"
function! s:get_method() abort
if s:_method ==# 'auto'
if exists('*nvim_buf_set_text')
return 'nvim_buf_set_text'
elseif !has('nvim')
return 'normal'
else
return 'function'
endif
endif
return s:_method
endfunction

"
" get_methods
"
function! s:get_methods() abort
return ['nvim_buf_set_text', 'normal', 'function']
endfunction

"
" is_text_mark_preserved
"
function! s:is_text_mark_preserved() abort
return index(['nvim_buf_set_text'], s:get_method()) >= 0
endfunction

"
" apply
"
Expand All @@ -89,7 +34,7 @@ function! s:apply(path, text_edits) abort
try
call s:_switch(a:path)
let [l:has_overflowed, l:text_edits] = s:_normalize(bufnr(l:target_bufname), a:text_edits)
let l:fix_cursor = s:_methods[s:get_method()](bufnr(l:target_bufname), l:text_edits, l:cursor_position)
let l:fix_cursor = s:_substitute(bufnr(l:target_bufname), l:text_edits, l:cursor_position)
if l:has_overflowed && getline('$') ==# ''
call s:delete(bufnr(l:target_bufname), '$', '$')
endif
Expand All @@ -103,63 +48,34 @@ function! s:apply(path, text_edits) abort
endif
endfunction

let s:_methods = {}

"
" nvim_buf_set_text
" _substitute
"
function! s:_methods.nvim_buf_set_text(bufnr, text_edits, cursor_position) abort
let l:fix_cursor = v:false

for l:text_edit in a: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:lines = s:Text.split_by_eol(l:text_edit.newText)
call nvim_buf_set_text(
\ a:bufnr,
\ l:start[0] - 1,
\ l:start[1] - 1,
\ l:end[0] - 1,
\ l:end[1] - 1,
\ l:lines
\ )
let l:fix_cursor = s:_fix_cursor(a:cursor_position, l:text_edit, l:lines) || l:fix_cursor
endfor

return l:fix_cursor
endfunction

"
" normal
"
function! s:_methods.normal(bufnr, text_edits, cursor_position) abort
function! s:_substitute(bufnr, text_edits, cursor_position) abort
let l:fix_cursor = v:false

try
let l:Restore = s:Option.define({
\ 'foldenable': '0',
\ 'virtualedit': 'onemore',
\ 'whichwrap': 'h',
\ 'selection': 'exclusive',
\ })
let l:view = winsaveview()
let l:regx = getreg('x')

for l:text_edit in a: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)
if l:start[0] != l:end[0] || l:start[1] != l:end[1]
let l:command = printf('%sG%s|v%sG%s|"_d', l:start[0], l:start[1], l:end[0], l:end[1])
else
let l:command = printf('%sG%s|', l:start[0], l:start[1])
endif
call setreg('x', s:Text.normalize_eol(l:text_edit.newText), 'c')
execute printf('noautocmd keepjumps normal! %s"xP', l:command)

execute printf('noautocmd keepjumps %ssubstitute/\%%%sl\%%%sc\zs\_.\{-}\ze\%%%sl\%%%sc/\=getreg("x")/',
\ l:start[0],
\ l:start[0],
\ l:start[1],
\ l:end[0],
\ l:end[1]
\ )
let l:fix_cursor = s:_fix_cursor(a:cursor_position, l:text_edit, s:Text.split_by_eol(l:text_edit.newText)) || l:fix_cursor
endfor
catch /.*/
echomsg string({ 'exception': v:exception, 'throwpoint': v:throwpoint })
call themis#log(string({ 'exception': v:exception, 'throwpoint': v:throwpoint }))
finally
call l:Restore()
call winrestview(l:view)
Expand All @@ -169,50 +85,6 @@ function! s:_methods.normal(bufnr, text_edits, cursor_position) abort
return l:fix_cursor
endfunction

"
" function
"
function! s:_methods.function(bufnr, text_edits, cursor_position) abort
let l:fix_cursor = v:false

for l:text_edit in a:text_edits
let l:start_line = getline(l:text_edit.range.start.line + 1)
let l:end_line = getline(l:text_edit.range.end.line + 1)
let l:before_line = strcharpart(l:start_line, 0, l:text_edit.range.start.character)
let l:after_line = strcharpart(l:end_line, l:text_edit.range.end.character, strchars(l:end_line) - l:text_edit.range.end.character)

" create lines.
let l:lines = s:Text.split_by_eol(l:text_edit.newText)
let l:lines[0] = l:before_line . l:lines[0]
let l:lines[-1] = l:lines[-1] . l:after_line

" save length.
let l:lines_len = len(l:lines)
let l:range_len = (l:text_edit.range.end.line - l:text_edit.range.start.line) + 1

" append or delete lines.
if l:lines_len > l:range_len
call append(l:text_edit.range.end.line, repeat([''], l:lines_len - l:range_len))
elseif l:lines_len < l:range_len
call s:delete(a:bufnr, l:text_edit.range.start.line + l:lines_len, l:text_edit.range.end.line)
endif

" set lines.
let l:i = 0
while l:i < len(l:lines)
let l:lnum = l:text_edit.range.start.line + l:i + 1
if get(getbufline(a:bufnr, l:lnum), 0, v:null) !=# l:lines[l:i]
call setline(l:lnum, l:lines[l:i])
endif
let l:i += 1
endwhile

let l:fix_cursor = s:_fix_cursor(a:cursor_position, l:text_edit, s:Text.split_by_eol(l:text_edit.newText))
endfor

return l:fix_cursor
endfunction

"
" _fix_cursor
"
Expand Down
2 changes: 0 additions & 2 deletions doc/vim-lsp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -687,8 +687,6 @@ g:lsp_linked_editing_enabled *g:lsp_linked_editing_enabled*

Enable textDocument/linkedEditingRange feature.

NOTE: This only works on the environment has `nvim_buf_set_text` for now.

Example: >
let g:lsp_linked_editing_enabled = 1
let g:lsp_linked_editing_enabled = 0
Expand Down

0 comments on commit 34d81d2

Please sign in to comment.