[英]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.