Add tcp feature (#985)

* Add tcp feature

* Update doc

* Update async.vim embed

* Update doc
This commit is contained in:
mattn
2021-01-01 01:28:06 +09:00
committed by GitHub
parent 5743ae2110
commit ee854b4c55
4 changed files with 98 additions and 36 deletions

View File

@@ -412,30 +412,41 @@ function! s:ensure_start(buf, server_name, cb) abort
return
endif
let l:cmd_type = type(l:server_info['cmd'])
if l:cmd_type == v:t_list
let l:cmd = l:server_info['cmd']
else
let l:cmd = l:server_info['cmd'](l:server_info)
if has_key(l:server_info, 'tcp')
let l:tcp = l:server_info['tcp'](l:server_info)
let l:lsp_id = lsp#client#start({
\ 'tcp': l:tcp,
\ 'on_stderr': function('s:on_stderr', [a:server_name]),
\ 'on_exit': function('s:on_exit', [a:server_name]),
\ 'on_notification': function('s:on_notification', [a:server_name]),
\ 'on_request': function('s:on_request', [a:server_name]),
\ })
elseif has_key(l:server_info, 'cmd')
let l:cmd_type = type(l:server_info['cmd'])
if l:cmd_type == v:t_list
let l:cmd = l:server_info['cmd']
else
let l:cmd = l:server_info['cmd'](l:server_info)
endif
if empty(l:cmd)
let l:msg = s:new_rpc_error('ignore server start since cmd is empty', { 'server_name': a:server_name })
call lsp#log(l:msg)
call a:cb(l:msg)
return
endif
call lsp#log('Starting server', a:server_name, l:cmd)
let l:lsp_id = lsp#client#start({
\ 'cmd': l:cmd,
\ 'on_stderr': function('s:on_stderr', [a:server_name]),
\ 'on_exit': function('s:on_exit', [a:server_name]),
\ 'on_notification': function('s:on_notification', [a:server_name]),
\ 'on_request': function('s:on_request', [a:server_name]),
\ })
endif
if empty(l:cmd)
let l:msg = s:new_rpc_error('ignore server start since cmd is empty', { 'server_name': a:server_name })
call lsp#log(l:msg)
call a:cb(l:msg)
return
endif
call lsp#log('Starting server', a:server_name, l:cmd)
let l:lsp_id = lsp#client#start({
\ 'cmd': l:cmd,
\ 'on_stderr': function('s:on_stderr', [a:server_name]),
\ 'on_exit': function('s:on_exit', [a:server_name]),
\ 'on_notification': function('s:on_notification', [a:server_name]),
\ 'on_request': function('s:on_request', [a:server_name]),
\ })
if l:lsp_id > 0
let l:server['lsp_id'] = l:lsp_id
let l:msg = s:new_rpc_success('started lsp server successfully', { 'server_name': a:server_name, 'lsp_id': l:lsp_id })

View File

@@ -183,16 +183,22 @@ function! s:on_exit(id, status, event) abort
endfunction
function! s:lsp_start(opts) abort
if !has_key(a:opts, 'cmd')
if has_key(a:opts, 'cmd')
let l:client_id = lsp#utils#job#start(a:opts.cmd, {
\ 'on_stdout': function('s:on_stdout'),
\ 'on_stderr': function('s:on_stderr'),
\ 'on_exit': function('s:on_exit'),
\ })
elseif has_key(a:opts, 'tcp')
let l:client_id = lsp#utils#job#connect(a:opts.tcp, {
\ 'on_stdout': function('s:on_stdout'),
\ 'on_stderr': function('s:on_stderr'),
\ 'on_exit': function('s:on_exit'),
\ })
else
return -1
endif
let l:client_id = lsp#utils#job#start(a:opts.cmd, {
\ 'on_stdout': function('s:on_stdout'),
\ 'on_stderr': function('s:on_stderr'),
\ 'on_exit': function('s:on_exit'),
\ })
let l:ctx = s:create_context(l:client_id, a:opts)
let l:ctx['id'] = l:client_id

