Skip to content

Commit d3c3732

Browse files
committed
fix(suggestion): weird indentation after .accept
1 parent 2c04d3b commit d3c3732

1 file changed

Lines changed: 31 additions & 63 deletions

File tree

lua/copilot/suggestion.lua

Lines changed: 31 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -122,69 +122,49 @@ local function cancel_inflight_requests()
122122
end)
123123
end
124124

125-
---@return string text
126-
---@return integer outdent
127-
---@return integer delete
128-
---@return string uuid
129-
local function suggestion_text_with_adjustments()
130-
local ok, text, outdent, delete, uuid = pcall(function()
125+
local function clear_preview()
126+
vim.api.nvim_buf_del_extmark(0, copilot.ns_id, copilot.extmark_id)
127+
end
128+
129+
local function get_current_suggestion()
130+
local ok, choice = pcall(function()
131131
if
132132
not vim.fn.mode():match("^[iR]")
133133
or vim.fn.pumvisible() == 1
134134
or vim.b.copilot_suggestion_hidden
135135
or not copilot._copilot.suggestions
136136
or #copilot._copilot.suggestions == 0
137137
then
138-
return "", 0, 0, ""
138+
return nil
139139
end
140140

141141
local choice = copilot._copilot.suggestions[copilot._copilot.choice]
142142
if not choice or not choice.range or choice.range.start.line ~= vim.fn.line(".") - 1 then
143-
return "", 0, 0, ""
143+
return nil
144144
end
145145

146146
if choice.range.start.character ~= 0 then
147147
-- unexpected range
148-
return "", 0, 0, ""
148+
return nil
149149
end
150150

151-
local line = vim.fn.getline(".")
152-
local offset = vim.fn.col(".") - 1
153-
154-
local typed = vim.fn.strpart(line, 0, offset)
155-
local delete = vim.fn.strpart(line, offset)
156-
157-
local uuid = choice.uuid or ""
158-
159-
if typed:match("^%s*$") then
160-
local leading = vim.fn.matchstr(choice.text, "^s+")
161-
local unindented = vim.fn.strpart(choice.text, #leading)
162-
if vim.fn.strpart(typed, 0, #leading) == leading or unindented ~= delete then
163-
return unindented, #typed - #leading, vim.fn.strchars(delete), uuid
164-
end
165-
else
166-
return vim.fn.strpart(choice.text, offset), 0, vim.fn.strchars(delete), uuid
167-
end
151+
return choice
168152
end)
169153

170154
if ok then
171-
return text, outdent, delete, uuid
155+
return choice
172156
end
173157

174-
return "", 0, 0, ""
175-
end
176-
177-
local function clear_preview()
178-
vim.api.nvim_buf_del_extmark(0, copilot.ns_id, copilot.extmark_id)
158+
return nil
179159
end
180160

181161
local function update_preview()
182-
local text, _, delete, uuid = suggestion_text_with_adjustments()
183-
text = vim.split(text, "\n", { plain = true, trimempty = true })
162+
local suggestion = get_current_suggestion()
163+
local displayLines = suggestion and vim.split(suggestion.displayText, "\n", { plain = true }) or {}
184164

185165
clear_preview()
186166

187-
if #text == 0 then
167+
if not suggestion or #displayLines == 0 then
188168
return
189169
end
190170

@@ -200,16 +180,16 @@ local function update_preview()
200180
local extmark = {
201181
id = copilot.extmark_id,
202182
virt_text_win_col = vim.fn.virtcol(".") - 1,
203-
virt_text = { { text[1] .. string.rep(" ", delete - #text[1]), hl_group.CopilotSuggestion } },
183+
virt_text = { { displayLines[1], hl_group.CopilotSuggestion } },
204184
}
205185

206-
if #text > 1 then
186+
if #displayLines > 1 then
207187
extmark.virt_lines = {}
208-
for i = 2, #text do
209-
extmark.virt_lines[i - 1] = { { text[i], hl_group.CopilotSuggestion } }
188+
for i = 2, #displayLines do
189+
extmark.virt_lines[i - 1] = { { displayLines[i], hl_group.CopilotSuggestion } }
210190
end
211191
if #annot > 0 then
212-
extmark.virt_lines[#text] = { { " " }, { annot, hl_group.CopilotAnnotation } }
192+
extmark.virt_lines[#displayLines] = { { " " }, { annot, hl_group.CopilotAnnotation } }
213193
end
214194
elseif #annot > 0 then
215195
extmark.virt_text[2] = { " " }
@@ -220,10 +200,10 @@ local function update_preview()
220200

221201
vim.api.nvim_buf_set_extmark(0, copilot.ns_id, vim.fn.line(".") - 1, vim.fn.col(".") - 1, extmark)
222202

223-
if uuid ~= copilot.uuid then
224-
copilot.uuid = uuid
203+
if suggestion.uuid ~= copilot.uuid then
204+
copilot.uuid = suggestion.uuid
225205
with_client(function(client)
226-
api.notify_shown(client, { uuid = uuid }, function() end)
206+
api.notify_shown(client, { uuid = suggestion.uuid }, function() end)
227207
end)
228208
end
229209
end
@@ -368,33 +348,21 @@ function mod.prev()
368348
end)
369349
end
370350

371-
local function get_displayed_suggestion()
372-
local text, outdent, delete, uuid = suggestion_text_with_adjustments()
373-
return {
374-
uuid = uuid,
375-
text = text,
376-
outdent_size = outdent,
377-
delete_size = delete,
378-
}
379-
end
380-
381351
function mod.accept()
382-
local s = get_displayed_suggestion()
383-
if vim.fn.empty(s.text) == 0 then
352+
local suggestion = get_current_suggestion()
353+
if suggestion and vim.fn.empty(suggestion.text) == 0 then
384354
reset_state()
385355
with_client(function(client)
386-
api.notify_accepted(client, { uuid = s.uuid }, function() end)
356+
api.notify_accepted(client, { uuid = suggestion.uuid }, function() end)
387357
end)
388358
copilot.uuid = nil
389359
clear_preview()
390360

391-
local keys = vim.api.nvim_replace_termcodes(
392-
string.rep("<Left><Del>", s.outdent_size) .. string.rep("<Del>", s.delete_size),
393-
true,
394-
false,
395-
true
396-
) or ""
397-
vim.api.nvim_feedkeys(keys .. s.text, "n", false)
361+
-- Hack for 'autoindent', makes the indent persist. Check `:help 'autoindent'`.
362+
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<Space><Left><Del>", true, false, true), "n", false)
363+
vim.lsp.util.apply_text_edits({ { range = suggestion.range, newText = suggestion.text } }, 0, "utf-16")
364+
-- Put cursor at the end of current line.
365+
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<C-O>$", true, false, true), "n", false)
398366
end
399367
end
400368

0 commit comments

Comments
 (0)