简体   繁体   English

Neovim异步缓冲等待

[英]Neovim asynchronous buffer waiting

I am working on a Neovim plugin that interacts with a REPL in a terminal buffer. 我正在研究一个与终端缓冲区中的REPL交互的Neovim插件。 I want to be able to send a command to the REPL, copy the response, and display it to the user somehow. 我希望能够向REPL发送命令,复制响应,并以某种方式将其显示给用户。 Currently, the terminal buffer doesn't seem to refresh output until the current vimscript function terminates, so I can't have a single function that does, eg: 目前,终端缓冲区似乎没有刷新输出,直到当前vimscript函数终止,所以我不能有一个功能,例如:

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

as the get_response function is working with the terminal buffer before it gets updated. 因为get_response函数在更新之前正在使用终端缓冲区。

Currently, I'm using neovim's job control, though if this can be accomplished in vanilla vim, all the better. 目前,我正在使用neovim的工作控制,但如果这可以在vanilla vim中完成,那就更好了。

Here's the code I'm using to initialize the terminal: 这是我用来初始化终端的代码:

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

Here's how I'm sending the command to the REPL: 这是我如何将命令发送到REPL:

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

I've tried adding an edit command to refresh, but that doesn't seem to work in the REPL. 我已经尝试添加一个edit命令来刷新,但这似乎在REPL中不起作用。

The code for communicating with the REPL is here . 与REPL通信的代码在这里 The code for managing the process is here . 管理流程的代码在这里

In the :term buffer you can set up a TextChanged handler. :term缓冲区中,您可以设置TextChanged处理程序。 Eg the following code sends the entire :term buffer contents to s:on_response : 例如,以下代码将整个:term缓冲区内容发送到s:on_response

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

Figuring out which text is "new" since the previous TextChanged event will require some custom logic. 确定自上一次TextChanged事件以来哪些文本是“新的”将需要一些自定义逻辑。 The '[ and '] marks aren't correctly set in the :term buffer (I'm not sure this is feasible for nvim to do automatically, but I made a bug report ). '[']标记未在:term缓冲区中正确设置(我不确定nvim是否可以自动执行,但我做了一个错误报告 )。

Note that TextChanged only fires if the user is in normal-mode (also immediately upon leaving insert-mode). 请注意, TextChanged仅在用户处于正常模式时触发(在离开插入模式时也立即触发)。

TextChangedI (notice the I at the end) should fire in insert-mode, but it doesn't work with :term , that's a bug . TextChangedI (注意结尾处的I )应该在插入模式下触发,但它不能用于:term ,这是一个bug


Another approach is to user timers (see :help timer_start ). 另一种方法是用户计时器(参见:help timer_start )。 Here's a timer that calls s:on_reponse(timer_id) every second: 这是一个s:on_reponse(timer_id)调用s:on_reponse(timer_id)的计时器:

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

But this isn't ideal because you would need to keep a map of terminals and timer ids (or iterate through all :terminal buffers and check their contents). 但这并不理想,因为您需要保留终端和计时器ID的映射(或迭代所有:terminal缓冲区并检查其内容)。


I made a feature request for a jobattach() function which would allow attaching on_stdout handlers to existing jobs (whereas jobstart() only adds handlers to new jobs). 我为jobattach()函数发出了一个功能请求 ,它允许将on_stdout处理程序附加到现有作业(而jobstart()只将处理程序添加到作业)。 This could then be used to attach to b:terminal_job_id of any :term buffer. 然后可以使用它来附加到任何:term buffer的b:terminal_job_id

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM