vim-lsp
vim-lsp copied to clipboard
Merge hovers
On current implementation, hovers are shown per the servers.
call lsp#callbag#pipe(
\ lsp#callbag#fromList(l:servers),
\ lsp#callbag#flatMap({server->
\ lsp#request(server, l:request)
\ }),
\ lsp#callbag#tap({x->s:show_hover(l:ui, x['server_name'], x['request'], x['response'])}),
\ lsp#callbag#takeUntil(lsp#callbag#pipe(
\ lsp#stream(),
\ lsp#callbag#filter({x->has_key(x, 'command')}),
\ )),
\ lsp#callbag#subscribe(),
\ )
Hope to merge them.
@prabirshrestha I'm not good at callbag. Is there way to get all result of the pipes like below?
call lsp#callbag#pipe(
\ lsp#callbag#fromList(l:servers),
\ lsp#callbag#flatMap({server->
\ lsp#request(server, l:request)
\ }),
\ lsp#callbag#takeUntil(lsp#callbag#pipe(
\ lsp#stream(),
\ lsp#callbag#filter({x->has_key(x, 'command')}),
\ )),
\ lsp#callbag#subscribe({xx -> s:show_hovers(l:ui, xx)}),
\ )
There are different ways to solve this.
function! s:log(...) abort
echom json_encode(a:000)
endfunction
call callbag#pipe(
\ callbag#fromList([1, 2, 3]),
\ callbag#scan({acc, curr -> add(acc, curr)}, []),
\ callbag#tap({x->s:log('scan tap', x)}),
\ callbag#subscribe(),
\ )
call callbag#pipe(
\ callbag#fromList([1, 2, 3]),
\ callbag#reduce({acc, curr -> add(acc, curr)}, []),
\ callbag#tap({x->s:log('reduce tap', x)}),
\ callbag#subscribe(),
\ )
I would primarily use scan
operator for this. The reason I like scan
here is that it calls next
as we get the value including all the previous values without waiting for all requests to finish i.e. a slow server will not impact others.
reduce
works similar to scan
but it will wait for all to complete so a slow server may impact. Ideally we should have a toList()
that does this for you automatically but currently toList()
needs to be renamed to toBlockingList()
so we can create a new `toList(). I was delaying this rename until we need to use it.
I don't have a strong preference currently thought reduce
is lot easier to work with. We already use reduce
in codelens.
You can also create your own using create
function. Unlike vim9script, vim8 script doesn't support |inline-functions|
so you need to keep creating function outside.
function! s:create(next, error, complete) abort
call a:next(1)
call a:next(2)
call a:complete()
endfunction
call callbag#create(function('s:create'))
Some of the callbag.vim implementation could be quiet daunting and I have been thinking of using callbag-doki
style pattern instead. https://github.com/Epimodev/callbag-doki/blob/master/src/sources/index.ts.
RxJS docs are the best to refer to.
I tried to implement with reduce, but seems not work.
call lsp#callbag#pipe(
\ lsp#callbag#fromList(l:servers),
\ lsp#callbag#flatMap({server->
\ lsp#request(server, l:request)
\ }),
\ lsp#callbag#reduce({acc, curr -> add(acc, curr)}, []),
\ lsp#callbag#tap({xx->s:show_hovers(l:ui, xx)}),
\ lsp#callbag#takeUntil(lsp#callbag#pipe(
\ lsp#stream(),
\ lsp#callbag#filter({x->has_key(x, 'command')}),
\ )),
\ lsp#callbag#subscribe(),
\ )
function! s:show_hovers(ui, hovers) abort
echo ''
if s:FloatingWindow.is_available() && a:ui ==? 'float'
call s:show_floating_window(a:hovers)
else
call s:show_preview_window(a:hovers)
endif
endfunction
Length of a:hovers
always be 1.
:LspHover --server=gopls
and :LspHover --server=efm-langserver
for each commands seems to be working good.
Wondering if there is a bug with async ones.
In the mean can you try using scan
and make it behave similar to reduce
.
function! s:log(...) abort
echom json_encode(a:000)
endfunction
let s:seed = srand()
let s:inputArray = [1,2,3,4]
call callbag#pipe(
\ callbag#fromList(s:inputArray),
\ callbag#flatMap({x->
\ callbag#pipe(
\ callbag#of(x),
\ callbag#delay(rand(s:seed) % 1000),
\ )
\ }),
\ callbag#scan({acc,curr->add(acc, curr)}, []),
\ callbag#filter({x->len(x) == len(s:inputArray)}),
\ callbag#tap({x->s:log('tap', x)}),
\ callbag#subscribe(),
\ )
I tried simulating async functions with random delays and it does only call tap once with the final values. The same code with reduce
fails so seems like it currently only works with non async funcs.
You can share the efm config settings to configure gopls? I can try fixing reduce
.
You can also use group
which is going to be simpler.
function! s:log(...) abort
echom json_encode(a:000)
endfunction
let s:seed = srand()
let s:inputArray = [1,2,3,4]
call callbag#pipe(
\ callbag#fromList(s:inputArray),
\ callbag#flatMap({x->
\ callbag#pipe(
\ callbag#of(x),
\ callbag#delay(rand(s:seed) % 1000),
\ )
\ }),
\ callbag#group(len(s:inputArray)),
\ callbag#tap({x->s:log('tap', x)}),
\ callbag#subscribe(),
\ )
Hmm, I don't get it.
call lsp#callbag#pipe(
\ lsp#callbag#fromList(l:servers),
\ lsp#callbag#flatMap({server->
\ callbag#pipe(
\ lsp#request(server, l:request)
\ )
\ }),
\ lsp#callbag#takeUntil(lsp#callbag#pipe(
\ lsp#stream(),
\ lsp#callbag#filter({x->has_key(x, 'command')}),
\ )),
\ lsp#callbag#group(len(l:servers)),
\ lsp#callbag#tap({xx->s:show_hovers(l:ui, xx)}),
\ lsp#callbag#subscribe(),
\ )
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.