Skip to content

Commit aa9e451

Browse files
committed
Copilot.vim 1.4.0
1 parent 042543f commit aa9e451

File tree

6 files changed

+158
-22
lines changed

6 files changed

+158
-22
lines changed

autoload/copilot.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ function! copilot#Init(...) abort
5050
endfunction
5151

5252
function! s:Start() abort
53-
if exists('s:agent.job')
53+
if exists('s:agent.job') || exists('s:agent.client_id')
5454
return
5555
endif
5656
let s:agent = copilot#agent#New({'notifications': {

autoload/copilot/agent.vim

Lines changed: 93 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ let g:autoloaded_copilot_agent = 1
55

66
scriptencoding utf-8
77

8-
let s:plugin_version = '1.3.5'
8+
let s:plugin_version = '1.4.0'
99

1010
let s:error_exit = -1
1111

@@ -15,6 +15,11 @@ if !exists('s:instances')
1515
let s:instances = {}
1616
endif
1717

18+
" allow sourcing this file to reload the Lua file too
19+
if has('nvim')
20+
lua package.loaded._copilot = nil
21+
endif
22+
1823
let s:jobstop = function(exists('*jobstop') ? 'jobstop' : 'job_stop')
1924
function! s:Kill(agent, ...) abort
2025
if has_key(a:agent, 'job')
@@ -49,7 +54,8 @@ function! s:Send(agent, request) abort
4954
endfunction
5055

5156
function! s:AgentNotify(method, params) dict abort
52-
return s:Send(self, {'method': a:method, 'params': a:params})
57+
call s:Send(self, {'method': a:method, 'params': a:params})
58+
return v:true
5359
endfunction
5460

5561
function! s:RequestWait() dict abort
@@ -77,20 +83,21 @@ endfunction
7783
if !exists('s:id')
7884
let s:id = 0
7985
endif
80-
function! s:AgentRequest(method, params, ...) dict abort
81-
let s:id += 1
82-
let request = {'method': a:method, 'params': a:params, 'id': s:id}
83-
call s:Send(self, request)
84-
call extend(request, {
85-
\ 'agent_id': self.id,
86+
87+
function s:SetUpRequest(agent, id, method, params, ...) abort
88+
let request = {
89+
\ 'agent_id': a:agent.id,
90+
\ 'id': a:id,
91+
\ 'method': a:method,
92+
\ 'params': a:params,
8693
\ 'Agent': function('s:RequestAgent'),
8794
\ 'Wait': function('s:RequestWait'),
8895
\ 'Await': function('s:RequestAwait'),
8996
\ 'Cancel': function('s:RequestCancel'),
9097
\ 'resolve': [],
9198
\ 'reject': [],
92-
\ 'status': 'running'})
93-
let self.requests[s:id] = request
99+
\ 'status': 'running'}
100+
let a:agent.requests[a:id] = request
94101
let args = a:000[2:-1]
95102
if len(args)
96103
if !empty(a:1)
@@ -110,6 +117,13 @@ function! s:AgentRequest(method, params, ...) dict abort
110117
return request
111118
endfunction
112119

120+
function! s:AgentRequest(method, params, ...) dict abort
121+
let s:id += 1
122+
let request = {'method': a:method, 'params': a:params, 'id': s:id}
123+
call s:Send(self, request)
124+
return call('s:SetUpRequest', [self, s:id, a:method, a:params] + a:000)
125+
endfunction
126+
113127
function! s:AgentCall(method, params, ...) dict abort
114128
let request = call(self.Request, [a:method, a:params] + a:000)
115129
if a:0
@@ -160,7 +174,11 @@ function! s:OnMessage(agent, body, ...) abort
160174
if type(response) != v:t_dict
161175
return
162176
endif
177+
return s:OnResponse(a:agent, response)
178+
endfunction
163179

180+
function! s:OnResponse(agent, response, ...) abort
181+
let response = a:response
164182
let id = get(response, 'id', v:null)
165183
if has_key(response, 'method')
166184
let params = get(response, 'params', v:null)
@@ -241,7 +259,7 @@ endfunction
241259

