我正在开发一个与终端缓冲区中的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。
答案 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
。