diff --git a/examples/neovim_luma_preview.lua b/examples/neovim_luma_preview.lua index 7b90d0d..5ed29d9 100644 --- a/examples/neovim_luma_preview.lua +++ b/examples/neovim_luma_preview.lua @@ -6,33 +6,93 @@ local preview_buf = nil local preview_win = nil +local active_job = nil +local update_id = 0 -local function update_luma_preview() - local src_buf = vim.api.nvim_get_current_buf() - local lines = vim.api.nvim_buf_get_lines(src_buf, 0, -1, false) - local cmd = vim.env.LUMA_MARKDOWN_BIN or "luma_markdown" - local output = vim.fn.systemlist(cmd, lines) +local function ensure_preview_buffer() + if preview_buf and vim.api.nvim_buf_is_valid(preview_buf) then return end - if not preview_buf or not vim.api.nvim_buf_is_valid(preview_buf) then - preview_buf = vim.api.nvim_create_buf(false, true) - vim.api.nvim_buf_set_option(preview_buf, "buftype", "nofile") - vim.api.nvim_buf_set_option(preview_buf, "bufhidden", "hide") - vim.api.nvim_buf_set_option(preview_buf, "swapfile", false) - vim.api.nvim_buf_set_option(preview_buf, "filetype", "markdown") - end + preview_buf = vim.api.nvim_create_buf(false, true) + vim.api.nvim_buf_set_option(preview_buf, "buftype", "nofile") + vim.api.nvim_buf_set_option(preview_buf, "bufhidden", "hide") + vim.api.nvim_buf_set_option(preview_buf, "swapfile", false) + vim.api.nvim_buf_set_option(preview_buf, "filetype", "markdown") +end +local function show_preview(src_buf, output) + ensure_preview_buffer() vim.api.nvim_buf_set_lines(preview_buf, 0, -1, false, output) if not preview_win or not vim.api.nvim_win_is_valid(preview_win) then + local src_win = vim.fn.bufwinid(src_buf) + if src_win == -1 then return end + + vim.api.nvim_set_current_win(src_win) vim.cmd "rightbelow vsplit" preview_win = vim.api.nvim_get_current_win() vim.api.nvim_win_set_buf(preview_win, preview_buf) - local src_win = vim.fn.bufwinid(src_buf) - if src_win ~= -1 then vim.api.nvim_set_current_win(src_win) end + vim.api.nvim_set_current_win(src_win) end end +local function update_luma_preview() + local src_buf = vim.api.nvim_get_current_buf() + local lines = vim.api.nvim_buf_get_lines(src_buf, 0, -1, false) + local changedtick = vim.api.nvim_buf_get_changedtick(src_buf) + local cmd = vim.env.LUMA_MARKDOWN_BIN or "luma_markdown" + + update_id = update_id + 1 + local this_update = update_id + + if active_job then + vim.fn.jobstop(active_job) + active_job = nil + end + + local output = {} + local errors = {} + local job + job = vim.fn.jobstart({ cmd }, { + stdin = "pipe", + stdout_buffered = true, + stderr_buffered = true, + on_stdout = function(_, data) + if data then vim.list_extend(output, data) end + end, + on_stderr = function(_, data) + if data then vim.list_extend(errors, data) end + end, + on_exit = function(_, exit_code) + if active_job == job then active_job = nil end + if this_update ~= update_id then return end + if not vim.api.nvim_buf_is_valid(src_buf) then return end + if vim.api.nvim_buf_get_changedtick(src_buf) ~= changedtick then return end + + if exit_code ~= 0 then + local message = table.concat(errors, "\n") + if message ~= "" then + vim.notify("Luma preview failed: " .. message, vim.log.levels.ERROR) + end + return + end + + -- io.println adds a final newline; systemlist used to remove it. + if output[#output] == "" then table.remove(output) end + show_preview(src_buf, output) + end, + }) + + if job <= 0 then + vim.notify("Could not start Luma preview: " .. cmd, vim.log.levels.ERROR) + return + end + + active_job = job + vim.fn.chansend(job, table.concat(lines, "\n")) + vim.fn.chanclose(job, "stdin") +end + vim.api.nvim_create_autocmd("BufWritePost", { pattern = "*.luma", callback = update_luma_preview,