mirror of
				https://github.com/amix/vimrc
				synced 2025-10-30 21:43:35 +08:00 
			
		
		
		
	Added the copilot.vim to sources_non_forked
This commit is contained in:
		
							
								
								
									
										603
									
								
								sources_non_forked/copilot.vim/autoload/copilot/agent.vim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										603
									
								
								sources_non_forked/copilot.vim/autoload/copilot/agent.vim
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,603 @@ | ||||
| if exists('g:autoloaded_copilot_agent') | ||||
|   finish | ||||
| endif | ||||
| let g:autoloaded_copilot_agent = 1 | ||||
|  | ||||
| scriptencoding utf-8 | ||||
|  | ||||
| let s:plugin_version = '1.13.0' | ||||
|  | ||||
| let s:error_exit = -1 | ||||
|  | ||||
| let s:root = expand('<sfile>:h:h:h') | ||||
|  | ||||
| if !exists('s:instances') | ||||
|   let s:instances = {} | ||||
| endif | ||||
|  | ||||
| " allow sourcing this file to reload the Lua file too | ||||
| if has('nvim') | ||||
|   lua package.loaded._copilot = nil | ||||
| endif | ||||
|  | ||||
| let s:jobstop = function(exists('*jobstop') ? 'jobstop' : 'job_stop') | ||||
| function! s:Kill(agent, ...) abort | ||||
|   if has_key(a:agent, 'job') | ||||
|     call s:jobstop(a:agent.job) | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:AgentClose() dict abort | ||||
|   if !has_key(self, 'job') | ||||
|     return | ||||
|   endif | ||||
|   if exists('*chanclose') | ||||
|     call chanclose(self.job, 'stdin') | ||||
|   else | ||||
|     call ch_close_in(self.job) | ||||
|   endif | ||||
|   call copilot#logger#Info('agent stopped') | ||||
|   call timer_start(2000, function('s:Kill', [self])) | ||||
| endfunction | ||||
|  | ||||
| function! s:LogSend(request, line) abort | ||||
|   return '--> ' . a:line | ||||
| endfunction | ||||
|  | ||||
| function! s:RejectRequest(request, error) abort | ||||
|   if a:request.status ==# 'canceled' | ||||
|     return | ||||
|   endif | ||||
|   let a:request.waiting = {} | ||||
|   call remove(a:request, 'resolve') | ||||
|   let reject = remove(a:request, 'reject') | ||||
|   let a:request.status = 'error' | ||||
|   let a:request.error = a:error | ||||
|   for Cb in reject | ||||
|     let a:request.waiting[timer_start(0, function('s:Callback', [a:request, 'error', Cb]))] = 1 | ||||
|   endfor | ||||
| endfunction | ||||
|  | ||||
| function! s:Send(agent, request) abort | ||||
|   try | ||||
|     call ch_sendexpr(a:agent.job, a:request) | ||||
|     return v:true | ||||
|   catch /^Vim\%((\a\+)\)\=:E631:/ | ||||
|     return v:false | ||||
|   endtry | ||||
| endfunction | ||||
|  | ||||
| function! s:AgentNotify(method, params) dict abort | ||||
|   return s:Send(self, {'method': a:method, 'params': a:params}) | ||||
| endfunction | ||||
|  | ||||
| function! s:RequestWait() dict abort | ||||
|   while self.status ==# 'running' | ||||
|     sleep 1m | ||||
|   endwhile | ||||
|   while !empty(get(self, 'waiting', {})) | ||||
|     sleep 1m | ||||
|   endwhile | ||||
|   return self | ||||
| endfunction | ||||
|  | ||||
| function! s:RequestAwait() dict abort | ||||
|   call self.Wait() | ||||
|   if has_key(self, 'result') | ||||
|     return self.result | ||||
|   endif | ||||
|   throw 'copilot#agent(' . self.error.code . '): ' . self.error.message | ||||
| endfunction | ||||
|  | ||||
| function! s:RequestAgent() dict abort | ||||
|   return get(s:instances, self.agent_id, v:null) | ||||
| endfunction | ||||
|  | ||||
| if !exists('s:id') | ||||
|   let s:id = 0 | ||||
| endif | ||||
|  | ||||
| function! s:SetUpRequest(agent, id, method, params, ...) abort | ||||
|   let request = { | ||||
|         \ 'agent_id': a:agent.id, | ||||
|         \ 'id': a:id, | ||||
|         \ 'method': a:method, | ||||
|         \ 'params': a:params, | ||||
|         \ 'Agent': function('s:RequestAgent'), | ||||
|         \ 'Wait': function('s:RequestWait'), | ||||
|         \ 'Await': function('s:RequestAwait'), | ||||
|         \ 'Cancel': function('s:RequestCancel'), | ||||
|         \ 'resolve': [], | ||||
|         \ 'reject': [], | ||||
|         \ 'status': 'running'} | ||||
|   let a:agent.requests[a:id] = request | ||||
|   let args = a:000[2:-1] | ||||
|   if len(args) | ||||
|     if !empty(a:1) | ||||
|       call add(request.resolve, { v -> call(a:1, [v] + args)}) | ||||
|     endif | ||||
|     if !empty(a:2) | ||||
|       call add(request.reject, { v -> call(a:2, [v] + args)}) | ||||
|     endif | ||||
|     return request | ||||
|   endif | ||||
|   if a:0 && !empty(a:1) | ||||
|     call add(request.resolve, a:1) | ||||
|   endif | ||||
|   if a:0 > 1 && !empty(a:2) | ||||
|     call add(request.reject, a:2) | ||||
|   endif | ||||
|   return request | ||||
| endfunction | ||||
|  | ||||
| function! s:UrlEncode(str) abort | ||||
|   return substitute(iconv(a:str, 'latin1', 'utf-8'),'[^A-Za-z0-9._~!$&''()*+,;=:@/-]','\="%".printf("%02X",char2nr(submatch(0)))','g') | ||||
| endfunction | ||||
|  | ||||
| let s:slash = exists('+shellslash') ? '\' : '/' | ||||
| function! s:UriFromBufnr(bufnr) abort | ||||
|   let absolute = tr(bufname(a:bufnr), s:slash, '/') | ||||
|   if absolute !~# '^\a\+:\|^/\|^$' && getbufvar(a:bufnr, 'buftype') =~# '^\%(nowrite\)\=$' | ||||
|     let absolute = substitute(tr(getcwd(), s:slash, '/'), '/\=$', '/', '') . absolute | ||||
|   endif | ||||
|   if has('win32') && absolute =~# '^\a://\@!' | ||||
|     return 'file:///' . strpart(absolute, 0, 2) . s:UrlEncode(strpart(absolute, 2)) | ||||
|   elseif absolute =~# '^/' | ||||
|     return 'file://' . s:UrlEncode(absolute) | ||||
|   elseif absolute =~# '^\a[[:alnum:].+-]*:\|^$' | ||||
|     return absolute | ||||
|   else | ||||
|     return '' | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:BufferText(bufnr) abort | ||||
|   return join(getbufline(a:bufnr, 1, '$'), "\n") . "\n" | ||||
| endfunction | ||||
|  | ||||
| function! s:LogMessage(params) abort | ||||
|   call copilot#logger#Raw(get(a:params, 'level', 3), get(a:params, 'message', '')) | ||||
| endfunction | ||||
|  | ||||
| function! s:ShowMessageRequest(params) abort | ||||
|   let choice = inputlist([a:params.message . "\n\nRequest Actions:"] + | ||||
|         \ map(copy(get(a:params, 'actions', [])), { i, v -> (i + 1) . '. ' . v.title})) | ||||
|   return choice > 0 ? get(a:params.actions, choice - 1, v:null) : v:null | ||||
| endfunction | ||||
|  | ||||
| function! s:SendRequest(agent, request) abort | ||||
|   if empty(s:Send(a:agent, a:request)) && has_key(a:agent.requests, a:request.id) | ||||
|     call s:RejectRequest(remove(a:agent.requests, a:request.id), {'code': 257, 'message': 'Write failed'}) | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:AgentRequest(method, params, ...) dict abort | ||||
|   let s:id += 1 | ||||
|   let request = {'method': a:method, 'params': deepcopy(a:params), 'id': s:id} | ||||
|   for doc in filter([get(request.params, 'doc', {}), get(request.params, 'textDocument',{})], 'type(get(v:val, "uri", "")) == v:t_number') | ||||
|     let bufnr = doc.uri | ||||
|     let doc.uri = s:UriFromBufnr(doc.uri) | ||||
|     let uri = doc.uri | ||||
|     let languageId = copilot#doc#LanguageForFileType(getbufvar(bufnr, '&filetype')) | ||||
|     let doc_version = getbufvar(bufnr, 'changedtick') | ||||
|     if has_key(self.open_buffers, bufnr) && ( | ||||
|           \ self.open_buffers[bufnr].uri !=# doc.uri || | ||||
|           \ self.open_buffers[bufnr].languageId !=# languageId) | ||||
|       call remove(self.open_buffers, bufnr) | ||||
|       sleep 1m | ||||
|     endif | ||||
|     if !has_key(self.open_buffers, bufnr) | ||||
|       let td_item = { | ||||
|             \ 'uri': doc.uri, | ||||
|             \ 'version': doc_version, | ||||
|             \ 'languageId': languageId, | ||||
|             \ 'text': s:BufferText(bufnr)} | ||||
|       call self.Notify('textDocument/didOpen', {'textDocument': td_item}) | ||||
|       let self.open_buffers[bufnr] = { | ||||
|             \ 'uri': doc.uri, | ||||
|             \ 'version': doc_version, | ||||
|             \ 'languageId': languageId} | ||||
|     else | ||||
|       let vtd_id = { | ||||
|             \ 'uri': doc.uri, | ||||
|             \ 'version': doc_version} | ||||
|       call self.Notify('textDocument/didChange', { | ||||
|             \ 'textDocument': vtd_id, | ||||
|             \ 'contentChanges': [{'text': s:BufferText(bufnr)}]}) | ||||
|       let self.open_buffers[bufnr].version = doc_version | ||||
|     endif | ||||
|     let doc.version = doc_version | ||||
|   endfor | ||||
|   call timer_start(0, { _ -> s:SendRequest(self, request) }) | ||||
|   return call('s:SetUpRequest', [self, s:id, a:method, a:params] + a:000) | ||||
| endfunction | ||||
|  | ||||
| function! s:AgentCall(method, params, ...) dict abort | ||||
|   let request = call(self.Request, [a:method, a:params] + a:000) | ||||
|   if a:0 | ||||
|     return request | ||||
|   endif | ||||
|   return request.Await() | ||||
| endfunction | ||||
|  | ||||
| function! s:AgentCancel(request) dict abort | ||||
|   if has_key(self.requests, get(a:request, 'id', '')) | ||||
|     call remove(self.requests, a:request.id) | ||||
|     call self.Notify('$/cancelRequest', {'id': a:request.id}) | ||||
|   endif | ||||
|   if get(a:request, 'status', '') ==# 'running' | ||||
|     let a:request.status = 'canceled' | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:RequestCancel() dict abort | ||||
|   let agent = self.Agent() | ||||
|   if !empty(agent) | ||||
|     call agent.Cancel(self) | ||||
|   elseif get(self, 'status', '') ==# 'running' | ||||
|     let self.status = 'canceled' | ||||
|   endif | ||||
|   return self | ||||
| endfunction | ||||
|  | ||||
| function! s:DispatchMessage(agent, handler, id, params, ...) abort | ||||
|   try | ||||
|     let response = {'result': call(a:handler, [a:params])} | ||||
|     if response.result is# 0 | ||||
|       let response.result = v:null | ||||
|     endif | ||||
|   catch | ||||
|     call copilot#logger#Exception() | ||||
|     let response = {'error': {'code': -32000, 'message': v:exception}} | ||||
|   endtry | ||||
|   if !empty(a:id) | ||||
|     call s:Send(a:agent, extend({'id': a:id}, response)) | ||||
|   endif | ||||
|   return response | ||||
| endfunction | ||||
|  | ||||
| function! s:OnMessage(agent, body, ...) abort | ||||
|   if !has_key(a:body, 'method') | ||||
|     return s:OnResponse(a:agent, a:body) | ||||
|   endif | ||||
|   let request = a:body | ||||
|   let id = get(request, 'id', v:null) | ||||
|   let params = get(request, 'params', v:null) | ||||
|   if has_key(a:agent.methods, request.method) | ||||
|     return s:DispatchMessage(a:agent, a:agent.methods[request.method], id, params) | ||||
|   elseif !empty(id) | ||||
|     call s:Send(a:agent, {"id": id, "error": {"code": -32700, "message": "Method not found: " . request.method}}) | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:OnResponse(agent, response, ...) abort | ||||
|   let response = a:response | ||||
|   let id = get(a:response, 'id', v:null) | ||||
|   if !has_key(a:agent.requests, id) | ||||
|     return | ||||
|   endif | ||||
|   let request = remove(a:agent.requests, id) | ||||
|   if request.status ==# 'canceled' | ||||
|     return | ||||
|   endif | ||||
|   let request.waiting = {} | ||||
|   let resolve = remove(request, 'resolve') | ||||
|   let reject = remove(request, 'reject') | ||||
|   if has_key(response, 'result') | ||||
|     let request.status = 'success' | ||||
|     let request.result = response.result | ||||
|     for Cb in resolve | ||||
|       let request.waiting[timer_start(0, function('s:Callback', [request, 'result', Cb]))] = 1 | ||||
|     endfor | ||||
|   else | ||||
|     let request.status = 'error' | ||||
|     let request.error = response.error | ||||
|     for Cb in reject | ||||
|       let request.waiting[timer_start(0, function('s:Callback', [request, 'error', Cb]))] = 1 | ||||
|     endfor | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:OnErr(agent, line, ...) abort | ||||
|   call copilot#logger#Debug('<-! ' . a:line) | ||||
| endfunction | ||||
|  | ||||
| function! s:OnExit(agent, code, ...) abort | ||||
|   let a:agent.exit_status = a:code | ||||
|   if has_key(a:agent, 'job') | ||||
|     call remove(a:agent, 'job') | ||||
|   endif | ||||
|   if has_key(a:agent, 'client_id') | ||||
|     call remove(a:agent, 'client_id') | ||||
|   endif | ||||
|   let code = a:code < 0 || a:code > 255 ? 256 : a:code | ||||
|   for id in sort(keys(a:agent.requests), { a, b -> +a > +b }) | ||||
|     call s:RejectRequest(remove(a:agent.requests, id), {'code': code, 'message': 'Agent exited', 'data': {'status': a:code}}) | ||||
|   endfor | ||||
|   call timer_start(0, { _ -> get(s:instances, a:agent.id) is# a:agent ? remove(s:instances, a:agent.id) : {} }) | ||||
|   call copilot#logger#Info('agent exited with status ' . a:code) | ||||
| endfunction | ||||
|  | ||||
| function! copilot#agent#LspInit(agent_id, initialize_result) abort | ||||
|   if !has_key(s:instances, a:agent_id) | ||||
|     return | ||||
|   endif | ||||
|   let instance = s:instances[a:agent_id] | ||||
|   call timer_start(0, { _ -> s:GetCapabilitiesResult(a:initialize_result, instance)}) | ||||
| endfunction | ||||
|  | ||||
| function! copilot#agent#LspExit(agent_id, code, signal) abort | ||||
|   if !has_key(s:instances, a:agent_id) | ||||
|     return | ||||
|   endif | ||||
|   let instance = remove(s:instances, a:agent_id) | ||||
|   call s:OnExit(instance, a:code) | ||||
| endfunction | ||||
|  | ||||
| function! copilot#agent#LspResponse(agent_id, opts, ...) abort | ||||
|   if !has_key(s:instances, a:agent_id) | ||||
|     return | ||||
|   endif | ||||
|   call s:OnResponse(s:instances[a:agent_id], a:opts) | ||||
| endfunction | ||||
|  | ||||
| function! s:LspRequest(method, params, ...) dict abort | ||||
|   let id = v:lua.require'_copilot'.lsp_request(self.id, a:method, a:params) | ||||
|   if id isnot# v:null | ||||
|     return call('s:SetUpRequest', [self, id, a:method, a:params] + a:000) | ||||
|   endif | ||||
|   if has_key(self, 'client_id') | ||||
|     call copilot#agent#LspExit(self.client_id, -1, -1) | ||||
|   endif | ||||
|   throw 'copilot#agent: LSP client not available' | ||||
| endfunction | ||||
|  | ||||
| function! s:LspClose() dict abort | ||||
|   if !has_key(self, 'client_id') | ||||
|     return | ||||
|   endif | ||||
|   return luaeval('vim.lsp.get_client_by_id(_A).stop()', self.client_id) | ||||
| endfunction | ||||
|  | ||||
| function! s:LspNotify(method, params) dict abort | ||||
|   return v:lua.require'_copilot'.rpc_notify(self.id, a:method, a:params) | ||||
| endfunction | ||||
|  | ||||
| function! copilot#agent#LspHandle(agent_id, request) abort | ||||
|   if !has_key(s:instances, a:agent_id) | ||||
|     return | ||||
|   endif | ||||
|   return s:OnMessage(s:instances[a:agent_id], a:request) | ||||
| endfunction | ||||
|  | ||||
| function! s:GetNodeVersion(command) abort | ||||
|   let out = [] | ||||
|   let err = [] | ||||
|   let status = copilot#job#Stream(a:command + ['--version'], function('add', [out]), function('add', [err])) | ||||
|   let string = matchstr(join(out, ''), '^v\zs\d\+\.[^[:space:]]*') | ||||
|   if status != 0 | ||||
|     let string = '' | ||||
|   endif | ||||
|   let major = str2nr(string) | ||||
|   let minor = str2nr(matchstr(string, '\.\zs\d\+')) | ||||
|   return {'status': status, 'string': string, 'major': major, 'minor': minor} | ||||
| endfunction | ||||
|  | ||||
| function! s:Command() abort | ||||
|   if !has('nvim-0.6') && v:version < 900 | ||||
|     return [v:null, '', 'Vim version too old'] | ||||
|   endif | ||||
|   let node = get(g:, 'copilot_node_command', '') | ||||
|   if empty(node) | ||||
|     let node = ['node'] | ||||
|   elseif type(node) == type('') | ||||
|     let node = [expand(node)] | ||||
|   endif | ||||
|   if !executable(get(node, 0, '')) | ||||
|     if get(node, 0, '') ==# 'node' | ||||
|       return [v:null, '', 'Node.js not found in PATH'] | ||||
|     else | ||||
|       return [v:null, '', 'Node.js executable `' . get(node, 0, '') . "' not found"] | ||||
|     endif | ||||
|   endif | ||||
|   let node_version = s:GetNodeVersion(node) | ||||
|   let warning = '' | ||||
|   if !get(g:, 'copilot_ignore_node_version') && node_version.major < 18 && get(node, 0, '') !=# 'node' && executable('node') | ||||
|     let node_version_from_path = s:GetNodeVersion(['node']) | ||||
|     if node_version_from_path.major >= 18 | ||||
|       let warning = 'Ignoring g:copilot_node_command: Node.js ' . node_version.string . ' is end-of-life' | ||||
|       let node = ['node'] | ||||
|       let node_version = node_version_from_path | ||||
|     endif | ||||
|   endif | ||||
|   if node_version.status != 0 | ||||
|     return [v:null, '', 'Node.js exited with status ' . node_version.status] | ||||
|   endif | ||||
|   if !get(g:, 'copilot_ignore_node_version') | ||||
|     if node_version.major == 0 | ||||
|       return [v:null, node_version.string, 'Could not determine Node.js version'] | ||||
|     elseif node_version.major < 16 || node_version.major == 16 && node_version.minor < 14 || node_version.major == 17 && node_version.minor < 3 | ||||
|       " 16.14+ and 17.3+ still work for now, but are end-of-life | ||||
|       return [v:null, node_version.string, 'Node.js version 18.x or newer required but found ' . node_version.string] | ||||
|     endif | ||||
|   endif | ||||
|   let agent = get(g:, 'copilot_agent_command', '') | ||||
|   if empty(agent) || !filereadable(agent) | ||||
|     let agent = s:root . '/dist/agent.js' | ||||
|     if !filereadable(agent) | ||||
|       return [v:null, node_version.string, 'Could not find dist/agent.js (bad install?)'] | ||||
|     endif | ||||
|   endif | ||||
|   return [node + [agent, '--stdio'], node_version.string, warning] | ||||
| endfunction | ||||
|  | ||||
| function! s:UrlDecode(str) abort | ||||
|   return substitute(a:str, '%\(\x\x\)', '\=iconv(nr2char("0x".submatch(1)), "utf-8", "latin1")', 'g') | ||||
| endfunction | ||||
|  | ||||
| function! copilot#agent#EditorInfo() abort | ||||
|   if !exists('s:editor_version') | ||||
|     if has('nvim') | ||||
|       let s:editor_version = matchstr(execute('version'), 'NVIM v\zs[^[:space:]]\+') | ||||
|     else | ||||
|       let s:editor_version = (v:version / 100) . '.' . (v:version % 100) . (exists('v:versionlong') ? printf('.%04d', v:versionlong % 1000) : '') | ||||
|     endif | ||||
|   endif | ||||
|   let info = { | ||||
|         \ 'editorInfo': {'name': has('nvim') ? 'Neovim': 'Vim', 'version': s:editor_version}, | ||||
|         \ 'editorPluginInfo': {'name': 'copilot.vim', 'version': s:plugin_version}} | ||||
|   if type(get(g:, 'copilot_proxy')) == v:t_string | ||||
|     let proxy = g:copilot_proxy | ||||
|   else | ||||
|     let proxy = '' | ||||
|   endif | ||||
|   let match = matchlist(proxy, '\c^\%([^:]\+://\)\=\%(\([^/#]\+@\)\)\=\%(\([^/:#]\+\)\|\[\([[:xdigit:]:]\+\)\]\)\%(:\(\d\+\)\)\=\%(/\|$\|?strict_\=ssl=\(.*\)\)') | ||||
|   if !empty(match) | ||||
|     let info.networkProxy = {'host': match[2] . match[3], 'port': empty(match[4]) ? 80 : +match[4]} | ||||
|     if match[5] =~? '^[0f]' | ||||
|       let info.networkProxy.rejectUnauthorized = v:false | ||||
|     elseif match[5] =~? '^[1t]' | ||||
|       let info.networkProxy.rejectUnauthorized = v:true | ||||
|     elseif exists('g:copilot_proxy_strict_ssl') | ||||
|       let info.networkProxy.rejectUnauthorized = empty(g:copilot_proxy_strict_ssl) ? v:false : v:true | ||||
|     endif | ||||
|     if !empty(match[1]) | ||||
|       let info.networkProxy.username = s:UrlDecode(matchstr(match[1], '^[^:@]*')) | ||||
|       let info.networkProxy.password = s:UrlDecode(matchstr(match[1], ':\zs[^@]*')) | ||||
|     endif | ||||
|   endif | ||||
|   return info | ||||
| endfunction | ||||
|  | ||||
| function! s:GetCapabilitiesResult(result, agent) abort | ||||
|   let a:agent.capabilities = get(a:result, 'capabilities', {}) | ||||
|   let info = copilot#agent#EditorInfo() | ||||
|   call a:agent.Request('setEditorInfo', extend({'editorConfiguration': a:agent.editorConfiguration}, info)) | ||||
| endfunction | ||||
|  | ||||
| function! s:GetCapabilitiesError(error, agent) abort | ||||
|   if a:error.code == s:error_exit | ||||
|     let a:agent.startup_error = 'Agent exited with status ' . a:error.data.status | ||||
|   else | ||||
|     let a:agent.startup_error = 'Unexpected error ' . a:error.code . ' calling agent: ' . a:error.message | ||||
|     call a:agent.Close() | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:AgentStartupError() dict abort | ||||
|   while (has_key(self, 'job') || has_key(self, 'client_id')) && !has_key(self, 'startup_error') && !has_key(self, 'capabilities') | ||||
|     sleep 10m | ||||
|   endwhile | ||||
|   if has_key(self, 'capabilities') | ||||
|     return '' | ||||
|   else | ||||
|     return get(self, 'startup_error', 'Something unexpected went wrong spawning the agent') | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! copilot#agent#New(...) abort | ||||
|   let opts = a:0 ? a:1 : {} | ||||
|   let instance = {'requests': {}, | ||||
|         \ 'editorConfiguration': get(opts, 'editorConfiguration', {}), | ||||
|         \ 'Close': function('s:AgentClose'), | ||||
|         \ 'Notify': function('s:AgentNotify'), | ||||
|         \ 'Request': function('s:AgentRequest'), | ||||
|         \ 'Call': function('s:AgentCall'), | ||||
|         \ 'Cancel': function('s:AgentCancel'), | ||||
|         \ 'StartupError': function('s:AgentStartupError'), | ||||
|         \ } | ||||
|   let instance.methods = extend({ | ||||
|         \ 'LogMessage': function('s:LogMessage'), | ||||
|         \ 'window/logMessage': function('s:LogMessage'), | ||||
|         \ }, get(opts, 'methods', {})) | ||||
|   let [command, node_version, command_error] = s:Command() | ||||
|   if len(command_error) | ||||
|     if empty(command) | ||||
|       let instance.id = -1 | ||||
|       let instance.startup_error = command_error | ||||
|       return instance | ||||
|     else | ||||
|       let instance.node_version_warning = command_error | ||||
|     endif | ||||
|   endif | ||||
|   let instance.node_version = node_version | ||||
|   if has('nvim') | ||||
|     call extend(instance, { | ||||
|         \ 'Close': function('s:LspClose'), | ||||
|         \ 'Notify': function('s:LspNotify'), | ||||
|         \ 'Request': function('s:LspRequest')}) | ||||
|     let instance.client_id = v:lua.require'_copilot'.lsp_start_client(command, keys(instance.methods)) | ||||
|     let instance.id = instance.client_id | ||||
|   else | ||||
|     let state = {'headers': {}, 'mode': 'headers', 'buffer': ''} | ||||
|     let instance.open_buffers = {} | ||||
|     let instance.methods = extend({'window/showMessageRequest': function('s:ShowMessageRequest')}, instance.methods) | ||||
|     let instance.job = job_start(command, { | ||||
|           \ 'cwd': copilot#job#Cwd(), | ||||
|           \ 'in_mode': 'lsp', | ||||
|           \ 'out_mode': 'lsp', | ||||
|           \ 'out_cb': { j, d -> timer_start(0, function('s:OnMessage', [instance, d])) }, | ||||
|           \ 'err_cb': { j, d -> timer_start(0, function('s:OnErr', [instance, d])) }, | ||||
|           \ 'exit_cb': { j, d -> timer_start(0, function('s:OnExit', [instance, d])) }, | ||||
|           \ }) | ||||
|     let instance.id = exists('*jobpid') ? jobpid(instance.job) : job_info(instance.job).process | ||||
|     let capabilities = {'workspace': {'workspaceFolders': v:true}, 'copilot': {}} | ||||
|     for name in keys(instance.methods) | ||||
|       if name =~# '^copilot/' | ||||
|         let capabilities.copilot[matchstr(name, '/\zs.*')] = v:true | ||||
|       endif | ||||
|     endfor | ||||
|     let request = instance.Request('initialize', {'capabilities': capabilities}, function('s:GetCapabilitiesResult'), function('s:GetCapabilitiesError'), instance) | ||||
|   endif | ||||
|   let s:instances[instance.id] = instance | ||||
|   return instance | ||||
| endfunction | ||||
|  | ||||
| function! copilot#agent#Cancel(request) abort | ||||
|   if type(a:request) == type({}) && has_key(a:request, 'Cancel') | ||||
|     call a:request.Cancel() | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:Callback(request, type, callback, timer) abort | ||||
|   call remove(a:request.waiting, a:timer) | ||||
|   if has_key(a:request, a:type) | ||||
|     call a:callback(a:request[a:type]) | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! copilot#agent#Result(request, callback) abort | ||||
|   if has_key(a:request, 'resolve') | ||||
|     call add(a:request.resolve, a:callback) | ||||
|   elseif has_key(a:request, 'result') | ||||
|     let a:request.waiting[timer_start(0, function('s:Callback', [a:request, 'result', a:callback]))] = 1 | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! copilot#agent#Error(request, callback) abort | ||||
|   if has_key(a:request, 'reject') | ||||
|     call add(a:request.reject, a:callback) | ||||
|   elseif has_key(a:request, 'error') | ||||
|     let a:request.waiting[timer_start(0, function('s:Callback', [a:request, 'error', a:callback]))] = 1 | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:CloseBuffer(bufnr) abort | ||||
|   for instance in values(s:instances) | ||||
|     try | ||||
|       if has_key(instance, 'job') && has_key(instance.open_buffers, a:bufnr) | ||||
|         let buffer = remove(instance.open_buffers, a:bufnr) | ||||
|         call instance.Notify('textDocument/didClose', {'textDocument': {'uri': buffer.uri}}) | ||||
|       endif | ||||
|     catch | ||||
|       call copilot#logger#Exception() | ||||
|     endtry | ||||
|   endfor | ||||
| endfunction | ||||
|  | ||||
| augroup copilot_agent | ||||
|   autocmd! | ||||
|   if !has('nvim') | ||||
|     autocmd BufUnload * call s:CloseBuffer(+expand('<abuf>')) | ||||
|   endif | ||||
| augroup END | ||||
							
								
								
									
										116
									
								
								sources_non_forked/copilot.vim/autoload/copilot/doc.vim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								sources_non_forked/copilot.vim/autoload/copilot/doc.vim
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,116 @@ | ||||
| if exists('g:autoloaded_copilot_prompt') | ||||
|   finish | ||||
| endif | ||||
| let g:autoloaded_copilot_prompt = 1 | ||||
|  | ||||
| scriptencoding utf-8 | ||||
|  | ||||
| let s:slash = exists('+shellslash') ? '\' : '/' | ||||
|  | ||||
| function copilot#doc#UTF16Width(str) abort | ||||
|   return strchars(substitute(a:str, "\\%#=2[^\u0001-\uffff]", "  ", 'g')) | ||||
| endfunction | ||||
|  | ||||
| if exists('*utf16idx') | ||||
|  | ||||
|   function! copilot#doc#UTF16ToByteIdx(str, utf16_idx) abort | ||||
|     return byteidx(a:str, a:utf16_idx, 1) | ||||
|   endfunction | ||||
|  | ||||
| elseif has('nvim') | ||||
|  | ||||
|   function! copilot#doc#UTF16ToByteIdx(str, utf16_idx) abort | ||||
|     try | ||||
|       return v:lua.vim.str_byteindex(a:str, a:utf16_idx, 1) | ||||
|     catch /^Vim(return):E5108:/ | ||||
|       return -1 | ||||
|     endtry | ||||
|   endfunction | ||||
|  | ||||
| else | ||||
|  | ||||
|   function! copilot#doc#UTF16ToByteIdx(str, utf16_idx) abort | ||||
|     if copilot#doc#UTF16Width(a:str) < a:utf16_idx | ||||
|       return -1 | ||||
|     endif | ||||
|     let end_offset = len(a:str) | ||||
|     while copilot#doc#UTF16Width(strpart(a:str, 0, end_offset)) > a:utf16_idx && end_offset > 0 | ||||
|       let end_offset -= 1 | ||||
|     endwhile | ||||
|     return end_offset | ||||
|   endfunction | ||||
|  | ||||
| endif | ||||
|  | ||||
|  | ||||
| let s:language_normalization_map = { | ||||
|       \ "bash":            "shellscript", | ||||
|       \ "bst":             "bibtex", | ||||
|       \ "cs":              "csharp", | ||||
|       \ "cuda":            "cuda-cpp", | ||||
|       \ "dosbatch":        "bat", | ||||
|       \ "dosini":          "ini", | ||||
|       \ "gitcommit":       "git-commit", | ||||
|       \ "gitrebase":       "git-rebase", | ||||
|       \ "make":            "makefile", | ||||
|       \ "objc":            "objective-c", | ||||
|       \ "objcpp":          "objective-cpp", | ||||
|       \ "ps1":             "powershell", | ||||
|       \ "raku":            "perl6", | ||||
|       \ "sh":              "shellscript", | ||||
|       \ "text":            "plaintext", | ||||
|       \ } | ||||
| function copilot#doc#LanguageForFileType(filetype) abort | ||||
|   let filetype = substitute(a:filetype, '\..*', '', '') | ||||
|   return get(s:language_normalization_map, empty(filetype) ? "text" : filetype, filetype) | ||||
| endfunction | ||||
|  | ||||
| function! s:RelativePath(absolute) abort | ||||
|   if exists('b:copilot_relative_path') | ||||
|     return b:copilot_relative_path | ||||
|   elseif exists('b:copilot_root') | ||||
|     let root = b:copilot_root | ||||
|   elseif len(get(b:, 'projectionist', {})) | ||||
|     let root = sort(keys(b:projectionist), { a, b -> a < b })[0] | ||||
|   else | ||||
|     let root = getcwd() | ||||
|   endif | ||||
|   let root = tr(root, s:slash, '/') . '/' | ||||
|   if strpart(tr(a:absolute, 'A-Z', 'a-z'), 0, len(root)) ==# tr(root, 'A-Z', 'a-z') | ||||
|     return strpart(a:absolute, len(root)) | ||||
|   else | ||||
|     return fnamemodify(a:absolute, ':t') | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! copilot#doc#Get() abort | ||||
|   let absolute = tr(@%, s:slash, '/') | ||||
|   if absolute !~# '^\a\+:\|^/\|^$' && &buftype =~# '^\%(nowrite\)\=$' | ||||
|     let absolute = substitute(tr(getcwd(), s:slash, '/'), '/\=$', '/', '') . absolute | ||||
|   endif | ||||
|   let doc = { | ||||
|         \ 'uri': bufnr(''), | ||||
|         \ 'version': getbufvar('', 'changedtick'), | ||||
|         \ 'relativePath': s:RelativePath(absolute), | ||||
|         \ 'insertSpaces': &expandtab ? v:true : v:false, | ||||
|         \ 'tabSize': shiftwidth(), | ||||
|         \ 'indentSize': shiftwidth(), | ||||
|         \ } | ||||
|   let line = getline('.') | ||||
|   let col_byte = col('.') - (mode() =~# '^[iR]' || empty(line)) | ||||
|   let col_utf16 = copilot#doc#UTF16Width(strpart(line, 0, col_byte)) | ||||
|   let doc.position = {'line': line('.') - 1, 'character': col_utf16} | ||||
|   return doc | ||||
| endfunction | ||||
|  | ||||
| function! copilot#doc#Params(...) abort | ||||
|   let extra = a:0 ? a:1 : {} | ||||
|   let params = extend({'doc': extend(copilot#doc#Get(), get(extra, 'doc', {}))}, extra, 'keep') | ||||
|   let params.textDocument = { | ||||
|         \ 'uri': params.doc.uri, | ||||
|         \ 'version': params.doc.version, | ||||
|         \ 'relativePath': params.doc.relativePath, | ||||
|         \ } | ||||
|   let params.position = params.doc.position | ||||
|   return params | ||||
| endfunction | ||||
							
								
								
									
										111
									
								
								sources_non_forked/copilot.vim/autoload/copilot/job.vim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								sources_non_forked/copilot.vim/autoload/copilot/job.vim
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,111 @@ | ||||
| if exists('g:autoloaded_copilot_job') | ||||
|   finish | ||||
| endif | ||||
| let g:autoloaded_copilot_job = 1 | ||||
|  | ||||
| scriptencoding utf-8 | ||||
|  | ||||
| function copilot#job#Nop(...) abort | ||||
| endfunction | ||||
|  | ||||
| function! s:Jobs(job_or_jobs) abort | ||||
|   let jobs = type(a:job_or_jobs) == v:t_list ? copy(a:job_or_jobs) : [a:job_or_jobs] | ||||
|   call map(jobs, { k, v -> type(v) == v:t_dict ? get(v, 'job', '') : v }) | ||||
|   call filter(jobs, { k, v -> type(v) !=# type('') }) | ||||
|   return jobs | ||||
| endfunction | ||||
|  | ||||
| let s:job_stop = exists('*job_stop') ? 'job_stop' : 'jobstop' | ||||
| function! copilot#job#Stop(job) abort | ||||
|   for job in s:Jobs(a:job) | ||||
|     call call(s:job_stop, [job]) | ||||
|   endfor | ||||
|   return copilot#job#Wait(a:job) | ||||
| endfunction | ||||
|  | ||||
| let s:sleep = has('patch-8.2.2366') ? 'sleep! 1m' : 'sleep 1m' | ||||
| function! copilot#job#Wait(jobs) abort | ||||
|   let jobs = s:Jobs(a:jobs) | ||||
|   if exists('*jobwait') | ||||
|     call jobwait(jobs) | ||||
|   else | ||||
|     for job in jobs | ||||
|       while ch_status(job) !=# 'closed' || job_status(job) ==# 'run' | ||||
|         exe s:sleep | ||||
|       endwhile | ||||
|     endfor | ||||
|   endif | ||||
|   return a:jobs | ||||
| endfunction | ||||
|  | ||||
| function! s:VimExitCallback(result, exit_cb, job, data) abort | ||||
|   let a:result.exit_status = a:data | ||||
|   if !has_key(a:result, 'closed') | ||||
|     return | ||||
|   endif | ||||
|   call remove(a:result, 'closed') | ||||
|   call a:exit_cb(a:result.exit_status) | ||||
| endfunction | ||||
|  | ||||
| function! s:VimCloseCallback(result, exit_cb, job) abort | ||||
|   if !has_key(a:result, 'exit_status') | ||||
|     let a:result.closed = v:true | ||||
|     return | ||||
|   endif | ||||
|   call a:exit_cb(a:result.exit_status) | ||||
| endfunction | ||||
|  | ||||
| function! s:NvimCallback(cb, job, data, type) dict abort | ||||
|   let self[a:type][0] .= remove(a:data, 0) | ||||
|   call extend(self[a:type], a:data) | ||||
|   while len(self[a:type]) > 1 | ||||
|     call a:cb(substitute(remove(self[a:type], 0), "\r$", '', '')) | ||||
|   endwhile | ||||
| endfunction | ||||
|  | ||||
| function! s:NvimExitCallback(out_cb, err_cb, exit_cb, job, data, type) dict abort | ||||
|   if len(self.stderr[0]) | ||||
|     call a:err_cb(substitute(self.stderr[0], "\r$", '', '')) | ||||
|   endif | ||||
|   call a:exit_cb(a:data) | ||||
| endfunction | ||||
|  | ||||
| function! copilot#job#Cwd() abort | ||||
|   let home = expand("~") | ||||
|   if !isdirectory(home) && isdirectory($VIM) | ||||
|     return $VIM | ||||
|   endif | ||||
|   return home | ||||
| endfunction | ||||
|  | ||||
| function! copilot#job#Stream(argv, out_cb, err_cb, ...) abort | ||||
|   let exit_status = [] | ||||
|   let ExitCb = function(a:0 && !empty(a:1) ? a:1 : { e -> add(exit_status, e) }, a:000[2:-1]) | ||||
|   let OutCb = function(empty(a:out_cb) ? 'copilot#job#Nop' : a:out_cb, a:000[2:-1]) | ||||
|   let ErrCb = function(empty(a:err_cb) ? 'copilot#job#Nop' : a:err_cb, a:000[2:-1]) | ||||
|   let state = {'headers': {}, 'mode': 'headers', 'buffer': ''} | ||||
|   if exists('*job_start') | ||||
|     let result = {} | ||||
|     let job = job_start(a:argv, { | ||||
|           \ 'cwd': copilot#job#Cwd(), | ||||
|           \ 'out_mode': 'raw', | ||||
|           \ 'out_cb': { j, d -> OutCb(d) }, | ||||
|           \ 'err_cb': { j, d -> ErrCb(d) }, | ||||
|           \ 'exit_cb': function('s:VimExitCallback', [result, ExitCb]), | ||||
|           \ 'close_cb': function('s:VimCloseCallback', [result, ExitCb]), | ||||
|           \ }) | ||||
|   else | ||||
|     let jopts = { | ||||
|           \ 'cwd': copilot#job#Cwd(), | ||||
|           \ 'stderr': [''], | ||||
|           \ 'on_stdout': { j, d, t -> OutCb(join(d, "\n")) }, | ||||
|           \ 'on_stderr': function('s:NvimCallback', [ErrCb]), | ||||
|           \ 'on_exit': function('s:NvimExitCallback', [OutCb, ErrCb, ExitCb])} | ||||
|     let job = jobstart(a:argv, jopts) | ||||
|   endif | ||||
|   if a:0 | ||||
|     return job | ||||
|   endif | ||||
|   call copilot#job#Wait(job) | ||||
|   return exit_status[0] | ||||
| endfunction | ||||
							
								
								
									
										72
									
								
								sources_non_forked/copilot.vim/autoload/copilot/logger.vim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								sources_non_forked/copilot.vim/autoload/copilot/logger.vim
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,72 @@ | ||||
| if exists('g:autoloaded_copilot_log') | ||||
|   finish | ||||
| endif | ||||
| let g:autoloaded_copilot_log = 1 | ||||
|  | ||||
| if !exists('s:log_file') | ||||
|   let s:log_file = tempname() . '-copilot.log' | ||||
|   try | ||||
|     call writefile([], s:log_file) | ||||
|   catch | ||||
|   endtry | ||||
| endif | ||||
|  | ||||
| function! copilot#logger#File() abort | ||||
|   return s:log_file | ||||
| endfunction | ||||
|  | ||||
| function! copilot#logger#Raw(level, message) abort | ||||
|   if $COPILOT_AGENT_VERBOSE !~# '^\%(1\|true\)$' && a:level < 1 | ||||
|     return | ||||
|   endif | ||||
|   let lines = type(a:message) == v:t_list ? copy(a:message) : split(a:message, "\n", 1) | ||||
|   try | ||||
|     if !filewritable(s:log_file) | ||||
|       return | ||||
|     endif | ||||
|     call map(lines, { k, L -> type(L) == v:t_func ? call(L, []) : L }) | ||||
|     call writefile(lines, s:log_file, 'a') | ||||
|   catch | ||||
|   endtry | ||||
| endfunction | ||||
|  | ||||
| function! copilot#logger#Trace(...) abort | ||||
|   call copilot#logger#Raw(-1, a:000) | ||||
| endfunction | ||||
|  | ||||
| function! copilot#logger#Debug(...) abort | ||||
|   call copilot#logger#Raw(0, a:000) | ||||
| endfunction | ||||
|  | ||||
| function! copilot#logger#Info(...) abort | ||||
|   call copilot#logger#Raw(1, a:000) | ||||
| endfunction | ||||
|  | ||||
| function! copilot#logger#Warn(...) abort | ||||
|   call copilot#logger#Raw(2, a:000) | ||||
| endfunction | ||||
|  | ||||
| function! copilot#logger#Error(...) abort | ||||
|   call copilot#logger#Raw(3, a:000) | ||||
| endfunction | ||||
|  | ||||
| function! copilot#logger#Exception() abort | ||||
|   if !empty(v:exception) && v:exception !=# 'Vim:Interrupt' | ||||
|     call copilot#logger#Error('Exception: ' . v:exception . ' @ ' . v:throwpoint) | ||||
|     let agent = copilot#RunningAgent() | ||||
|     if !empty(agent) | ||||
|       let stacklines = [] | ||||
|       for frame in split(substitute(substitute(v:throwpoint, ', \S\+ \(\d\+\)$', '[\1]', ''), '^function ', '', ''), '\.\@<!\.\.\.\@!') | ||||
|         if frame =~# '[\/]' | ||||
|           call add(stacklines, '[redacted]') | ||||
|         else | ||||
|           call add(stacklines, substitute(frame, '^<SNR>\d\+_', '<SID>', '')) | ||||
|         endif | ||||
|       endfor | ||||
|       call agent.Request('telemetry/exception', { | ||||
|             \ 'origin': 'copilot.vim', | ||||
|             \ 'stacktrace': join([v:exception] + stacklines, "\n") | ||||
|             \ }) | ||||
|     endif | ||||
|   endif | ||||
| endfunction | ||||
							
								
								
									
										160
									
								
								sources_non_forked/copilot.vim/autoload/copilot/panel.vim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								sources_non_forked/copilot.vim/autoload/copilot/panel.vim
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,160 @@ | ||||
| if exists('g:autoloaded_copilot_panel') | ||||
|   finish | ||||
| endif | ||||
| let g:autoloaded_copilot_panel = 1 | ||||
|  | ||||
| scriptencoding utf-8 | ||||
|  | ||||
| if !exists('s:panel_id') | ||||
|   let s:panel_id = 0 | ||||
| endif | ||||
|  | ||||
| let s:separator = repeat('─', 72) | ||||
|  | ||||
| function! s:Solutions(state) abort | ||||
|   return sort(values(get(a:state, 'solutions', {})), { a, b -> a.score < b.score }) | ||||
| endfunction | ||||
|  | ||||
| function! s:Render(panel_id) abort | ||||
|   let bufnr = bufnr('^' . a:panel_id . '$') | ||||
|   let state = getbufvar(bufnr, 'copilot_panel') | ||||
|   if !bufloaded(bufnr) || type(state) != v:t_dict | ||||
|     return | ||||
|   endif | ||||
|   let sorted = s:Solutions(state) | ||||
|   if !empty(get(state, 'status', '')) | ||||
|     let lines = ['Error: ' . state.status] | ||||
|   else | ||||
|     let target = get(state, 'count_target', '?') | ||||
|     let received = has_key(state, 'status') ? target : len(sorted) | ||||
|     let lines = ['Synthesiz' . (has_key(state, 'status') ? 'ed ' : 'ing ') . received . '/' . target . ' solutions (Duplicates hidden)'] | ||||
|   endif | ||||
|   if len(sorted) | ||||
|     call add(lines, 'Press <CR> on a solution to accept') | ||||
|   endif | ||||
|   for solution in sorted | ||||
|     let lines += [s:separator] + split(solution.displayText, "\n", 1) | ||||
|   endfor | ||||
|   try | ||||
|     call setbufvar(bufnr, '&modifiable', 1) | ||||
|     call setbufvar(bufnr, '&readonly', 0) | ||||
|     call setbufline(bufnr, 1, lines) | ||||
|   finally | ||||
|     call setbufvar(bufnr, '&modifiable', 0) | ||||
|     call setbufvar(bufnr, '&readonly', 1) | ||||
|   endtry | ||||
| endfunction | ||||
|  | ||||
| function! copilot#panel#Solution(params, ...) abort | ||||
|   let state = getbufvar('^' . a:params.panelId . '$', 'copilot_panel') | ||||
|   if !bufloaded(a:params.panelId) || type(state) != v:t_dict | ||||
|     return | ||||
|   endif | ||||
|   let state.solutions[a:params.solutionId] = a:params | ||||
|   call s:Render(a:params.panelId) | ||||
| endfunction | ||||
|  | ||||
| function! copilot#panel#SolutionsDone(params, ...) abort | ||||
|   let state = getbufvar('^' . a:params.panelId . '$', 'copilot_panel') | ||||
|   if !bufloaded(a:params.panelId) || type(state) != v:t_dict | ||||
|     call copilot#logger#Debug('SolutionsDone: ' . a:params.panelId) | ||||
|     return | ||||
|   endif | ||||
|   let state.status = get(a:params, 'message', '') | ||||
|   call s:Render(a:params.panelId) | ||||
| endfunction | ||||
|  | ||||
| function! copilot#panel#Accept(...) abort | ||||
|   let state = get(b:, 'copilot_panel', {}) | ||||
|   let solutions = s:Solutions(state) | ||||
|   if empty(solutions) | ||||
|     return '' | ||||
|   endif | ||||
|   if !has_key(state, 'bufnr') || !bufloaded(get(state, 'bufnr', -1)) | ||||
|     return "echoerr 'Buffer was closed'" | ||||
|   endif | ||||
|   let at = a:0 ? a:1 : line('.') | ||||
|   let solution_index = 0 | ||||
|   for lnum in range(1, at) | ||||
|     if getline(lnum) ==# s:separator | ||||
|       let solution_index += 1 | ||||
|     endif | ||||
|   endfor | ||||
|   if solution_index > 0 && solution_index <= len(solutions) | ||||
|     let solution = solutions[solution_index - 1] | ||||
|     let lnum = solution.range.start.line + 1 | ||||
|     if getbufline(state.bufnr, lnum) !=# [state.line] | ||||
|       return 'echoerr "Buffer has changed since synthesizing solution"' | ||||
|     endif | ||||
|     let lines = split(solution.displayText, "\n", 1) | ||||
|     let old_first = getline(solution.range.start.line + 1) | ||||
|     let lines[0] = strpart(old_first, 0, copilot#doc#UTF16ToByteIdx(old_first, solution.range.start.character)) . lines[0] | ||||
|     let old_last = getline(solution.range.end.line + 1) | ||||
|     let lines[-1] .= strpart(old_last, copilot#doc#UTF16ToByteIdx(old_last, solution.range.start.character)) | ||||
|     call setbufline(state.bufnr, solution.range.start.line + 1, lines[0]) | ||||
|     call appendbufline(state.bufnr, solution.range.start.line + 1, lines[1:-1]) | ||||
|     call copilot#Request('notifyAccepted', {'uuid': solution.solutionId}) | ||||
|     bwipeout | ||||
|     let win = bufwinnr(state.bufnr) | ||||
|     if win > 0 | ||||
|       exe win . 'wincmd w' | ||||
|       exe solution.range.start.line + len(lines) | ||||
|       if state.was_insert | ||||
|         startinsert! | ||||
|       else | ||||
|         normal! $ | ||||
|       endif | ||||
|     endif | ||||
|   endif | ||||
|   return '' | ||||
| endfunction | ||||
|  | ||||
| function! s:Initialize(state) abort | ||||
|   let &l:filetype = 'copilot' . (empty(a:state.filetype) ? '' : '.' . a:state.filetype) | ||||
|   let &l:tabstop = a:state.tabstop | ||||
|   call clearmatches() | ||||
|   call matchadd('CopilotSuggestion', '\C^' . s:separator . '\n\zs' . escape(a:state.line, '][^$.*\~'), 10, 4) | ||||
|   nmap <buffer><script> <CR> <Cmd>exe copilot#panel#Accept()<CR> | ||||
|   nmap <buffer><script> [[ <Cmd>call search('^─\{9,}\n.', 'bWe')<CR> | ||||
|   nmap <buffer><script> ]] <Cmd>call search('^─\{9,}\n.', 'We')<CR> | ||||
| endfunction | ||||
|  | ||||
| function! s:BufReadCmd() abort | ||||
|   setlocal bufhidden=wipe buftype=nofile nobuflisted readonly nomodifiable | ||||
|   let state = get(b:, 'copilot_panel') | ||||
|   if type(state) != v:t_dict | ||||
|     return | ||||
|   endif | ||||
|   call s:Initialize(state) | ||||
|   call s:Render(expand('<amatch>')) | ||||
|   return '' | ||||
| endfunction | ||||
|  | ||||
| function! copilot#panel#Open(opts) abort | ||||
|   let s:panel_id += 1 | ||||
|   let state = {'solutions': {}, 'filetype': &filetype, 'line': getline('.'), 'bufnr': bufnr(''), 'tabstop': &tabstop} | ||||
|   let bufname = 'copilot:///' . s:panel_id | ||||
|   let params = copilot#doc#Params({'panelId': bufname}) | ||||
|   let state.was_insert = mode() =~# '^[iR]' | ||||
|   if state.was_insert | ||||
|     stopinsert | ||||
|   else | ||||
|     let params.doc.position.character = copilot#doc#UTF16Width(state.line) | ||||
|     let params.position.character = params.doc.position.character | ||||
|   endif | ||||
|   let response = copilot#Request('getPanelCompletions', params).Wait() | ||||
|   if response.status ==# 'error' | ||||
|     return 'echoerr ' . string(response.error.message) | ||||
|   endif | ||||
|   let state.count_target = response.result.solutionCountTarget | ||||
|   exe substitute(a:opts.mods, '\C\<tab\>', '-tab', 'g') 'keepalt split' bufname | ||||
|   let b:copilot_panel = state | ||||
|   call s:Initialize(state) | ||||
|   call s:Render(@%) | ||||
|   return '' | ||||
| endfunction | ||||
|  | ||||
| augroup github_copilot_panel | ||||
|   autocmd! | ||||
|   autocmd BufReadCmd copilot:///* exe s:BufReadCmd() | ||||
| augroup END | ||||
		Reference in New Issue
	
	Block a user
	 Amir
					Amir