242260
function! s:OnExit(agent, code) abort
243261
let a:agent.exit_status = a:code
244-
call remove(a:agent, 'job')
262+
unlet! a:agent.job
245263
for id in sort(keys(a:agent.requests), { a, b -> +a > +b })
246264
let request = remove(a:agent.requests, id)
247265
if request.status ==# 'canceled'
@@ -261,6 +279,53 @@ function! s:OnExit(agent, code) abort
261279
call copilot#logger#Info('agent exited with status ' . a:code)
262280
endfunction
263281

282+
function! copilot#agent#LspInit(agent_id, initialize_result) abort
283+
if !has_key(s:instances, a:agent_id)
284+
return
285+
endif
286+
let instance = s:instances[a:agent_id]
287+
call s:GetCapabilitiesResult(a:initialize_result, instance)
288+
endfunction
289+
290+
function! copilot#agent#LspExit(agent_id, code, signal) abort
291+
if !has_key(s:instances, a:agent_id)
292+
return
293+
endif
294+
let instance = remove(s:instances, a:agent_id)
295+
unlet! instance.client_id
296+
call s:OnExit(instance, a:code)
297+
endfunction
298+
299+
function! copilot#agent#LspResponse(agent_id, opts, ...) abort
300+
if !has_key(s:instances, a:agent_id)
301+
return
302+
endif
303+
call s:OnResponse(s:instances[a:agent_id], a:opts)
304+
endfunction
305+
306+
function! s:LspRequest(method, params, ...) dict abort
307+
let id = v:lua.require'_copilot'.lsp_request(self.id, a:method, a:params)
308+
return call('s:SetUpRequest', [self, id, a:method, a:params] + a:000)
309+
endfunction
310+
311+
function! s:LspClose() dict abort
312+
if !has_key(self, 'client_id')
313+
return
314+
endif
315+
return luaeval('vim.lsp.get_client_by_id(_A).stop()', self.client_id)
316+
endfunction
317+
318+
function! s:LspNotify(method, params) dict abort
319+
return v:lua.require'_copilot'.rpc_notify(self.id, a:method, a:params)
320+
endfunction
321+
322+
function copilot#agent#LspHandle(agent_id, response) abort
323+
if !has_key(s:instances, a:agent_id)
324+
return
325+
endif
326+
call s:OnResponse(s:instances[a:agent_id], a:response)
327+
endfunction
328+
264329
unlet! s:is_arm_macos
265330
function! s:IsArmMacOS() abort
266331
if exists('s:is_arm_macos')
@@ -351,7 +416,7 @@ function! s:AgentStartupError() dict abort
351416
while has_key(self, 'job') && !has_key(self, 'startup_error') && !has_key(self, 'capabilities')
352417
sleep 10m
353418
endwhile
354-
if has_key(self, 'capabilities')
419+
if has_key(self, 'capabilities') || has_key(self, 'client_id')
355420
return ''
356421
else
357422
return get(self, 'startup_error', 'Something unexpected went wrong spawning the agent')
@@ -376,13 +441,22 @@ function! copilot#agent#New(...) abort
376441
let instance.startup_error = command_error
377442
return instance
378443
endif
379-
let state = {'headers': {}, 'mode': 'headers', 'buffer': ''}
380-
let instance.job = copilot#job#Stream(command,
381-
\ function('s:OnOut', [instance, state]),
382-
\ function('s:OnErr', [instance]),
383-
\ function('s:OnExit', [instance]))
384-
let instance.id = exists('*jobpid') ? jobpid(instance.job) : job_info(instance.job).process
385-
let request = instance.Request('initialize', {'capabilities': {}}, function('s:GetCapabilitiesResult'), function('s:GetCapabilitiesError'), instance)
444+
if has('nvim')
445+
call extend(instance, {
446+
\ 'Close': function('s:LspClose'),
447+
\ 'Notify': function('s:LspNotify'),
448+
\ 'Request': function('s:LspRequest')})
449+
let instance.client_id = v:lua.require'_copilot'.lsp_start_client(command, keys(instance.notifications) + keys(instance.methods) + ['LogMessage'])
450+
let instance.id = instance.client_id
451+
else
452+
let state = {'headers': {}, 'mode': 'headers', 'buffer': ''}
453+
let instance.job = copilot#job#Stream(command,
454+
\ function('s:OnOut', [instance, state]),
455+
\ function('s:OnErr', [instance]),
456+
\ function('s:OnExit', [instance]))
457+
let instance.id = exists('*jobpid') ? jobpid(instance.job) : job_info(instance.job).process
458+
let request = instance.Request('initialize', {'capabilities': {'workspace': {'workspaceFolders': v:true}}}, function('s:GetCapabilitiesResult'), function('s:GetCapabilitiesError'), instance)
459+
endif
386460
let s:instances[instance.id] = instance
387461
return instance
388462
endfunction

