@@ -70,7 +70,11 @@ function! s:RejectRequest(request, error) abort
7070endfunction
7171
7272function ! s: AfterInitialized (fn, ... ) dict abort
73- call add (self .after_initialized, function (a: fn , a: 000 ))
73+ call add (self .after_initialized, function (a: fn , [self ] + a: 000 ))
74+ endfunction
75+
76+ function ! s: AlreadyInitialized (fn, ... ) dict abort
77+ return copilot#util#Defer (function (a: fn , [self ] + a: 000 ))
7478endfunction
7579
7680function ! s: Send (instance, request) abort
@@ -94,7 +98,7 @@ endfunction
9498
9599function ! s: VimNotify (method, params) dict abort
96100 let request = {' method' : a: method , ' params' : a: params }
97- call self .AfterInitialized (function (' s:Send' , [ self , request]) )
101+ call self .AfterInitialized (function (' s:Send' ), request)
98102endfunction
99103
100104function ! s: RequestWait () dict abort
@@ -269,7 +273,7 @@ function! s:VimRequest(method, params, ...) dict abort
269273 let params = deepcopy (a: params )
270274 let [_, progress] = s: PreprocessParams (self , params)
271275 let request = call (' s:SetUpRequest' , [self , s: id , a: method , params, progress] + a: 000 )
272- call self .AfterInitialized (function (' s:SendRequest' , [ self , request]) )
276+ call self .AfterInitialized (function (' s:SendRequest' ), request)
273277 let self .requests[s: id ] = request
274278 return request
275279endfunction
@@ -369,6 +373,15 @@ function! s:OnErr(instance, ch, line, ...) abort
369373 endif
370374endfunction
371375
376+ function ! s: FlushAfterInitialized (instance) abort
377+ if has_key (a: instance , ' after_initialized' )
378+ let a: instance .AfterInitialized = function (' s:AlreadyInitialized' )
379+ for Fn in remove (a: instance , ' after_initialized' )
380+ call copilot#util#Defer (Fn)
381+ endfor
382+ endif
383+ endfunction
384+
372385function ! s: OnExit (instance, code, ... ) abort
373386 let a: instance .exit_status = a: code
374387 if has_key (a: instance , ' job' )
@@ -389,12 +402,7 @@ function! s:OnExit(instance, code, ...) abort
389402 for id in sort (keys (a: instance .requests), { a , b - > + a > + b })
390403 call s: RejectRequest (remove (a: instance .requests, id), s: error_exit )
391404 endfor
392- if has_key (a: instance , ' after_initialized' )
393- let a: instance .AfterInitialized = function (' copilot#util#Defer' )
394- for Fn in remove (a: instance , ' after_initialized' )
395- call copilot#util#Defer (Fn)
396- endfor
397- endif
405+ call s: FlushAfterInitialized (a: instance )
398406 call copilot#util#Defer ({ - > get (s: instances , a: instance .id) is # a: instance ? remove (s: instances , a: instance .id) : {} })
399407 if a: code == 0
400408 call copilot#logger#Info (message)
@@ -444,7 +452,7 @@ function! s:NvimRequest(method, params, ...) dict abort
444452 let params = deepcopy (a: params )
445453 let [bufnr , progress] = s: PreprocessParams (self , params)
446454 let request = call (' s:SetUpRequest' , [self , v: null , a: method , params, progress] + a: 000 )
447- call self .AfterInitialized (function (' s:NvimDoRequest' , [ self , request, bufnr ]) )
455+ call self .AfterInitialized (function (' s:NvimDoRequest' ), request, bufnr )
448456 return request
449457endfunction
450458
@@ -473,11 +481,11 @@ function! s:NvimClose() dict abort
473481endfunction
474482
475483function ! s: NvimNotify (method, params) dict abort
476- call self .AfterInitialized (function (' s:NvimDoNotify' , [ self .client_id, a: method , a: params]) )
484+ call self .AfterInitialized (function (' s:NvimDoNotify' ), a: method , a: params )
477485endfunction
478486
479- function ! s: NvimDoNotify (client_id , method, params) abort
480- return eval (" v:lua.require'_copilot'.rpc_notify(a:client_id , a:method, a:params)" )
487+ function ! s: NvimDoNotify (client , method, params) abort
488+ return eval (" v:lua.require'_copilot'.rpc_notify(a:client.id , a:method, a:params)" )
481489endfunction
482490
483491function ! copilot#client#LspHandle (id, request) abort
@@ -488,7 +496,19 @@ function! copilot#client#LspHandle(id, request) abort
488496endfunction
489497
490498function ! s: PackageVersion () abort
491- return json_decode (join (readfile (s: root . ' /copilot-language-server/package.json' ))).version
499+ try
500+ return json_decode (join (readfile (s: root . ' /copilot-language-server/package.json' ))).version
501+ catch
502+ endtry
503+ return ' '
504+ endfunction
505+
506+ function ! s: GetCommand (var , default) abort
507+ let cmd = get (g: , a: var , ' ' )
508+ if type (cmd) == type (' ' ) && ! empty (cmd)
509+ return [expand (cmd)]
510+ endif
511+ return type (cmd) == v: t_list && ! empty (cmd) ? copy (cmd) : a: default
492512endfunction
493513
494514let s: script_name = ' copilot-language-server/dist/language-server.js'
@@ -497,11 +517,14 @@ function! s:Command() abort
497517 if ! has (' nvim-0.8' ) && v: version < 900
498518 return [[], [], ' Vim version too old' ]
499519 endif
500- let script = get (g: , ' copilot_command' , [])
501- if type (script ) == type (' ' )
502- let script = empty (script ) ? [] : [expand (script )]
520+ let script = s: GetCommand (' copilot_command' , [])
521+ let npx = get (g: , ' copilot_version' , get (g: , ' copilot_npx' , v: null ))
522+ if npx is # v: null
523+ let npx = empty (script ) && ! empty (get (g: , ' copilot_npx_command' , 1 )) ? v: true : v: false
524+ endif
525+ if type (npx) != v: t_string && ! empty (npx)
526+ let npx = ' '
503527 endif
504- let npx = get (g: , ' copilot_npx' , v: false )
505528 if type (npx) == v: t_string
506529 if empty (npx)
507530 let npx = ' ^'
@@ -513,11 +536,17 @@ function! s:Command() abort
513536 let npx = s: pkg_name . npx
514537 endif
515538 if npx = ~# ' @[~<>=^]\+$'
516- let npx .= s: PackageVersion ()
539+ let pkg_version = s: PackageVersion ()
540+ if pkg_version = ~# ' ^[1-9]'
541+ let npx .= pkg_version
542+ else
543+ let npx = substitute (npx, ' @[=~]$' , ' @^' , ' ' ) . ' 1.0.0'
544+ endif
545+ endif
546+ let script = s: GetCommand (' copilot_npx_command' , [' npx' ]) + [npx]
547+ if ! executable (script [0 ])
548+ let script = []
517549 endif
518- let script = [' npx' , npx]
519- elseif ! empty (npx)
520- let script = [' npx' , s: pkg_name . ' @^' . s: PackageVersion ()]
521550 endif
522551 if empty (script )
523552 let script = [s: root . ' /' . s: script_name ]
@@ -527,12 +556,7 @@ function! s:Command() abort
527556 elseif ! filereadable (script [0 ])
528557 return [[], [], ' Could not find ' . script [0 ]]
529558 endif
530- let node = get (g: , ' copilot_node_command' , ' ' )
531- if empty (node)
532- let node = [' node' ]
533- elseif type (node) == type (' ' )
534- let node = [expand (node)]
535- endif
559+ let node = s: GetCommand (' copilot_node_command' , [' node' ])
536560 if ! executable (get (node, 0 , ' ' ))
537561 if get (node, 0 , ' ' ) == # ' node'
538562 return [[], [], ' Node.js not found in PATH' ]
@@ -586,10 +610,7 @@ function! s:PostInit(result, instance) abort
586610 if ! has_key (a: instance , ' node_version' ) && has_key (a: result .serverInfo, ' nodeVersion' )
587611 let a: instance .node_version = a: result .serverInfo.nodeVersion
588612 endif
589- let a: instance .AfterInitialized = function (' copilot#util#Defer' )
590- for Fn in remove (a: instance , ' after_initialized' )
591- call copilot#util#Defer (Fn)
592- endfor
613+ call s: FlushAfterInitialized (a: instance )
593614endfunction
594615
595616function ! s: InitializeResult (result, instance) abort
@@ -615,6 +636,16 @@ function! s:StartupError() dict abort
615636 endif
616637endfunction
617638
639+ function ! s: VimDidChangeConfiguration () dict abort
640+ let settings = copilot#client#Settings ()
641+ return self .Notify (' workspace/didChangeConfiguration' , {' settings' : settings})
642+ endfunction
643+
644+ function ! s: NvimDidChangeConfiguration () dict abort
645+ let settings = copilot#client#Settings ()
646+ return eval (" v:lua.require'_copilot'.did_change_configuration(self.id, settings)" )
647+ endfunction
648+
618649function ! s: StatusNotification (params, instance) abort
619650 let a: instance .status = a: params
620651endfunction
@@ -666,6 +697,7 @@ function! copilot#client#New() abort
666697 \ ' IsAttached' : function (' s:False' ),
667698 \ ' Call' : function (' s:Call' ),
668699 \ ' Cancel' : function (' s:Cancel' ),
700+ \ ' DidChangeConfiguration' : function (' s:VimDidChangeConfiguration' ),
669701 \ ' StartupError' : function (' s:StartupError' ),
670702 \ }
671703 let instance.methods = copy (s: notifications )
@@ -674,6 +706,7 @@ function! copilot#client#New() abort
674706 let instance.id = -1
675707 let instance.startup_error = command_error
676708 call copilot#logger#Error (command_error)
709+ call s: FlushAfterInitialized (instance)
677710 return instance
678711 endif
679712 let instance.node = node
@@ -703,17 +736,38 @@ function! copilot#client#New() abort
703736 let instance.workspaceFolders[folder.uri] = v: true
704737 endfor
705738 call copilot#logger#Debug (' Spawning ' . join (command , ' ' ))
739+ let is_win_shell = has (' win32' ) && &shellcmdflag !~# ' ^-'
740+ if is_win_shell && command [0 ] !~# ' [\/]'
741+ let exepath = exepath (command [0 ])
742+ if exepath !~? ' \.exe$\|^$'
743+ let command [0 ] = fnamemodify (exepath , ' :t' )
744+ endif
745+ endif
706746 if has (' nvim' )
747+ if is_win_shell
748+ call map (command , { _, v - > substitute (v , ' \^' , ' ^^^^' , ' g' ) })
749+ endif
707750 call extend (instance, {
708751 \ ' Close' : function (' s:NvimClose' ),
709752 \ ' Notify' : function (' s:NvimNotify' ),
710753 \ ' Request' : function (' s:NvimRequest' ),
711754 \ ' Attach' : function (' s:NvimAttach' ),
755+ \ ' DidChangeConfiguration' : function (' s:NvimDidChangeConfiguration' ),
712756 \ ' IsAttached' : function (' s:NvimIsAttached' ),
713757 \ })
714- let instance.client_id = eval (" v:lua.require'_copilot'.lsp_start_client(command, instance.name, keys(instance.methods), opts, settings)" )
758+ let id = eval (" v:lua.require'_copilot'.lsp_start_client(command, instance.name, keys(instance.methods), opts, settings)" )
759+ if id is # v: null
760+ let instance.id = -1
761+ let instance.startup_error = ' Neovim failed to start LSP client'
762+ call s: FlushAfterInitialized (instance)
763+ return instance
764+ endif
765+ let instance.client_id = id
715766 let instance.id = instance.client_id
716767 else
768+ if is_win_shell
769+ let command = join (map (command , { _, v - > v = ~# ' [;&|^ ]' ? ' "' . v . ' "' : v }), ' ' )
770+ endif
717771 call extend (instance, {
718772 \ ' Close' : function (' s:VimClose' ),
719773 \ ' Notify' : function (' s:VimNotify' ),
0 commit comments