35
35
36
36
--- Grabbed from vim.lsp.utils. Converts an offset_encoding to byte offset
37
37
--- @param position lsp.Position
38
- --- @param offset_encoding string | nil utf-8| utf-16 | utf-32
38
+ --- @param offset_encoding ? ' utf-8' | ' utf-16' | ' utf-32'
39
39
--- @return integer
40
40
local function get_line_byte_from_position (position , offset_encoding )
41
41
local bufnr = vim .api .nvim_get_current_buf ()
42
- -- LSP's line and characters are 0-indexed
43
- -- Vim's line and columns are 1-indexed
44
42
local col = position .character
45
- -- When on the first character, we can ignore the difference between byte and
46
- -- character
47
- if col > 0 then
48
- local line = vim . api . nvim_buf_get_lines ( bufnr , position . line , position . line + 1 , true )[ 1 ] or ' '
49
- if vim .fn . has ( ' nvim-0.11.0 ' ) == 1 then
50
- return vim .str_byteindex ( line , offset_encoding or ' utf-16 ' , col , false )
51
- else
52
- return vim . lsp . util . _str_byteindex_enc ( line , col , offset_encoding or ' utf-16 ' )
53
- end
43
+
44
+ -- When on the first character, we can ignore the difference between byte and character
45
+ if col == 0 then return 0 end
46
+
47
+ local line = vim .api . nvim_buf_get_lines ( bufnr , position . line , position . line + 1 , false )[ 1 ] or ' '
48
+ if vim .fn . has ( ' nvim-0.11.0 ' ) == 1 then
49
+ col = vim . str_byteindex ( line , offset_encoding or ' utf-16 ' , col , false )
50
+ else
51
+ col = vim . lsp . util . _str_byteindex_enc ( line , col , offset_encoding or ' utf-16 ' )
54
52
end
55
- return col
53
+ return math.min ( col , # line )
56
54
end
57
55
58
56
--- Gets the text edit from an item, handling insert/replace ranges and converts
@@ -67,7 +65,7 @@ function text_edits.get_from_item(item)
67
65
text_edit = {
68
66
newText = item .textEditText or item .insertText or item .label ,
69
67
-- FIXME: temporarily convert insertReplaceEdit to regular textEdit
70
- range = item .editRange .insert or item .editRange .replace or item .editRange ,
68
+ range = vim . deepcopy ( item .editRange .insert or item .editRange .replace or item .editRange ) ,
71
69
}
72
70
end
73
71
@@ -83,19 +81,22 @@ function text_edits.get_from_item(item)
83
81
local client = vim .lsp .get_client_by_id (item .client_id )
84
82
local offset_encoding = client ~= nil and client .offset_encoding or ' utf-8'
85
83
86
- -- convert the offset encoding to utf-8 if necessary
87
- if offset_encoding ~= ' utf-8' then
88
- text_edit .range .start .character = get_line_byte_from_position (text_edit .range .start , offset_encoding )
89
- text_edit .range [' end' ].character = get_line_byte_from_position (text_edit .range [' end' ], offset_encoding )
90
- end
91
-
92
84
-- Adjust the position of the text edit to be the current cursor position
93
85
-- since the data might be outdated. We compare the cursor column position
94
86
-- from when the items were fetched versus the current.
95
87
-- HACK: is there a better way?
96
88
-- TODO: take into account the offset_encoding
97
89
local offset = vim .api .nvim_win_get_cursor (0 )[2 ] - item .cursor_column
98
90
text_edit .range [' end' ].character = text_edit .range [' end' ].character + offset
91
+
92
+ -- convert the offset encoding to utf-8 if necessary
93
+ -- TODO: we have to do this last because it applies a max on the position based on the length of the line
94
+ -- so it would break the offset code when removing characters at the end of the line
95
+ if offset_encoding ~= ' utf-8' then
96
+ text_edit .range .start .character = get_line_byte_from_position (text_edit .range .start , offset_encoding )
97
+ text_edit .range [' end' ].character = get_line_byte_from_position (text_edit .range [' end' ], offset_encoding )
98
+ end
99
+
99
100
return text_edit
100
101
end
101
102
0 commit comments