为测试输出创建临时只读缓冲区

Nic*_*ick 3 neovim

我想创建一个 Neovim 插件,每当保存文件时自动运行测试套件。概述如下:

  1. 如果我保存 Rust 文件,请运行cargo test
  2. 如果没有为测试输出打开缓冲区,则自动创建缓冲区
  3. 将该缓冲区标记为只读
  4. 如果我保存另一个文件,请重用现有缓冲区
  5. 如果缓冲区退出(例如:q),则在下一次测试运行时创建一个新缓冲区

然而,我目前面临三个问题:

  1. 当我退出缓冲区时我无法检测到
  2. 当测试输出长于缓冲区高度时,缓冲区不会向下滚动
  3. 当我想退出 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" })
Run Code Online (Sandbox Code Playgroud)

PS 我知道有几个现有的插件可供测试。我正在创建自己的插件,因为我想学习如何编写 neovim 插件。

Rya*_*son 5

我尽了最大努力。我相信这可以解决您的问题并实现您的目标。

local buffer_number = -1

local function log(_, data)
    if data then
        -- Make it temporarily writable so we don't have warnings.
        vim.api.nvim_buf_set_option(buffer_number, "readonly", false)
        
        -- Append the data.
        vim.api.nvim_buf_set_lines(buffer_number, -1, -1, true, data)

        -- Make readonly again.
        vim.api.nvim_buf_set_option(buffer_number, "readonly", true)

        -- Mark as not modified, otherwise you'll get an error when
        -- attempting to exit vim.
        vim.api.nvim_buf_set_option(buffer_number, "modified", false)

        -- Get the window the buffer is in and set the cursor position to the bottom.
        local buffer_window = vim.api.nvim_call_function("bufwinid", { buffer_number })
        local buffer_line_count = vim.api.nvim_buf_line_count(buffer_number)
        vim.api.nvim_win_set_cursor(buffer_window, { buffer_line_count, 0 })
    end
end

local function open_buffer()
    -- Get a boolean that tells us if the buffer number is visible anymore.
    --
    -- :help bufwinnr
    local buffer_visible = vim.api.nvim_call_function("bufwinnr", { buffer_number }) ~= -1

    if buffer_number == -1 or not buffer_visible then
        -- Create a new buffer with the name "AUTOTEST_OUTPUT".
        -- Same name will reuse the current buffer.
        vim.api.nvim_command("botright vsplit AUTOTEST_OUTPUT")
        
        -- Collect the buffer's number.
        buffer_number = vim.api.nvim_get_current_buf()
        
        -- Mark the buffer as readonly.
        vim.opt_local.readonly = true
    end
end

function autotest(pattern, command)
    vim.api.nvim_create_autocmd("BufWritePost", {
        pattern = pattern,
        callback = function()
            -- Open our buffer, if we need to.
            open_buffer()
        
            -- Clear the buffer's contents incase it has been used.
            vim.api.nvim_buf_set_lines(buffer_number, 0, -1, true, {})

            -- Run the command.
            vim.fn.jobstart(command, {
                stdout_buffered = true,
                on_stdout = log,
                on_stderr = log,
            })
        end
    })
end

autotest("*.rs", { "cargo", "test" })
Run Code Online (Sandbox Code Playgroud)

我添加了一些评论来帮助解释每个步骤,但专门针对您的每个问题:

  1. 当我退出缓冲区时我无法检测到

由于您已经有了缓冲区编号,因此您可以查询它是否仍然可见。只需在创建新缓冲区时使用相同的名称,我们就可以重用任何现有的缓冲区。

  1. 当测试输出长于缓冲区高度时,缓冲区不会向下滚动

这很棘手,我不确定这是否是最好的方法,但我能够查询缓冲区有多少行并将缓冲区窗口的光标设置到底部。

  1. 当我想退出 Neovim 时,它要求我保存所有这些临时缓冲区(我不想这样做)

这是因为缓冲区被修改了。默认情况下,Neovim 不希望在您进行主动修改时很容易意外丢失您的工作。为了解决这个问题,我们可以轻松地标记它没有被修改!

希望有帮助。