View File

@@ -1,4 +1,4 @@
" https://github.com/prabirshrestha/async.vim#d15123af3483350e235397116b554cb37e705130 (dirty)
" https://github.com/prabirshrestha/async.vim#236debf1a68d69a74f1f6647c273b0477e1ec1bf (dirty)
" :AsyncEmbed path=./autoload/lsp/utils/job.vim namespace=lsp#utils#job
" Author: Prabir Shrestha <mail at prabir dot me>
@@ -195,7 +195,11 @@ function! s:job_stop(jobid) abort
" silently for 'E900: Invalid job id' exception
endtry
elseif l:jobinfo.type == s:job_type_vimjob
call job_stop(s:jobs[a:jobid].job)
if type(s:jobs[a:jobid].job) == v:t_job
call job_stop(s:jobs[a:jobid].job)
elseif type(s:jobs[a:jobid].job) == v:t_channel
call ch_close(s:jobs[a:jobid].job)
endif
endif
endif
endfunction
@@ -306,6 +310,21 @@ function! s:job_pid(jobid) abort
return 0
endfunction
function! s:callback_cb(jobid, opts, ch, data) abort
if has_key(a:opts, 'on_stdout')
call a:opts.on_stdout(a:jobid, split(a:data, "\n", 1), 'stdout')
endif
endfunction
function! s:close_cb(jobid, opts, ch) abort
if has_key(a:opts, 'on_exit')
call a:opts.on_exit(a:jobid, 'closed', 'exit')
endif
if has_key(s:jobs, a:jobid)
call remove(s:jobs, a:jobid)
endif
endfunction
" public apis {{{
function! lsp#utils#job#start(cmd, opts) abort
return s:job_start(a:cmd, a:opts)
@@ -328,6 +347,33 @@ endfunction
function! lsp#utils#job#pid(jobid) abort
return s:job_pid(a:jobid)
endfunction
function! lsp#utils#job#connect(addr, opts) abort
let s:jobidseq = s:jobidseq + 1
let l:jobid = s:jobidseq
let l:retry = 0
while l:retry < 5
let l:ch = ch_open(a:addr, {'waittime': 1000})
call ch_setoptions(l:ch, {
\ 'callback': function('s:callback_cb', [l:jobid, a:opts]),
\ 'close_cb': function('s:close_cb', [l:jobid, a:opts]),
\ 'mode': 'raw',
\})
if ch_status(l:ch) ==# 'open'
break
endif
sleep 100m
let l:retry += 1
endwhile
let s:jobs[l:jobid] = {
\ 'type': s:job_type_vimjob,
\ 'opts': a:opts,
\ 'job': l:ch,
\ 'channel': l:ch,
\ 'buffer': ''
\}
return l:jobid
endfunction
" }}}
let &cpo = s:save_cpo

View File

@@ -220,15 +220,14 @@ on pyls (https://github.com/palantir/python-language-server)
augroup END
<
TCP SERVERS *vim-lsp-tcp*
You can use netcat to connect to LSP servers that don't support stdio, but do
support TCP. Set your cmd to use your netcat executable (`nc` on unix-likes),
localhost, and your server's port. The Godot game engine uses 6008 as its LSP
port and godot ftplugins define gdscript or gdscript3 filetype: >
You can use tcp to connect to LSP servers that don't support stdio. Set host
and port to tcp. The Godot game engine uses 6008 as its LSP port and godot
ftplugins define gdscript or gdscript3 filetype: >
au User lsp_setup
\ call lsp#register_server({
\ 'name': 'godot',
\ 'cmd': ["nc", "localhost", "6008"],
\ 'tcp': "localhost:6008",
\ 'allowlist': ['gdscript3', 'gdscript']
\ })
>