~detegr/nvim-bqn

Use virtual lines to show output v1 SUPERSEDED

Andrey Popp: 1
 Use virtual lines to show output

 1 files changed, 32 insertions(+), 38 deletions(-)
I think the enter behavior in this implementation makes sense. It
greatly reduces the amount of visual selections needed.

About the visual selection, I think your suggestion about sending
exactly the selection is the most reasonable thing to do. It could be
handy for example when there's an expensive computation somewhere in the
previous lines of the file and you would want to avoid evaluating that
every time.
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~detegr/nvim-bqn/patches/27068/mbox | git am -3
Learn more about email & git

[PATCH] Use virtual lines to show output Export this patch

Neovim 0.6.0 was recently released and has added a new feature called
virtual lines. This allows to attach a set of "out-of-buffer" lines to
some locations via extmark mechanism.

This patch changes how output is shown - instead of making a separate
split buffer it shows computed value as a set of virtual lines attached
to the "end" of the computed region.
---
This adds some comments describing why something being done.

 lua/bqn.lua | 70 ++++++++++++++++++++++++-----------------------------
 1 file changed, 32 insertions(+), 38 deletions(-)

diff --git a/lua/bqn.lua b/lua/bqn.lua
index de733b3..491477f 100644
--- a/lua/bqn.lua
+++ b/lua/bqn.lua
@@ -1,36 +1,18 @@
local buf = nil
local win = nil
local ns = vim.api.nvim_create_namespace('bqn-out')

local function check_buf()
    if win == nil or not vim.api.nvim_win_is_valid(win) then
        local prev = vim.api.nvim_get_current_win()
        if buf == nil then
            buf = vim.api.nvim_create_buf(false, false)
        end
        vim.api.nvim_buf_set_name(buf, "BQN")
        vim.api.nvim_buf_set_option(buf, "buftype", "nofile")
        vim.api.nvim_buf_set_option(buf, "swapfile", false)
        vim.api.nvim_buf_set_option(buf, "modeline", false)
        vim.cmd("below 3split")
        vim.api.nvim_win_set_buf(vim.api.nvim_get_current_win(), buf)
        win = vim.api.nvim_get_current_win()
        vim.api.nvim_win_set_option(win, "wrap", false)
        vim.api.nvim_set_current_win(prev)
    elseif vim.api.nvim_win_is_valid(win) then
        local winid = vim.api.nvim_eval("bufwinid(" .. buf .. ")")
        if winid == -1 then
            local prev = vim.api.nvim_get_current_win()
            vim.cmd("below 3split")
            vim.api.nvim_win_set_buf(vim.api.nvim_get_current_win(), buf)
            win = vim.api.nvim_get_current_win()
            vim.api.nvim_set_current_win(prev)
        end
function evalBQN(from, to, pretty)
    -- Compute `to` position by looking back till we find first non-empty line.
    while to > 0 do
      local line = vim.api.nvim_buf_get_lines(0, to - 1, to, true)[1]
      if #line ~= 0 then break end
      to = to - 1
    end
end

function evalBQN(from, to, pretty)
    local code = vim.api.nvim_buf_get_lines(0, from - 1, to, true)
    if from > to then
      from = to
    end

    local code = vim.api.nvim_buf_get_lines(0, 0, to, true)
    local program = ""
    for k, v in ipairs(code) do
        program = program .. v .. "\n"
@@ -49,23 +31,35 @@ function evalBQN(from, to, pretty)
    if not found then
        bqn = "BQN"
    end

    local executable = assert(io.popen(bqn .. " -" .. flag .. " \"" .. program .. "\""))
    local cmd = bqn .. " -" .. flag .. " \"" .. program .. "\""
    local executable = assert(io.popen(cmd))
    local output = executable:read('*all')
    executable:close()

    check_buf()

    local lines = {}
    local line_count = 0
    for line in output:gmatch("[^\n]+") do
        table.insert(lines, line)
        table.insert(lines, {{' ' .. line, 'Comment'}})
        line_count = line_count + 1
    end
    table.insert(lines, {{' ', 'Comment'}})

    -- Compute `cto` (clear to) position by looking forward from `to` till we
    -- find first non-empty line. We do this so we clear all "orphaned" virtual
    -- line blocks (which correspond to already deleted lines).
    local total_lines = vim.api.nvim_buf_line_count(0)
    local cto = to + 1
    while cto <= total_lines do
      local line = vim.api.nvim_buf_get_lines(0, cto-1, cto, true)[1]
      if #line ~= 0 then break end
      cto = cto + 1
    end

    vim.api.nvim_buf_set_lines(buf, -1, -1, false, lines)
    vim.api.nvim_win_set_height(win, line_count)
    vim.api.nvim_win_set_cursor(win, {vim.api.nvim_buf_line_count(buf), 0})
    vim.api.nvim_buf_clear_namespace(0, ns, from - 1, cto - 1)
    vim.api.nvim_buf_set_extmark(0, ns, to - 1, 0, {
      end_line = to - 1,
      end_col = 3,
      virt_lines=lines
    })
end

return {
-- 
2.30.2
Ah, forgot about another thing — this patch changes how it determines
what to eval — it always sends code from the start of the buffer to
the current `to`. I actually think this is a good thing when you just
press Enter (you really want all previously defined bindings to be
available) but for visual mode — maybe it should send exactly what was
selected..