convert to unix lineendings

This commit is contained in:
Prabir Shrestha
2016-12-23 22:18:06 -08:00
parent cbb25285f8
commit b00348017c
3 changed files with 295 additions and 295 deletions

42
LICENSE
View File

@@ -1,21 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Prabir Shrestha
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
The MIT License (MIT)
Copyright (c) 2016 Prabir Shrestha
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

120
README.md
View File

@@ -1,60 +1,60 @@
vim-lsp (experimental)
======================
Async [Language Server Protocol](https://github.com/Microsoft/language-server-protocol) plugin for vim8 and neovim.
Internally vim-lsp uses [async.vim](https://github.com/prabirshrestha/async.vim).
Language Server Protocol VIM Client usage
=========================================
Sample usage talking with `langserver-go`
```vim
function! s:on_stderr(id, data, event)
echom 'lsp('.a:id.'):stderr:'.join(a:data, "\r\n")
endfunction
function! s:on_exit(id, status, event)
echom 'lsp('.a:id.'):exit:'.a:status
endfunction
function! s:on_notification(id, data, event)
if lsp#lspClient#is_error(a:data.response)
echom 'lsp('.a:id.'):notification:notification error receieved for '.a:data.request.method
elseif lsp#lspClient#is_server_instantiated_notification(a:data)
" request key will not be present in a:data
" make sure to check before accessing a:data.request in order to prevent unhandled errors
echom 'lsp('.a:id.'):notification:notification success receieved for '.json_encode(a:data.response)
else
echom 'lsp('.a:id.'):notification:notification success receieved for '.a:data.request.method
endif
endfunction
function! s:on_notification1(id, data, event)
echom 'lsp('.a:id.'):notification1:'json_encode(a:data)
endfunction
" go get github.com/sourcegraph/go-langserver/langserver/cmd/langserver-go
let g:lsp_id = lsp#lspClient#start({
\ 'cmd': ['langserver-go', '-trace', '-logfile', expand('~/Desktop/langserver-go.log')],
\ 'on_stderr': function('s:on_stderr'),
\ 'on_exit': function('s:on_exit'),
\ 'on_notification': function('s:on_notification')
\ })
if g:lsp_id > 0
echom 'lsp server running'
call lsp#lspClient#send(g:lsp_id, {
\ 'method': 'initialize',
\ 'params': {
\ 'capabilities': {},
\ 'rootPath': 'file:///D:/go/src/github.com/nsf/gocode'
\ },
\ 'on_notification': function('s:on_notification1')
\ })
else
echom 'failed to start lsp server'
endif
" call lsp#lspClient#stop(g:lsp_id)
```
vim-lsp (experimental)
======================
Async [Language Server Protocol](https://github.com/Microsoft/language-server-protocol) plugin for vim8 and neovim.
Internally vim-lsp uses [async.vim](https://github.com/prabirshrestha/async.vim).
Language Server Protocol VIM Client usage
=========================================
Sample usage talking with `langserver-go`
```vim
function! s:on_stderr(id, data, event)
echom 'lsp('.a:id.'):stderr:'.join(a:data, "\r\n")
endfunction
function! s:on_exit(id, status, event)
echom 'lsp('.a:id.'):exit:'.a:status
endfunction
function! s:on_notification(id, data, event)
if lsp#lspClient#is_error(a:data.response)
echom 'lsp('.a:id.'):notification:notification error receieved for '.a:data.request.method
elseif lsp#lspClient#is_server_instantiated_notification(a:data)
" request key will not be present in a:data
" make sure to check before accessing a:data.request in order to prevent unhandled errors
echom 'lsp('.a:id.'):notification:notification success receieved for '.json_encode(a:data.response)
else
echom 'lsp('.a:id.'):notification:notification success receieved for '.a:data.request.method
endif
endfunction
function! s:on_notification1(id, data, event)
echom 'lsp('.a:id.'):notification1:'json_encode(a:data)
endfunction
" go get github.com/sourcegraph/go-langserver/langserver/cmd/langserver-go
let g:lsp_id = lsp#lspClient#start({
\ 'cmd': ['langserver-go', '-trace', '-logfile', expand('~/Desktop/langserver-go.log')],
\ 'on_stderr': function('s:on_stderr'),
\ 'on_exit': function('s:on_exit'),
\ 'on_notification': function('s:on_notification')
\ })
if g:lsp_id > 0
echom 'lsp server running'
call lsp#lspClient#send(g:lsp_id, {
\ 'method': 'initialize',
\ 'params': {
\ 'capabilities': {},
\ 'rootPath': 'file:///D:/go/src/github.com/nsf/gocode'
\ },
\ 'on_notification': function('s:on_notification1')
\ })
else
echom 'failed to start lsp server'
endif
" call lsp#lspClient#stop(g:lsp_id)
```

View File

@@ -1,214 +1,214 @@
let s:save_cpo = &cpo
set cpo&vim
let s:lsp_clients = {} " { id, opts, req_seq, on_notifications: { request, on_notification }, stdout: { max_buffer_size, buffer, content_length, headers } }
let s:lsp_default_max_buffer = -1
let s:lsp_text_document_sync_kind_none = 0
let s:lsp_text_document_sync_kind_full = 1
let s:lsp_text_document_sync_kind_incremental = 2
function! s:trim(str) abort
return matchstr(a:str,'^\s*\zs.\{-}\ze\s*$')
endfunction
function! s:_on_lsp_stdout(id, data, event)
if has_key(s:lsp_clients, a:id)
let l:client = s:lsp_clients[a:id]
let l:client.stdout.buffer .= join(a:data, "\n")
if l:client.stdout.max_buffer_size != -1 && len(l:client.stdout.buffer) > l:client.stdout.max_buffer_size
echom 'lsp: reached max buffer size'
call lsp#utils#job#stop(a:id)
endif
while 1
if l:client.stdout.content_length == -1 " if content-length is -1 we haven't parsed the headers
" wait for all the headers to arrive
let l:header_end_index = stridx(l:client.stdout.buffer, "\r\n\r\n")
if l:header_end_index >= 0
for l:header in split(l:client.stdout.buffer[:l:header_end_index - 1], "\r\n")
let l:header_key_value_seperator = stridx(l:header, ":")
let l:header_key = s:trim(l:header[:l:header_key_value_seperator - 1])
let l:header_value = s:trim(l:header[l:header_key_value_seperator + 1:])
if l:header_key ==? 'Content-Length'
let l:client.stdout.content_length = str2nr(l:header_value, 10)
endif
let l:client.stdout.headers[l:header_key] = s:trim(l:header_value)
endfor
let l:client.stdout.buffer = l:client.stdout.buffer[l:header_end_index + 4:]
continue
else
" wait for next buffer to arrive
break
endif
else
if len(l:client.stdout.buffer) >= l:client.stdout.content_length
" we have the full message
let l:response_str = l:client.stdout.buffer[:l:client.stdout.content_length - 1]
let l:client.stdout.buffer = l:client.stdout.buffer[l:client.stdout.content_length:]
let l:client.stdout.content_length = -1 " reset since we are done reading the current message
let l:response_msg = json_decode(l:response_str)
if has_key(l:response_msg, 'id')
let l:on_notification_data = { 'response': l:response_msg }
if has_key(l:client.on_notifications, l:response_msg.id)
" requests are absent for server instantiated events
let l:on_notification_data.request = l:client.on_notifications[l:response_msg.id].request
endif
if has_key(l:client.opts, 'on_notification')
call l:client.opts.on_notification(a:id, l:on_notification_data, 'on_notification')
endif
if has_key(l:client.on_notifications, 'on_notification')
call l:client.on_notifications[l:response_msg.id](a:id, l:on_notification_data, 'on_notification')
endif
if has_key(l:client.on_notifications, l:response_msg.id)
" requests are absent for server instantiated events
call remove(l:client.on_notifications, l:response_msg.id)
endif
endif
if len(l:client.stdout.buffer) > 0
" we have more data in the buffer so try parsing the new headers from top
continue
else
" we are done processing the message here so stop
break
endif
else
" we don't have the entire message body, so wait for the next buffer
break
endif
endif
endwhile
endif
endfunction
function! s:_on_lsp_stderr(id, data, event)
if has_key(s:lsp_clients, a:id)
let l:client = s:lsp_clients[a:id]
if has_key(l:client.opts, 'on_stderr')
call l:client.opts.on_stderr(a:id, a:data, a:event)
endif
endif
endfunction
function! s:_on_lsp_exit(id, status, event)
if has_key(s:lsp_clients, a:id)
let l:client = s:lsp_clients[a:id]
if has_key(l:client.opts, 'on_exit')
call l:client.opts.on_exit(a:id, a:status, a:event)
endif
endif
endfunction
function! s:lsp_start(opts)
if !has_key(a:opts, 'cmd')
return -1
endif
let l:lsp_client_id = lsp#utils#job#start(a:opts.cmd, {
\ 'on_stdout': function('s:_on_lsp_stdout'),
\ 'on_stderr': function('s:_on_lsp_stderr'),
\ 'on_exit': function('s:_on_lsp_exit'),
\ })
let l:max_buffer_size = s:lsp_default_max_buffer
if has_key(a:opts, 'max_buffer_size')
let l:max_buffer_size = a:opts.max_buffer_size
endif
let s:lsp_clients[l:lsp_client_id] = {
\ 'id': l:lsp_client_id,
\ 'opts': a:opts,
\ 'req_seq': 0,
\ 'on_notifications': {},
\ 'stdout': {
\ 'max_buffer_size': l:max_buffer_size,
\ 'buffer': '',
\ 'content_length': -1,
\ 'headers': {}
\ },
\ }
return l:lsp_client_id
endfunction
function! s:lsp_stop(id)
call lsp#utils#job#stop(a:id)
endfunction
function! s:lsp_send_request(id, opts) " opts = { method, params?, on_notification }
if has_key(s:lsp_clients, a:id)
let l:client = s:lsp_clients[a:id]
let l:client.req_seq = l:client.req_seq + 1
let l:req_seq = l:client.req_seq
let l:msg = { 'jsonrpc': '2.0', 'id': l:req_seq, 'method': a:opts.method }
if has_key(a:opts, 'params')
let l:msg.params = a:opts.params
endif
let l:json = json_encode(l:msg)
let l:req_data = 'Content-Length: ' . len(l:json) . "\r\n\r\n" . l:json
let l:client.on_notifications[l:req_seq] = { 'request': l:msg }
if has_key(a:opts, 'on_notification')
let l:client.on_notifications[l:req_seq].on_notification = a:opts.on_notification
endif
call lsp#utils#job#send(l:client.id, l:req_data)
return l:req_seq
else
return -1
endif
endfunction
function! s:lsp_get_last_request_id(id)
return s:lsp_clients[a:id].req_seq
endfunction
function! s:lsp_is_error(notification)
return has_key(a:notification, 'error')
endfunction
function! s:is_server_instantiated_notification(notification)
return !has_key(a:notification, 'request')
endfunction
" public apis {{{
let lsp#lspClient#text_document_sync_kind_none = s:lsp_text_document_sync_kind_none
let lsp#lspClient#text_document_sync_kind_full = s:lsp_text_document_sync_kind_full
let lsp#lspClient#text_document_sync_kind_incremental = s:lsp_text_document_sync_kind_incremental
function! lsp#lspClient#start(opts)
return s:lsp_start(a:opts)
endfunction
function! lsp#lspClient#stop(client_id)
return s:lsp_stop(a:client_id)
endfunction
function! lsp#lspClient#send(client_id, opts)
return s:lsp_send_request(a:client_id, a:opts)
endfunction
function! lsp#lspClient#get_last_request_id(client_id)
return s:lsp_get_last_request_id(a:client_id)
endfunction
function! lsp#lspClient#is_error(notification)
return s:lsp_is_error(a:notification)
endfunction
function! lsp#lspClient#is_server_instantiated_notification(notification)
return s:is_server_instantiated_notification(a:notification)
endfunction
" }}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim sw=4 ts=4 et
let s:save_cpo = &cpo
set cpo&vim
let s:lsp_clients = {} " { id, opts, req_seq, on_notifications: { request, on_notification }, stdout: { max_buffer_size, buffer, content_length, headers } }
let s:lsp_default_max_buffer = -1
let s:lsp_text_document_sync_kind_none = 0
let s:lsp_text_document_sync_kind_full = 1
let s:lsp_text_document_sync_kind_incremental = 2
function! s:trim(str) abort
return matchstr(a:str,'^\s*\zs.\{-}\ze\s*$')
endfunction
function! s:_on_lsp_stdout(id, data, event)
if has_key(s:lsp_clients, a:id)
let l:client = s:lsp_clients[a:id]
let l:client.stdout.buffer .= join(a:data, "\n")
if l:client.stdout.max_buffer_size != -1 && len(l:client.stdout.buffer) > l:client.stdout.max_buffer_size
echom 'lsp: reached max buffer size'
call lsp#utils#job#stop(a:id)
endif
while 1
if l:client.stdout.content_length == -1 " if content-length is -1 we haven't parsed the headers
" wait for all the headers to arrive
let l:header_end_index = stridx(l:client.stdout.buffer, "\r\n\r\n")
if l:header_end_index >= 0
for l:header in split(l:client.stdout.buffer[:l:header_end_index - 1], "\r\n")
let l:header_key_value_seperator = stridx(l:header, ":")
let l:header_key = s:trim(l:header[:l:header_key_value_seperator - 1])
let l:header_value = s:trim(l:header[l:header_key_value_seperator + 1:])
if l:header_key ==? 'Content-Length'
let l:client.stdout.content_length = str2nr(l:header_value, 10)
endif
let l:client.stdout.headers[l:header_key] = s:trim(l:header_value)
endfor
let l:client.stdout.buffer = l:client.stdout.buffer[l:header_end_index + 4:]
continue
else
" wait for next buffer to arrive
break
endif
else
if len(l:client.stdout.buffer) >= l:client.stdout.content_length
" we have the full message
let l:response_str = l:client.stdout.buffer[:l:client.stdout.content_length - 1]
let l:client.stdout.buffer = l:client.stdout.buffer[l:client.stdout.content_length:]
let l:client.stdout.content_length = -1 " reset since we are done reading the current message
let l:response_msg = json_decode(l:response_str)
if has_key(l:response_msg, 'id')
let l:on_notification_data = { 'response': l:response_msg }
if has_key(l:client.on_notifications, l:response_msg.id)
" requests are absent for server instantiated events
let l:on_notification_data.request = l:client.on_notifications[l:response_msg.id].request
endif
if has_key(l:client.opts, 'on_notification')
call l:client.opts.on_notification(a:id, l:on_notification_data, 'on_notification')
endif
if has_key(l:client.on_notifications, 'on_notification')
call l:client.on_notifications[l:response_msg.id](a:id, l:on_notification_data, 'on_notification')
endif
if has_key(l:client.on_notifications, l:response_msg.id)
" requests are absent for server instantiated events
call remove(l:client.on_notifications, l:response_msg.id)
endif
endif
if len(l:client.stdout.buffer) > 0
" we have more data in the buffer so try parsing the new headers from top
continue
else
" we are done processing the message here so stop
break
endif
else
" we don't have the entire message body, so wait for the next buffer
break
endif
endif
endwhile
endif
endfunction
function! s:_on_lsp_stderr(id, data, event)
if has_key(s:lsp_clients, a:id)
let l:client = s:lsp_clients[a:id]
if has_key(l:client.opts, 'on_stderr')
call l:client.opts.on_stderr(a:id, a:data, a:event)
endif
endif
endfunction
function! s:_on_lsp_exit(id, status, event)
if has_key(s:lsp_clients, a:id)
let l:client = s:lsp_clients[a:id]
if has_key(l:client.opts, 'on_exit')
call l:client.opts.on_exit(a:id, a:status, a:event)
endif
endif
endfunction
function! s:lsp_start(opts)
if !has_key(a:opts, 'cmd')
return -1
endif
let l:lsp_client_id = lsp#utils#job#start(a:opts.cmd, {
\ 'on_stdout': function('s:_on_lsp_stdout'),
\ 'on_stderr': function('s:_on_lsp_stderr'),
\ 'on_exit': function('s:_on_lsp_exit'),
\ })
let l:max_buffer_size = s:lsp_default_max_buffer
if has_key(a:opts, 'max_buffer_size')
let l:max_buffer_size = a:opts.max_buffer_size
endif
let s:lsp_clients[l:lsp_client_id] = {
\ 'id': l:lsp_client_id,
\ 'opts': a:opts,
\ 'req_seq': 0,
\ 'on_notifications': {},
\ 'stdout': {
\ 'max_buffer_size': l:max_buffer_size,
\ 'buffer': '',
\ 'content_length': -1,
\ 'headers': {}
\ },
\ }
return l:lsp_client_id
endfunction
function! s:lsp_stop(id)
call lsp#utils#job#stop(a:id)
endfunction
function! s:lsp_send_request(id, opts) " opts = { method, params?, on_notification }
if has_key(s:lsp_clients, a:id)
let l:client = s:lsp_clients[a:id]
let l:client.req_seq = l:client.req_seq + 1
let l:req_seq = l:client.req_seq
let l:msg = { 'jsonrpc': '2.0', 'id': l:req_seq, 'method': a:opts.method }
if has_key(a:opts, 'params')
let l:msg.params = a:opts.params
endif
let l:json = json_encode(l:msg)
let l:req_data = 'Content-Length: ' . len(l:json) . "\r\n\r\n" . l:json
let l:client.on_notifications[l:req_seq] = { 'request': l:msg }
if has_key(a:opts, 'on_notification')
let l:client.on_notifications[l:req_seq].on_notification = a:opts.on_notification
endif
call lsp#utils#job#send(l:client.id, l:req_data)
return l:req_seq
else
return -1
endif
endfunction
function! s:lsp_get_last_request_id(id)
return s:lsp_clients[a:id].req_seq
endfunction
function! s:lsp_is_error(notification)
return has_key(a:notification, 'error')
endfunction
function! s:is_server_instantiated_notification(notification)
return !has_key(a:notification, 'request')
endfunction
" public apis {{{
let lsp#lspClient#text_document_sync_kind_none = s:lsp_text_document_sync_kind_none
let lsp#lspClient#text_document_sync_kind_full = s:lsp_text_document_sync_kind_full
let lsp#lspClient#text_document_sync_kind_incremental = s:lsp_text_document_sync_kind_incremental
function! lsp#lspClient#start(opts)
return s:lsp_start(a:opts)
endfunction
function! lsp#lspClient#stop(client_id)
return s:lsp_stop(a:client_id)
endfunction
function! lsp#lspClient#send(client_id, opts)
return s:lsp_send_request(a:client_id, a:opts)
endfunction
function! lsp#lspClient#get_last_request_id(client_id)
return s:lsp_get_last_request_id(a:client_id)
endfunction
function! lsp#lspClient#is_error(notification)
return s:lsp_is_error(a:notification)
endfunction
function! lsp#lspClient#is_server_instantiated_notification(notification)
return s:is_server_instantiated_notification(a:notification)
endfunction
" }}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim sw=4 ts=4 et