You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 07:55:18