Neovim自动测试插件开发求助:临时只读输出缓冲问题
自定义Neovim自动测试插件问题解决
需求说明
- 保存Rust文件时执行
cargo test - 未打开测试输出缓冲时自动创建该缓冲
- 将缓冲标记为只读
- 再次保存文件时复用现有缓冲
- 缓冲被关闭后,下次测试重新创建缓冲
当前遇到的问题
- 无法检测缓冲是否被关闭
- 测试输出长度超过缓冲高度时,缓冲不会自动向下滚动
- 退出Neovim时,提示保存临时缓冲(无需保存)
参考代码
local buffer_number = -1 local function log(_, data) if data then vim.api.nvim_buf_set_lines(buffer_number, -1, -1, true, data) end end local function open_buffer() if buffer_number == -1 then vim.api.nvim_command('botright vnew') buffer_number = vim.api.nvim_get_current_buf() end end local function autotest(pattern, command) vim.api.nvim_create_autocmd("BufWritePost", { group = vim.api.nvim_create_augroup("autotest", { clear = true }), pattern = pattern, callback = function() open_buffer() vim.api.nvim_buf_set_lines(buffer_number, 0, -1, true, {}) vim.fn.jobstart(command, { stdout_buffered = true, on_stdout = log, on_stderr = log, }) end }) end autotest("*.rs", { "cargo", "test" })
注:已知多款测试类插件,自行开发为学习Neovim插件编写方法。
解决方案
1. 检测缓冲是否被关闭
仅靠buffer_number == -1无法准确判断缓冲状态,需用vim.api.nvim_buf_is_valid(buffer_number)验证缓冲是否存在。同时监听BufDelete事件,缓冲被关闭时重置buffer_number:
local buffer_number = -1 local augroup = vim.api.nvim_create_augroup("autotest", { clear = true }) local function open_buffer() if buffer_number == -1 or not vim.api.nvim_buf_is_valid(buffer_number) then vim.cmd('botright vnew') buffer_number = vim.api.nvim_get_current_buf() -- 标记缓冲为只读 vim.api.nvim_buf_set_option(buffer_number, 'readonly', true) -- 设置缓冲不被保存 vim.api.nvim_buf_set_option(buffer_number, 'buftype', 'nofile') vim.api.nvim_buf_set_option(buffer_number, 'bufhidden', 'wipe') -- 自定义缓冲名称 vim.api.nvim_buf_set_name(buffer_number, '[AutoTest Output]') end end -- 缓冲被删除时重置编号 vim.api.nvim_create_autocmd("BufDelete", { group = augroup, pattern = '[AutoTest Output]', callback = function() buffer_number = -1 end })
2. 自动滚动到缓冲底部
在log函数中,每次写入内容后,找到显示该缓冲的窗口,将光标定位到最后一行:
local function log(_, data) if not data or buffer_number == -1 or not vim.api.nvim_buf_is_valid(buffer_number) then return end vim.api.nvim_buf_set_lines(buffer_number, -1, -1, true, data) -- 自动滚动到最新输出位置 local windows = vim.fn.win_findbuf(buffer_number) for _, win in ipairs(windows) do vim.api.nvim_win_set_cursor(win, {vim.api.nvim_buf_line_count(buffer_number), 0}) end end
3. 避免退出时提示保存临时缓冲
通过设置缓冲的buftype为nofile、bufhidden为wipe,Neovim会将其识别为临时缓冲,不会提示保存,这部分已在open_buffer函数中添加。
完整代码
local buffer_number = -1 local augroup = vim.api.nvim_create_augroup("autotest", { clear = true }) local function log(_, data) if not data or buffer_number == -1 or not vim.api.nvim_buf_is_valid(buffer_number) then return end vim.api.nvim_buf_set_lines(buffer_number, -1, -1, true, data) -- 自动滚动到缓冲底部 local windows = vim.fn.win_findbuf(buffer_number) for _, win in ipairs(windows) do vim.api.nvim_win_set_cursor(win, {vim.api.nvim_buf_line_count(buffer_number), 0}) end end local function open_buffer() if buffer_number == -1 or not vim.api.nvim_buf_is_valid(buffer_number) then vim.cmd('botright vnew') buffer_number = vim.api.nvim_get_current_buf() -- 标记为只读 vim.api.nvim_buf_set_option(buffer_number, 'readonly', true) -- 设置为临时缓冲,无需保存 vim.api.nvim_buf_set_option(buffer_number, 'buftype', 'nofile') vim.api.nvim_buf_set_option(buffer_number, 'bufhidden', 'wipe') vim.api.nvim_buf_set_name(buffer_number, '[AutoTest Output]') end end local function autotest(pattern, command) vim.api.nvim_create_autocmd("BufWritePost", { group = augroup, pattern = pattern, callback = function() open_buffer() -- 清空缓冲内容 vim.api.nvim_buf_set_lines(buffer_number, 0, -1, true, {}) vim.fn.jobstart(command, { stdout_buffered = true, on_stdout = log, on_stderr = log, }) end }) end -- 监听缓冲删除事件,重置buffer_number vim.api.nvim_create_autocmd("BufDelete", { group = augroup, pattern = '[AutoTest Output]', callback = function() buffer_number = -1 end }) autotest("*.rs", { "cargo", "test" })
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

