mirror of
https://github.com/Smaug123/nix-dotfiles
synced 2025-10-06 15:08:41 +00:00
111 lines
3.4 KiB
Lua
111 lines
3.4 KiB
Lua
BuildUtils = {}
|
|
|
|
-- Create a new buffer and a new floating window to hold that buffer.
|
|
local function create_floating_window()
|
|
-- Create a new buffer for build output
|
|
local buf = vim.api.nvim_create_buf(false, true) -- No listed, scratch buffer
|
|
|
|
-- Calculate window size and position here (example: full width, 10 lines high at the bottom)
|
|
local width = vim.api.nvim_get_option_value("columns", {})
|
|
local height = vim.api.nvim_get_option_value("lines", {})
|
|
local win_height = math.min(10, math.floor(height * 0.2)) -- 20% of total height or 10 lines
|
|
local win_opts = {
|
|
relative = "editor",
|
|
width = width,
|
|
height = win_height,
|
|
col = 0,
|
|
row = height - win_height,
|
|
style = "minimal",
|
|
border = "single",
|
|
}
|
|
|
|
local win = vim.api.nvim_open_win(buf, false, win_opts)
|
|
|
|
return { window = win, buffer = buf }
|
|
end
|
|
|
|
local function _on_output(context, is_stdout, err, data, on_line)
|
|
local prefix
|
|
if is_stdout then
|
|
prefix = "OUT"
|
|
else
|
|
prefix = "ERR"
|
|
end
|
|
if err or data then
|
|
vim.schedule(function()
|
|
if err then
|
|
-- Append the error message to the buffer
|
|
local count = vim.api.nvim_buf_line_count(context.buffer)
|
|
vim.api.nvim_buf_set_lines(context.buffer, count, count, false, { "error " .. prefix .. ": " .. err })
|
|
end
|
|
if data then
|
|
-- Append the data to the buffer
|
|
local count = vim.api.nvim_buf_line_count(context.buffer)
|
|
vim.api.nvim_buf_set_lines(
|
|
context.buffer,
|
|
count,
|
|
count,
|
|
false,
|
|
vim.tbl_map(function(line)
|
|
return prefix .. ": " .. line
|
|
end, vim.split(data, "\n"))
|
|
)
|
|
end
|
|
if vim.api.nvim_win_is_valid(context.window) then
|
|
local cur_win = vim.api.nvim_get_current_win()
|
|
local cur_buf = vim.api.nvim_win_get_buf(cur_win)
|
|
if cur_buf ~= context.buffer then
|
|
local new_line_count = vim.api.nvim_buf_line_count(context.buffer)
|
|
vim.api.nvim_win_set_cursor(context.window, { new_line_count, 0 })
|
|
end
|
|
end
|
|
|
|
on_line(data, is_stdout, context)
|
|
end)
|
|
end
|
|
end
|
|
|
|
-- Arguments:
|
|
-- * exe, a string (no need to escape this)
|
|
-- * args, a table like { "-m", "venv", vim.fn.shellescape(some_path) }
|
|
-- * description of this process, visible to the user, e.g. "venv creation"
|
|
-- * context, the result of `create_floating_window`
|
|
-- * on_line, a function which takes "the string written", (true if stdout else false), and the context table; should return nothing. We'll call that on every line of stdout and stderr.
|
|
-- * on_complete, takes `context`, `code` (exit code) and `signal` ("documented" with neovim's uv.spawn, hah)
|
|
local function run_external(exe, args, description, context, on_line, on_complete)
|
|
local handle
|
|
local stdout = vim.uv.new_pipe(false)
|
|
local stderr = vim.uv.new_pipe(false)
|
|
handle, _ = vim.uv.spawn(
|
|
exe,
|
|
{
|
|
args = args,
|
|
stdio = { nil, stdout, stderr },
|
|
},
|
|
vim.schedule_wrap(function(code, signal)
|
|
stdout:read_stop()
|
|
stderr:read_stop()
|
|
stdout:close()
|
|
stderr:close()
|
|
handle:close()
|
|
print("External process " .. description .. " completed, exit code " .. code .. " and signal " .. signal)
|
|
on_complete(context, code, signal)
|
|
end)
|
|
)
|
|
|
|
if not handle then
|
|
print("Failed to start " .. description .. " process.")
|
|
return
|
|
end
|
|
|
|
vim.uv.read_start(stdout, function(err, data)
|
|
_on_output(context, true, err, data, on_line)
|
|
end)
|
|
vim.uv.read_start(stderr, function(err, data)
|
|
_on_output(context, false, err, data, on_line)
|
|
end)
|
|
end
|
|
|
|
BuildUtils.create_window = create_floating_window
|
|
BuildUtils.run = run_external
|