Neovim 异步缓冲区等待
Neovim asynchronous buffer waiting
我正在开发一个与终端缓冲区中的 REPL 交互的 Neovim 插件。我希望能够向 REPL 发送命令,复制响应,并以某种方式将其显示给用户。目前,在当前 vim 脚本函数终止之前,终端缓冲区似乎不会刷新输出,所以我不能有一个函数可以这样做,例如:
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 中似乎不起作用。
在 :term
缓冲区中,您可以设置一个 TextChanged
处理程序。例如。以下代码将整个 :term
缓冲区内容发送到 s:on_response
:
autocmd TextChanged <buffer> call <SID>on_response(getline(1,'$'))
找出自上一个 TextChanged
事件以来哪个文本是 "new" 将需要一些自定义逻辑。 '[
和 ']
标记未在 :term
缓冲区中正确设置(我不确定 nvim
是否可以自动执行此操作,但我做了一个 bug report).
请注意 TextChanged
仅在用户处于正常模式时触发(离开插入模式时也会立即触发)。
TextChangedI
(注意最后的 I
)应该在插入模式下触发,但它不适用于 :term
,那是 bug。
另一种方法是使用用户计时器(请参阅 :help timer_start
)。这是一个每秒调用 s:on_reponse(timer_id)
的计时器:
call timer_start(1000, '<SID>on_response', {'repeat':-1})
但这并不理想,因为您需要保留终端和计时器 ID 的映射(或遍历所有 :terminal
缓冲区并检查它们的内容)。
我为 jobattach()
函数创建了一个 feature request,它允许将 on_stdout
处理程序附加到现有作业(而 jobstart()
仅将处理程序添加到 新 个职位)。然后可以使用它附加到任何 :term
缓冲区的 b:terminal_job_id
。
我正在开发一个与终端缓冲区中的 REPL 交互的 Neovim 插件。我希望能够向 REPL 发送命令,复制响应,并以某种方式将其显示给用户。目前,在当前 vim 脚本函数终止之前,终端缓冲区似乎不会刷新输出,所以我不能有一个函数可以这样做,例如:
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 中似乎不起作用。
在 :term
缓冲区中,您可以设置一个 TextChanged
处理程序。例如。以下代码将整个 :term
缓冲区内容发送到 s:on_response
:
autocmd TextChanged <buffer> call <SID>on_response(getline(1,'$'))
找出自上一个 TextChanged
事件以来哪个文本是 "new" 将需要一些自定义逻辑。 '[
和 ']
标记未在 :term
缓冲区中正确设置(我不确定 nvim
是否可以自动执行此操作,但我做了一个 bug report).
请注意 TextChanged
仅在用户处于正常模式时触发(离开插入模式时也会立即触发)。
TextChangedI
(注意最后的 I
)应该在插入模式下触发,但它不适用于 :term
,那是 bug。
另一种方法是使用用户计时器(请参阅 :help timer_start
)。这是一个每秒调用 s:on_reponse(timer_id)
的计时器:
call timer_start(1000, '<SID>on_response', {'repeat':-1})
但这并不理想,因为您需要保留终端和计时器 ID 的映射(或遍历所有 :terminal
缓冲区并检查它们的内容)。
我为 jobattach()
函数创建了一个 feature request,它允许将 on_stdout
处理程序附加到现有作业(而 jobstart()
仅将处理程序添加到 新 个职位)。然后可以使用它附加到任何 :term
缓冲区的 b:terminal_job_id
。