2

我正在开发一个与终端缓冲区中的 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 通信的代码在这里。管理流程的代码在这里

4

1 回答 1

3

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

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

找出自上一个TextChanged事件以来哪些文本是“新的”将需要一些自定义逻辑。和标记未正确设置在缓冲区'[中(我不确定这是否可行,但我做了一个错误报告)。']:termnvim

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

TextChangedI(注意I最后)应该在插入模式下触发,但它不适用于:term,这是一个错误


另一种方法是使用用户计时器(请参阅 参考资料:help timer_start)。s:on_reponse(timer_id)这是一个每秒调用一次的计时器:

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

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


我对允许将处理程序附加到现有作业的功能提出了功能请求(而仅处理程序添加到作业)。这可以用来附加到任何缓冲区。jobattach()on_stdoutjobstart()b:terminal_job_id:term

于 2016-07-07T14:00:14.450 回答