Skip to content

Commit 4545247

Browse files
committed
Always use method in TextEdit
1 parent 761ac6d commit 4545247

File tree

3 files changed

+43
-179
lines changed

3 files changed

+43
-179
lines changed

autoload/lsp/internal/linked_editing_range.vim

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ function! lsp#internal#linked_editing_range#_enable() abort
3030
\ lsp#callbag#pipe(
3131
\ lsp#callbag#fromEvent(['TextChanged', 'TextChangedI', 'TextChangedP']),
3232
\ lsp#callbag#filter({ -> g:lsp_linked_editing_range_enabled }),
33-
\ lsp#callbag#delay(0),
3433
\ lsp#callbag#subscribe({ -> s:sync() })
3534
\ ),
3635
\ )
@@ -60,7 +59,7 @@ function! lsp#internal#linked_editing_range#prepare() abort
6059
endfunction
6160

6261
function! s:enabled(...) abort
63-
return g:lsp_linked_editing_range_enabled && s:TextEdit.is_text_mark_preserved() && s:TextMark.is_available()
62+
return g:lsp_linked_editing_range_enabled && s:TextMark.is_available()
6463
endfunction
6564

6665
function! s:request_sync() abort

autoload/vital/_lsp/VS/LSP/TextEdit.vim

Lines changed: 42 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
function! s:_SID() abort
55
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
66
endfunction
7-
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")
7+
execute join(['function! vital#_lsp#VS#LSP#TextEdit#import() abort', printf("return map({'_vital_depends': '', 'apply': '', '_vital_loaded': ''}, \"vital#_lsp#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
88
delfunction s:_SID
99
" ___vital___
1010
"
@@ -23,144 +23,64 @@ function! s:_vital_depends() abort
2323
return ['VS.LSP.Text', 'VS.LSP.Position', 'VS.Vim.Option']
2424
endfunction
2525

26-
"
27-
" Current selected method.
28-
"
29-
let s:_method = 'auto'
30-
31-
"
32-
" This dict contains some logics for patching text.
33-
"
34-
let s:_methods = {}
35-
36-
"
37-
" set_method
38-
"
39-
function! s:set_method(method) abort
40-
if !has_key(s:_methods, a:method)
41-
let s:_method = 'auto'
42-
elseif a:method ==# 'nvim_buf_set_text' && !exists('*nvim_buf_set_text')
43-
let s:_method = 'auto'
44-
elseif a:method ==# 'normal' && has('nvim')
45-
let s:_method = 'auto'
46-
else
47-
let s:_method = a:method
48-
endif
49-
endfunction
50-
51-
"
52-
" get_method
53-
"
54-
function! s:get_method() abort
55-
if s:_method ==# 'auto'
56-
if exists('*nvim_buf_set_text')
57-
return 'nvim_buf_set_text'
58-
elseif !has('nvim')
59-
return 'normal'
60-
else
61-
return 'function'
62-
endif
63-
endif
64-
return s:_method
65-
endfunction
66-
67-
"
68-
" get_methods
69-
"
70-
function! s:get_methods() abort
71-
return ['nvim_buf_set_text', 'normal', 'function']
72-
endfunction
73-
74-
"
75-
" is_text_mark_preserved
76-
"
77-
function! s:is_text_mark_preserved() abort
78-
return index(['nvim_buf_set_text'], s:get_method()) >= 0
79-
endfunction
80-
8126
"
8227
" apply
8328
"
8429
function! s:apply(path, text_edits) abort
8530
let l:current_bufname = bufname('%')
86-
let l:target_bufname = a:path
87-
let l:cursor_position = s:Position.cursor()
31+
let l:current_position = s:Position.cursor()
8832

33+
let l:target_bufnr = s:_switch(a:path)
8934
try
90-
call s:_switch(a:path)
91-
let [l:has_overflowed, l:text_edits] = s:_normalize(bufnr(l:target_bufname), a:text_edits)
92-
let l:fix_cursor = s:_methods[s:get_method()](bufnr(l:target_bufname), l:text_edits, l:cursor_position)
93-
if l:has_overflowed && getline('$') ==# ''
94-
call s:delete(bufnr(l:target_bufname), '$', '$')
95-
endif
96-
call s:_switch(l:current_bufname)
35+
let l:fix_cursor = s:_substitute(l:target_bufnr, a:text_edits, l:current_position)
9736
catch /.*/
9837
call themis#log(string({ 'exception': v:exception, 'throwpoint': v:throwpoint }))
9938
endtry
39+
let l:current_bufnr = s:_switch(l:current_bufname)
10040

101-
if get(l:, 'fix_cursor', v:false) && bufnr(l:current_bufname) == bufnr(l:target_bufname)
102-
call cursor(s:Position.lsp_to_vim('%', l:cursor_position))
41+
if get(l:, 'fix_cursor', v:false) && l:current_bufnr == l:target_bufnr
42+
call cursor(s:Position.lsp_to_vim('%', l:current_position))
10343
endif
10444
endfunction
10545

106-
let s:_methods = {}
107-
108-
"
109-
" nvim_buf_set_text
110-
"
111-
function! s:_methods.nvim_buf_set_text(bufnr, text_edits, cursor_position) abort
112-
let l:fix_cursor = v:false
113-
114-
for l:text_edit in a:text_edits
115-
let l:start = s:Position.lsp_to_vim(a:bufnr, l:text_edit.range.start)
116-
let l:end = s:Position.lsp_to_vim(a:bufnr, l:text_edit.range.end)
117-
let l:lines = s:Text.split_by_eol(l:text_edit.newText)
118-
call nvim_buf_set_text(
119-
\ a:bufnr,
120-
\ l:start[0] - 1,
121-
\ l:start[1] - 1,
122-
\ l:end[0] - 1,
123-
\ l:end[1] - 1,
124-
\ l:lines
125-
\ )
126-
let l:fix_cursor = s:_fix_cursor(a:cursor_position, l:text_edit, l:lines) || l:fix_cursor
127-
endfor
128-
129-
return l:fix_cursor
130-
endfunction
131-
13246
"
133-
" normal
47+
" _substitute
13448
"
135-
function! s:_methods.normal(bufnr, text_edits, cursor_position) abort
49+
function! s:_substitute(bufnr, text_edits, current_position) abort
13650
let l:fix_cursor = v:false
13751

13852
try
53+
" Save state.
13954
let l:Restore = s:Option.define({
14055
\ 'foldenable': '0',
141-
\ 'virtualedit': 'onemore',
142-
\ 'whichwrap': 'h',
143-
\ 'selection': 'exclusive',
14456
\ })
14557
let l:view = winsaveview()
14658
let l:regx = getreg('x')
14759

148-
for l:text_edit in a:text_edits
60+
" Apply substitute.
61+
let [l:fixeol, l:text_edits] = s:_normalize(a:bufnr, a:text_edits)
62+
for l:text_edit in l:text_edits
14963
let l:start = s:Position.lsp_to_vim(a:bufnr, l:text_edit.range.start)
15064
let l:end = s:Position.lsp_to_vim(a:bufnr, l:text_edit.range.end)
151-
if l:start[0] != l:end[0] || l:start[1] != l:end[1]
152-
let l:command = printf('%sG%s|v%sG%s|"_d', l:start[0], l:start[1], l:end[0], l:end[1])
153-
else
154-
let l:command = printf('%sG%s|', l:start[0], l:start[1])
155-
endif
15665
call setreg('x', s:Text.normalize_eol(l:text_edit.newText), 'c')
157-
execute printf('noautocmd keepjumps normal! %s"xP', l:command)
158-
159-
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
66+
execute printf('noautocmd keepjumps %ssubstitute/\%%%sl\%%%sc\zs\_.\{-}\ze\%%%sl\%%%sc/\=getreg("x")/',
67+
\ l:start[0],
68+
\ l:start[0],
69+
\ l:start[1],
70+
\ l:end[0],
71+
\ l:end[1]
72+
\ )
73+
let l:fix_cursor = s:_fix_cursor(a:current_position, l:text_edit, getreg('x', 1, v:true)) || l:fix_cursor
16074
endfor
75+
76+
" Remove last empty line if fixeol enabled.
77+
if l:fixeol && getline('$') == ''
78+
$delete _
79+
endif
16180
catch /.*/
162-
echomsg string({ 'exception': v:exception, 'throwpoint': v:throwpoint })
81+
call themis#log(string({ 'exception': v:exception, 'throwpoint': v:throwpoint }))
16382
finally
83+
" Restore state.
16484
call l:Restore()
16585
call winrestview(l:view)
16686
call setreg('x', l:regx)
@@ -169,50 +89,6 @@ function! s:_methods.normal(bufnr, text_edits, cursor_position) abort
16989
return l:fix_cursor
17090
endfunction
17191

172-
"
173-
" function
174-
"
175-
function! s:_methods.function(bufnr, text_edits, cursor_position) abort
176-
let l:fix_cursor = v:false
177-
178-
for l:text_edit in a:text_edits
179-
let l:start_line = getline(l:text_edit.range.start.line + 1)
180-
let l:end_line = getline(l:text_edit.range.end.line + 1)
181-
let l:before_line = strcharpart(l:start_line, 0, l:text_edit.range.start.character)
182-
let l:after_line = strcharpart(l:end_line, l:text_edit.range.end.character, strchars(l:end_line) - l:text_edit.range.end.character)
183-
184-
" create lines.
185-
let l:lines = s:Text.split_by_eol(l:text_edit.newText)
186-
let l:lines[0] = l:before_line . l:lines[0]
187-
let l:lines[-1] = l:lines[-1] . l:after_line
188-
189-
" save length.
190-
let l:lines_len = len(l:lines)
191-
let l:range_len = (l:text_edit.range.end.line - l:text_edit.range.start.line) + 1
192-
193-
" append or delete lines.
194-
if l:lines_len > l:range_len
195-
call append(l:text_edit.range.end.line, repeat([''], l:lines_len - l:range_len))
196-
elseif l:lines_len < l:range_len
197-
call s:delete(a:bufnr, l:text_edit.range.start.line + l:lines_len, l:text_edit.range.end.line)
198-
endif
199-
200-
" set lines.
201-
let l:i = 0
202-
while l:i < len(l:lines)
203-
let l:lnum = l:text_edit.range.start.line + l:i + 1
204-
if get(getbufline(a:bufnr, l:lnum), 0, v:null) !=# l:lines[l:i]
205-
call setline(l:lnum, l:lines[l:i])
206-
endif
207-
let l:i += 1
208-
endwhile
209-
210-
let l:fix_cursor = s:_fix_cursor(a:cursor_position, l:text_edit, s:Text.split_by_eol(l:text_edit.newText))
211-
endfor
212-
213-
return l:fix_cursor
214-
endfunction
215-
21692
"
21793
" _fix_cursor
21894
"
@@ -240,7 +116,7 @@ endfunction
240116
function! s:_normalize(bufnr, text_edits) abort
241117
let l:text_edits = type(a:text_edits) == type([]) ? a:text_edits : [a:text_edits]
242118
let l:text_edits = s:_range(l:text_edits)
243-
let l:text_edits = sort(copy(l:text_edits), function('s:_compare', [], {}))
119+
let l:text_edits = sort(l:text_edits, function('s:_compare'))
244120
let l:text_edits = s:_check(l:text_edits)
245121
let l:text_edits = reverse(l:text_edits)
246122
return s:_fix_text_edits(a:bufnr, l:text_edits)
@@ -250,15 +126,20 @@ endfunction
250126
" _range
251127
"
252128
function! s:_range(text_edits) abort
129+
let l:text_edits = []
253130
for l:text_edit in a:text_edits
131+
if type(l:text_edit) != type({})
132+
continue
133+
endif
254134
if l:text_edit.range.start.line > l:text_edit.range.end.line || (
255135
\ l:text_edit.range.start.line == l:text_edit.range.end.line &&
256136
\ l:text_edit.range.start.character > l:text_edit.range.end.character
257137
\ )
258138
let l:text_edit.range = { 'start': l:text_edit.range.end, 'end': l:text_edit.range.start }
259139
endif
140+
let l:text_edits += [l:text_edit]
260141
endfor
261-
return a:text_edits
142+
return l:text_edits
262143
endfunction
263144

264145
"
@@ -298,49 +179,35 @@ function! s:_fix_text_edits(bufnr, text_edits) abort
298179
let l:buf = getbufline(a:bufnr, '^', '$')
299180
let l:max = len(l:buf)
300181

301-
let l:has_overflowed = v:false
182+
let l:fixeol = v:false
302183
let l:text_edits = []
303184
for l:text_edit in a:text_edits
304185
if l:max <= l:text_edit.range.start.line
305186
let l:text_edit.range.start.line = l:max - 1
306187
let l:text_edit.range.start.character = strchars(get(l:buf, -1, 0))
307188
let l:text_edit.newText = "\n" . l:text_edit.newText
308-
let l:has_overflowed = v:true
189+
let l:fixeol = &fixendofline && !&binary
309190
endif
310191
if l:max <= l:text_edit.range.end.line
311192
let l:text_edit.range.end.line = l:max - 1
312193
let l:text_edit.range.end.character = strchars(get(l:buf, -1, 0))
313-
let l:has_overflowed = v:true
194+
let l:fixeol = &fixendofline && !&binary
314195
endif
315196
call add(l:text_edits, l:text_edit)
316197
endfor
317198

318-
return [l:has_overflowed, l:text_edits]
199+
return [l:fixeol, l:text_edits]
319200
endfunction
320201

321202
"
322203
" _switch
323204
"
324205
function! s:_switch(path) abort
325206
if bufnr(a:path) >= 0
326-
execute printf('keepalt keepjumps %sbuffer!', bufnr(a:path))
207+
execute printf('noautocmd keepalt keepjumps %sbuffer!', bufnr(a:path))
327208
else
328-
execute printf('keepalt keepjumps edit! %s', fnameescape(a:path))
209+
execute printf('noautocmd keepalt keepjumps edit! %s', fnameescape(a:path))
329210
endif
211+
return bufnr('%')
330212
endfunction
331213

332-
"
333-
" delete
334-
"
335-
function! s:delete(bufnr, start, end) abort
336-
if exists('*deletebufline')
337-
call deletebufline(a:bufnr, a:start, a:end)
338-
else
339-
try
340-
let l:Restore = s:Option.define({ 'foldenable': '0' })
341-
execute printf('%s,%sdelete _', a:start, a:end)
342-
finally
343-
call l:Restore()
344-
endtry
345-
endif
346-
endfunction

doc/vim-lsp.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -687,8 +687,6 @@ g:lsp_linked_editing_enabled *g:lsp_linked_editing_enabled*
687687

688688
Enable textDocument/linkedEditingRange feature.
689689

690-
NOTE: This only works on the environment has `nvim_buf_set_text` for now.
691-
692690
Example: >
693691
let g:lsp_linked_editing_enabled = 1
694692
let g:lsp_linked_editing_enabled = 0

0 commit comments

Comments
 (0)