Neovim异步缓冲等待

时间:2016-07-06 04:14:14

标签: vim neovim

我正在开发一个与终端缓冲区中的REPL交互的Neovim插件。我希望能够向REPL发送命令,复制响应,并以某种方式将其显示给用户。目前,终端缓冲区似乎没有刷新输出,直到当前的vimscript函数终止,所以我不能有一个功能,例如:

function! plugin#eval(str)
    call s:send_to_repl(str)
    echomsg s:get_response()
endfunction

因为get_response函数在更新之前正在使用终端缓冲区。

目前,我使用neovim的工作控制,但如果这可以在vanilla vim中完成,那就更好了。

这是我用来初始化终端的代码:

function! s:start_buffer(height)
    set bufhidden=hide
    set noswapfile
    set buftype=nofile
    set hidden
    terminal! stack ghci --with-ghc intero
    let l:buffer_id = bufnr('%')
    let g:intero_job_id = b:terminal_job_id
endfunction

以下是我如何将命令发送到REPL:

function! s:send(str)
    call jobsend(g:intero_job_id, add([a:str], ''))
endfunction

我已尝试添加edit命令进行刷新,但这似乎不适用于REPL。

与REPL通信的代码是here。管理流程的代码是here

1 个答案:

答案 0 :(得分:3)

:term缓冲区中,您可以设置TextChanged处理程序。例如。以下代码将整个:term缓冲区内容发送到s:on_response

autocmd TextChanged <buffer> call <SID>on_response(getline(1,'$'))

确定自上一个TextChanged事件以来哪些文本是“新的”将需要一些自定义逻辑。在'[缓冲区中未正确设置']:term标记(我不确定nvim自动执行此操作是否可行,但我做了{ {3}})。

请注意,TextChanged仅在用户处于正常模式时触发(在离开插入模式时也立即触发)。

TextChangedI(注意最后的I)应该以插入模式触发,但它不适用于:term,即bug report

另一种方法是用户定时器(见:help timer_start)。这是一个每秒调用s:on_reponse(timer_id)的计时器:

call timer_start(1000, '<SID>on_response', {'repeat':-1})

但这并不理想,因为您需要保留终端和计时器ID的映射(或遍历所有:terminal缓冲区并检查其内容)。

我为jobattach()函数设置bug,允许将on_stdout处理程序附加到现有作业(而jobstart()只为 new 工作)。然后,可以将其用于附加到任何b:terminal_job_id缓冲区的:term