autoload/copilot/doc.vim

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,12 @@ endfunction
8282

8383
function! copilot#doc#Params(...) abort
8484
let extra = a:0 ? a:1 : {}
85-
return extend({'doc': extend(copilot#doc#Get(), get(extra, 'doc', {}))}, extra, 'keep')
85+
let params = extend({'doc': extend(copilot#doc#Get(), get(extra, 'doc', {}))}, extra, 'keep')
86+
let params.textDocument = {
87+
\ 'uri': params.doc.uri,
88+
\ 'languageId': params.doc.languageId,
89+
\ 'relativePath': params.doc.relativePath,
90+
\ }
91+
let params.position = params.doc.position
92+
return params
8693
endfunction

autoload/copilot/panel.vim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ function! copilot#panel#Open(opts) abort
133133
stopinsert
134134
else
135135
let params.doc.position.character = copilot#doc#UTF16Width(state.line)
136+
let params.position.character = params.doc.position.character
136137
endif
137138
let response = copilot#Request('getPanelCompletions', params).Wait()
138139
if response.status ==# 'error'

copilot/dist/agent.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lua/_copilot.lua

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
local copilot = {}
2+
3+
copilot.lsp_start_client = function(cmd, handler_names)
4+
local handlers = {}
5+
local id
6+
for _, name in ipairs(handler_names) do
7+
handlers[name] = function(err, result)
8+
if result then
9+
local retval = vim.call('copilot#agent#LspHandle', id, {method = name, params = result})
10+
if retval ~= 0 then return retval end
11+
end
12+
end
13+
end
14+
id = vim.lsp.start_client({
15+
cmd = cmd,
16+
name = 'copilot',
17+
handlers = handlers,
18+
get_language_id = function(bufnr, filetype)
19+
return vim.call('copilot#doc#LanguageForFileType', filetype)
20+
end,
21+
on_init = function(client, initialize_result)
22+
vim.call('copilot#agent#LspInit', client.id, initialize_result)
23+
end,
24+
on_exit = function(code, signal, client_id)
25+
vim.call('copilot#agent#LspExit', client_id, code, signal)
26+
end
27+
})
28+
return id
29+
end
30+
31+
copilot.lsp_request = function(client_id, method, params, bufnr)
32+
bufnr = bufnr or 0
33+
vim.lsp.buf_attach_client(bufnr, client_id)
34+
params.uri = vim.uri_from_bufnr(bufnr)
35+
local _, id
36+
_, id = vim.lsp.get_client_by_id(client_id).request(method, params, function(err, result)
37+
vim.call('copilot#agent#LspResponse', client_id, {id = id, error = err, result = result}, bufnr)
38+
end)
39+
return id
40+
end
41+
42+
copilot.rpc_request = function(client_id, method, params)
43+
local _, id
44+
_, id = vim.lsp.get_client_by_id(client_id).rpc.request(method, params, function(err, result)
45+
vim.call('copilot#agent#LspResponse', client_id, {id = id, error = err, result = result})
46+
end)
47+
return id
48+
end
49+
50+
copilot.rpc_notify = function(client_id, method, params)
51+
return vim.lsp.get_client_by_id(client_id).rpc.notify(method, params)
52+
end
53+
54+
return copilot

0 commit comments

Comments
 (0)