Skip to content

Commit 028fc35

Browse files
authored
feat!(nes): split walk and apply keys for composability (#17)
1 parent d3ee0f1 commit 028fc35

11 files changed

+252
-72
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@ return {
2828
vim.g.copilot_nes_debounce = 500
2929
vim.lsp.enable("copilot")
3030
vim.keymap.set("n", "<tab>", function()
31-
require("copilot-lsp.nes").apply_pending_nes()
31+
-- Try to jump to the start of the suggestion edit.
32+
-- If already at the start, then apply the pending suggestion and jump to the end of the edit.
33+
local _ = require("copilot-lsp.nes").walk_cursor_start_edit()
34+
or (
35+
require("copilot-lsp.nes").apply_pending_nes() and require("copilot-lsp.nes").walk_cursor_end_edit()
36+
)
3237
end)
3338
end,
3439
}
@@ -44,7 +49,10 @@ return {
4449
function(cmp)
4550
if vim.b[vim.api.nvim_get_current_buf()].nes_state then
4651
cmp.hide()
47-
return require("copilot-lsp.nes").apply_pending_nes()
52+
return (
53+
require("copilot-lsp.nes").apply_pending_nes()
54+
and require("copilot-lsp.nes").walk_cursor_end_edit()
55+
)
4856
end
4957
if cmp.snippet_active() then
5058
return cmp.accept()

lua/copilot-lsp/nes/init.lua

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ local function handle_nes_response(err, result)
2020
nes_ui._display_next_suggestion(result.edits, nes_ns)
2121
end
2222

23+
--- Requests the NextEditSuggestion from the current cursor position
2324
---@param copilot_lss vim.lsp.Client?
2425
function M.request_nes(copilot_lss)
2526
local pos_params = vim.lsp.util.make_position_params(0, "utf-16")
@@ -30,35 +31,80 @@ function M.request_nes(copilot_lss)
3031
copilot_lss:request("textDocument/copilotInlineEdit", pos_params, handle_nes_response)
3132
end
3233

34+
--- Walks the cursor to the start of the edit.
35+
--- This function returns false if there is no edit to apply or if the cursor is already at the start position of the
36+
--- edit.
3337
---@param bufnr? integer
34-
---@return boolean
35-
function M.apply_pending_nes(bufnr)
38+
---@return boolean --if the cursor walked
39+
function M.walk_cursor_start_edit(bufnr)
3640
bufnr = bufnr and bufnr > 0 and bufnr or vim.api.nvim_get_current_buf()
37-
3841
---@type copilotlsp.InlineEdit
3942
local state = vim.b[bufnr].nes_state
4043
if not state then
4144
return false
4245
end
43-
vim.schedule(function()
44-
local prev_mode = vim.api.nvim_get_mode().mode
45-
if prev_mode == "i" then
46-
vim.cmd("stopinsert!")
47-
end
46+
47+
local cursor_row, _ = unpack(vim.api.nvim_win_get_cursor(0))
48+
if cursor_row - 1 ~= state.range.start.line then
49+
vim.b[bufnr].nes_jump = true
4850
---@type lsp.Location
49-
local jump_loc = {
51+
local jump_loc_before = {
5052
uri = state.textDocument.uri,
5153
range = {
52-
start = state.range["end"],
53-
["end"] = state.range["end"],
54+
start = state.range["start"],
55+
["end"] = state.range["start"],
5456
},
5557
}
56-
vim.lsp.util.show_document(jump_loc, "utf-16", { focus = true })
58+
return vim.lsp.util.show_document(jump_loc_before, "utf-16", { focus = true })
59+
else
60+
return false
61+
end
62+
end
63+
64+
--- Walks the cursor to the end of the edit.
65+
--- This function returns false if there is no edit to apply or if the cursor is already at the end position of the
66+
--- edit
67+
---@param bufnr? integer
68+
---@return boolean --if the cursor walked
69+
function M.walk_cursor_end_edit(bufnr)
70+
bufnr = bufnr and bufnr > 0 and bufnr or vim.api.nvim_get_current_buf()
71+
---@type copilotlsp.InlineEdit
72+
local state = vim.b[bufnr].nes_state
73+
if not state then
74+
return false
75+
end
76+
77+
---@type lsp.Location
78+
local jump_loc_after = {
79+
uri = state.textDocument.uri,
80+
range = {
81+
start = state.range["end"],
82+
["end"] = state.range["end"],
83+
},
84+
}
85+
--NOTE: If last line is deletion, then this may be outside of the buffer
86+
vim.schedule(function()
87+
pcall(vim.lsp.util.show_document, jump_loc_after, "utf-16", { focus = true })
88+
end)
89+
return true
90+
end
91+
92+
--- This function applies the pending nes edit to the current buffer and then clears the marks for the pending
93+
--- suggestion
94+
---@param bufnr? integer
95+
---@return boolean --if the nes was applied
96+
function M.apply_pending_nes(bufnr)
97+
bufnr = bufnr and bufnr > 0 and bufnr or vim.api.nvim_get_current_buf()
98+
99+
---@type copilotlsp.InlineEdit
100+
local state = vim.b[bufnr].nes_state
101+
if not state then
102+
return false
103+
end
104+
vim.schedule(function()
57105
utils.apply_inline_edit(state)
106+
vim.b[bufnr].nes_jump = false
58107
nes_ui.clear_suggestion(bufnr, nes_ns)
59-
if prev_mode == "i" then
60-
vim.cmd("startinsert")
61-
end
62108
end)
63109
return true
64110
end

lua/copilot-lsp/nes/ui.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ end
1010
---@param ns_id integer
1111
function M.clear_suggestion(bufnr, ns_id)
1212
bufnr = bufnr and bufnr > 0 and bufnr or vim.api.nvim_get_current_buf()
13+
if vim.b[bufnr].nes_jump then
14+
vim.b[bufnr].nes_jump = false
15+
return
16+
end
1317
vim.api.nvim_buf_clear_namespace(bufnr, ns_id, 0, -1)
1418
---@type copilotlsp.InlineEdit
1519
local state = vim.b[bufnr].nes_state

tests/mock_lsp.lua

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,15 @@ local function getNesResponse(td)
8585
},
8686
}
8787
local response = responses[filename]
88+
8889
assert(response, "unhandled doc")
8990
return response
9091
end
9192

9293
function M.server()
9394
local closing = false
9495
local srv = {}
96+
local seen_files = {}
9597

9698
function srv.request(method, params, handler)
9799
table.insert(M.messages, { method = method, params = params })
@@ -102,8 +104,17 @@ function M.server()
102104
elseif method == "shutdown" then
103105
handler(nil, nil)
104106
elseif method == "textDocument/copilotInlineEdit" then
105-
local response = getNesResponse(params.textDocument)
106-
handler(nil, response)
107+
if not seen_files[params.textDocument.uri] then
108+
seen_files[params.textDocument.uri] = true
109+
local response = getNesResponse(params.textDocument)
110+
handler(nil, response)
111+
return
112+
end
113+
---@type copilotlsp.copilotInlineEditResponse
114+
local empty_response = {
115+
edits = {},
116+
}
117+
handler(nil, empty_response)
107118
else
108119
assert(false, "Unhandled method: " .. method)
109120
end

tests/nes/test_nes.lua

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ T["nes"]["same line edit"] = function()
3535
vim.uv.sleep(500)
3636
ref(child.get_screenshot())
3737
child.lua_func(function()
38-
require("copilot-lsp.nes").apply_pending_nes(0)
38+
local _ = require("copilot-lsp.nes").apply_pending_nes() and require("copilot-lsp.nes").walk_cursor_end_edit()
3939
end)
4040
ref(child.get_screenshot())
4141
end
@@ -55,7 +55,7 @@ T["nes"]["multi line edit"] = function()
5555
vim.uv.sleep(500)
5656
ref(child.get_screenshot())
5757
child.lua_func(function()
58-
require("copilot-lsp.nes").apply_pending_nes(0)
58+
local _ = require("copilot-lsp.nes").apply_pending_nes() and require("copilot-lsp.nes").walk_cursor_end_edit()
5959
end)
6060
ref(child.get_screenshot())
6161
end
@@ -75,7 +75,11 @@ T["nes"]["removal edit"] = function()
7575
vim.uv.sleep(500)
7676
ref(child.get_screenshot())
7777
child.lua_func(function()
78-
require("copilot-lsp.nes").apply_pending_nes(0)
78+
require("copilot-lsp.nes").walk_cursor_start_edit()
79+
end)
80+
ref(child.get_screenshot())
81+
child.lua_func(function()
82+
local _ = require("copilot-lsp.nes").apply_pending_nes() and require("copilot-lsp.nes").walk_cursor_end_edit()
7983
end)
8084
ref(child.get_screenshot())
8185
end
@@ -95,7 +99,12 @@ T["nes"]["add only edit"] = function()
9599
vim.uv.sleep(500)
96100
ref(child.get_screenshot())
97101
child.lua_func(function()
98-
require("copilot-lsp.nes").apply_pending_nes(0)
102+
require("copilot-lsp.nes").walk_cursor_start_edit()
103+
end)
104+
vim.uv.sleep(100)
105+
ref(child.get_screenshot())
106+
child.lua_func(function()
107+
local _ = require("copilot-lsp.nes").apply_pending_nes() and require("copilot-lsp.nes").walk_cursor_end_edit()
99108
end)
100109
ref(child.get_screenshot())
101110
end
@@ -121,7 +130,7 @@ T["nes"]["highlights replacement"] = function()
121130
vim.uv.sleep(500)
122131
ref(child.get_screenshot())
123132
child.lua_func(function()
124-
require("copilot-lsp.nes").apply_pending_nes(0)
133+
local _ = require("copilot-lsp.nes").apply_pending_nes() and require("copilot-lsp.nes").walk_cursor_end_edit()
125134
end)
126135
ref(child.get_screenshot())
127136
end

tests/screenshots/tests-nes-test_nes.lua---nes---add-only-edit-003

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,31 +21,31 @@
2121
20|~
2222
21|~
2323
22|~
24-
23|tests/fixtures/addonly_edit.txt [+] 4,1 All
24+
23|tests/fixtures/addonly_edit.txt 3,1 All
2525
24|
2626

2727
--|---------|---------|---------|---------|---------|---------|---------|---------|
2828
01|00000000000000000000000000000000000000000000000000000000000000000000000000000000
2929
02|00000000000000000000000000000000000000000000000000000000000000000000000000000000
30-
03|00000000000000000000000000000000000000000000000000000000000000000000000000000000
30+
03|11111100000000000000000000000000000000000000000000000000000000000000000000000000
3131
04|00000000000000000000000000000000000000000000000000000000000000000000000000000000
32-
05|11111111111111111111111111111111111111111111111111111111111111111111111111111111
33-
06|11111111111111111111111111111111111111111111111111111111111111111111111111111111
34-
07|11111111111111111111111111111111111111111111111111111111111111111111111111111111
35-
08|11111111111111111111111111111111111111111111111111111111111111111111111111111111
36-
09|11111111111111111111111111111111111111111111111111111111111111111111111111111111
37-
10|11111111111111111111111111111111111111111111111111111111111111111111111111111111
38-
11|11111111111111111111111111111111111111111111111111111111111111111111111111111111
39-
12|11111111111111111111111111111111111111111111111111111111111111111111111111111111
40-
13|11111111111111111111111111111111111111111111111111111111111111111111111111111111
41-
14|11111111111111111111111111111111111111111111111111111111111111111111111111111111
42-
15|11111111111111111111111111111111111111111111111111111111111111111111111111111111
43-
16|11111111111111111111111111111111111111111111111111111111111111111111111111111111
44-
17|11111111111111111111111111111111111111111111111111111111111111111111111111111111
45-
18|11111111111111111111111111111111111111111111111111111111111111111111111111111111
46-
19|11111111111111111111111111111111111111111111111111111111111111111111111111111111
47-
20|11111111111111111111111111111111111111111111111111111111111111111111111111111111
48-
21|11111111111111111111111111111111111111111111111111111111111111111111111111111111
49-
22|11111111111111111111111111111111111111111111111111111111111111111111111111111111
50-
23|22222222222222222222222222222222222222222222222222222222222222222222222222222222
32+
05|22222222222222222222222222222222222222222222222222222222222222222222222222222222
33+
06|22222222222222222222222222222222222222222222222222222222222222222222222222222222
34+
07|22222222222222222222222222222222222222222222222222222222222222222222222222222222
35+
08|22222222222222222222222222222222222222222222222222222222222222222222222222222222
36+
09|22222222222222222222222222222222222222222222222222222222222222222222222222222222
37+
10|22222222222222222222222222222222222222222222222222222222222222222222222222222222
38+
11|22222222222222222222222222222222222222222222222222222222222222222222222222222222
39+
12|22222222222222222222222222222222222222222222222222222222222222222222222222222222
40+
13|22222222222222222222222222222222222222222222222222222222222222222222222222222222
41+
14|22222222222222222222222222222222222222222222222222222222222222222222222222222222
42+
15|22222222222222222222222222222222222222222222222222222222222222222222222222222222
43+
16|22222222222222222222222222222222222222222222222222222222222222222222222222222222
44+
17|22222222222222222222222222222222222222222222222222222222222222222222222222222222
45+
18|22222222222222222222222222222222222222222222222222222222222222222222222222222222
46+
19|22222222222222222222222222222222222222222222222222222222222222222222222222222222
47+
20|22222222222222222222222222222222222222222222222222222222222222222222222222222222
48+
21|22222222222222222222222222222222222222222222222222222222222222222222222222222222
49+
22|22222222222222222222222222222222222222222222222222222222222222222222222222222222
50+
23|33333333333333333333333333333333333333333333333333333333333333333333333333333333
5151
24|00000000000000000000000000000000000000000000000000000000000000000000000000000000
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
--|---------|---------|---------|---------|---------|---------|---------|---------|
2+
01|1 line
3+
02|2 line
4+
03|line 3
5+
04|4 line
6+
05|~
7+
06|~
8+
07|~
9+
08|~
10+
09|~
11+
10|~
12+
11|~
13+
12|~
14+
13|~
15+
14|~
16+
15|~
17+
16|~
18+
17|~
19+
18|~
20+
19|~
21+
20|~
22+
21|~
23+
22|~
24+
23|tests/fixtures/addonly_edit.txt [+] 3,1 All
25+
24|
26+
27+
--|---------|---------|---------|---------|---------|---------|---------|---------|
28+
01|00000000000000000000000000000000000000000000000000000000000000000000000000000000
29+
02|00000000000000000000000000000000000000000000000000000000000000000000000000000000
30+
03|00000000000000000000000000000000000000000000000000000000000000000000000000000000
31+
04|00000000000000000000000000000000000000000000000000000000000000000000000000000000
32+
05|11111111111111111111111111111111111111111111111111111111111111111111111111111111
33+
06|11111111111111111111111111111111111111111111111111111111111111111111111111111111
34+
07|11111111111111111111111111111111111111111111111111111111111111111111111111111111
35+
08|11111111111111111111111111111111111111111111111111111111111111111111111111111111
36+
09|11111111111111111111111111111111111111111111111111111111111111111111111111111111
37+
10|11111111111111111111111111111111111111111111111111111111111111111111111111111111
38+
11|11111111111111111111111111111111111111111111111111111111111111111111111111111111
39+
12|11111111111111111111111111111111111111111111111111111111111111111111111111111111
40+
13|11111111111111111111111111111111111111111111111111111111111111111111111111111111
41+
14|11111111111111111111111111111111111111111111111111111111111111111111111111111111
42+
15|11111111111111111111111111111111111111111111111111111111111111111111111111111111
43+
16|11111111111111111111111111111111111111111111111111111111111111111111111111111111
44+
17|11111111111111111111111111111111111111111111111111111111111111111111111111111111
45+
18|11111111111111111111111111111111111111111111111111111111111111111111111111111111
46+
19|11111111111111111111111111111111111111111111111111111111111111111111111111111111
47+
20|11111111111111111111111111111111111111111111111111111111111111111111111111111111
48+
21|11111111111111111111111111111111111111111111111111111111111111111111111111111111
49+
22|11111111111111111111111111111111111111111111111111111111111111111111111111111111
50+
23|22222222222222222222222222222222222222222222222222222222222222222222222222222222
51+
24|00000000000000000000000000000000000000000000000000000000000000000000000000000000

tests/screenshots/tests-nes-test_nes.lua---nes---highlights-replacement-003

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
20|~
2222
21|~
2323
22|~
24-
23|tests/fixtures/highlight_test.c [+] 5,32 All
24+
23|tests/fixtures/highlight_test.c [+] 5,31 All
2525
24|
2626

2727
--|---------|---------|---------|---------|---------|---------|---------|---------|

tests/screenshots/tests-nes-test_nes.lua---nes---multi-line-edit-003

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
20|~
2222
21|~
2323
22|~
24-
23|tests/fixtures/multiline_edit.txt [+] 2,8 All
24+
23|tests/fixtures/multiline_edit.txt [+] 2,9 All
2525
24|
2626

2727
--|---------|---------|---------|---------|---------|---------|---------|---------|

0 commit comments

Comments
 (0)