From c556ea9ea1a02de2c380d8d5c18d03557c191788 Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Wed, 4 Mar 2026 01:36:53 -0500 Subject: [PATCH 1/4] fix(compiler): skip reload command for one-shot builds Problem: compile() unconditionally resolved the reload command, so :Preview build on a provider with reload = function/table (e.g. typst) would start a long-running process (typst watch) instead of a one-shot compile (typst compile). Error diagnostics were also lost because typst watch does not exit non-zero on input errors. Solution: add an opts parameter to compile() with a oneshot flag. M.build() passes { oneshot = true } so resolve_reload_cmd() is skipped and the one-shot path is always taken. toggle() continues to call compile() without the flag, preserving long-running behavior for watch mode. --- lua/preview/compiler.lua | 9 +++++++-- lua/preview/init.lua | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lua/preview/compiler.lua b/lua/preview/compiler.lua index 8555881..5836c3a 100644 --- a/lua/preview/compiler.lua +++ b/lua/preview/compiler.lua @@ -55,7 +55,9 @@ end ---@param name string ---@param provider preview.ProviderConfig ---@param ctx preview.Context -function M.compile(bufnr, name, provider, ctx) +function M.compile(bufnr, name, provider, ctx, opts) + opts = opts or {} + if vim.bo[bufnr].modified then vim.cmd('silent! update') end @@ -81,7 +83,10 @@ function M.compile(bufnr, name, provider, ctx) last_output[bufnr] = output_file end - local reload_cmd = resolve_reload_cmd(provider, resolved_ctx) + local reload_cmd + if not opts.oneshot then + reload_cmd = resolve_reload_cmd(provider, resolved_ctx) + end if reload_cmd then log.dbg( diff --git a/lua/preview/init.lua b/lua/preview/init.lua index bbf70f1..6257783 100644 --- a/lua/preview/init.lua +++ b/lua/preview/init.lua @@ -153,7 +153,7 @@ function M.build(bufnr) end local ctx = M.build_context(bufnr) local provider = config.providers[name] - compiler.compile(bufnr, name, provider, ctx) + compiler.compile(bufnr, name, provider, ctx, { oneshot = true }) end ---@param bufnr? integer From f87f478612b9cfa6c7861a7948f7bda95c1d21ef Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Wed, 4 Mar 2026 01:37:16 -0500 Subject: [PATCH 2/4] fix(compiler): respect provider open config in M.open() Problem: :Preview open always called vim.ui.open regardless of the provider's open field. Providers configured with a custom opener (e.g. open = { 'sioyek', '--new-instance' }) were ignored, so the first build opened with sioyek but :Preview open fell back to the system default. Solution: init.lua resolves the provider's open config and passes it to compiler.open(). If open_config is a table, the custom command is spawned with the output path appended. Otherwise vim.ui.open is used as before. --- lua/preview/compiler.lua | 10 ++++++++-- lua/preview/init.lua | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lua/preview/compiler.lua b/lua/preview/compiler.lua index 5836c3a..9f13924 100644 --- a/lua/preview/compiler.lua +++ b/lua/preview/compiler.lua @@ -443,13 +443,19 @@ end ---@param bufnr integer ---@return boolean -function M.open(bufnr) +function M.open(bufnr, open_config) local output = last_output[bufnr] if not output then log.dbg('no last output file for buffer %d', bufnr) return false end - vim.ui.open(output) + if type(open_config) == 'table' then + local open_cmd = vim.list_extend({}, open_config) + table.insert(open_cmd, output) + vim.system(open_cmd) + else + vim.ui.open(output) + end return true end diff --git a/lua/preview/init.lua b/lua/preview/init.lua index 6257783..29b282c 100644 --- a/lua/preview/init.lua +++ b/lua/preview/init.lua @@ -190,7 +190,9 @@ end ---@param bufnr? integer function M.open(bufnr) bufnr = bufnr or vim.api.nvim_get_current_buf() - if not compiler.open(bufnr) then + local name = M.resolve_provider(bufnr) + local open_config = name and config.providers[name] and config.providers[name].open + if not compiler.open(bufnr, open_config) then vim.notify('[preview.nvim] no output file available for this buffer', vim.log.levels.WARN) end end From 845fabb4337b97a366ebeafd9e16181931d5c75e Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Wed, 4 Mar 2026 02:13:22 -0500 Subject: [PATCH 3/4] fix: normalize notify prefix to [preview.nvim]: everywhere MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: some vim.notify calls used [preview.nvim] (no colon) while others used [preview.nvim]: — inconsistent with the log module format. Solution: add the missing colon and space to all notify calls in init.lua and compiler.lua so every user-facing message matches the [preview.nvim]: prefix used by the log module. --- lua/preview/compiler.lua | 6 +++--- lua/preview/init.lua | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lua/preview/compiler.lua b/lua/preview/compiler.lua index 9f13924..8482b38 100644 --- a/lua/preview/compiler.lua +++ b/lua/preview/compiler.lua @@ -408,7 +408,7 @@ end ---@param ctx preview.Context function M.clean(bufnr, name, provider, ctx) if not provider.clean then - vim.notify('[preview.nvim] provider "' .. name .. '" has no clean command', vim.log.levels.WARN) + vim.notify('[preview.nvim]: provider "' .. name .. '" has no clean command', vim.log.levels.WARN) return end @@ -432,10 +432,10 @@ function M.clean(bufnr, name, provider, ctx) vim.schedule_wrap(function(result) if result.code == 0 then log.dbg('clean succeeded for buffer %d', bufnr) - vim.notify('[preview.nvim] clean complete', vim.log.levels.INFO) + vim.notify('[preview.nvim]: clean complete', vim.log.levels.INFO) else log.dbg('clean failed for buffer %d (exit code %d)', bufnr, result.code) - vim.notify('[preview.nvim] clean failed: ' .. (result.stderr or ''), vim.log.levels.ERROR) + vim.notify('[preview.nvim]: clean failed: ' .. (result.stderr or ''), vim.log.levels.ERROR) end end) ) diff --git a/lua/preview/init.lua b/lua/preview/init.lua index 29b282c..acceea5 100644 --- a/lua/preview/init.lua +++ b/lua/preview/init.lua @@ -148,7 +148,7 @@ function M.build(bufnr) bufnr = bufnr or vim.api.nvim_get_current_buf() local name = M.resolve_provider(bufnr) if not name then - vim.notify('[preview.nvim] no provider configured for this filetype', vim.log.levels.WARN) + vim.notify('[preview.nvim]: no provider configured for this filetype', vim.log.levels.WARN) return end local ctx = M.build_context(bufnr) @@ -167,7 +167,7 @@ function M.clean(bufnr) bufnr = bufnr or vim.api.nvim_get_current_buf() local name = M.resolve_provider(bufnr) if not name then - vim.notify('[preview.nvim] no provider configured for this filetype', vim.log.levels.WARN) + vim.notify('[preview.nvim]: no provider configured for this filetype', vim.log.levels.WARN) return end local ctx = M.build_context(bufnr) @@ -180,7 +180,7 @@ function M.watch(bufnr) bufnr = bufnr or vim.api.nvim_get_current_buf() local name = M.resolve_provider(bufnr) if not name then - vim.notify('[preview.nvim] no provider configured for this filetype', vim.log.levels.WARN) + vim.notify('[preview.nvim]: no provider configured for this filetype', vim.log.levels.WARN) return end local provider = config.providers[name] @@ -193,7 +193,7 @@ function M.open(bufnr) local name = M.resolve_provider(bufnr) local open_config = name and config.providers[name] and config.providers[name].open if not compiler.open(bufnr, open_config) then - vim.notify('[preview.nvim] no output file available for this buffer', vim.log.levels.WARN) + vim.notify('[preview.nvim]: no output file available for this buffer', vim.log.levels.WARN) end end From 82483e47c43c6a32a59950447861e3d2c4a69116 Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Wed, 4 Mar 2026 02:16:54 -0500 Subject: [PATCH 4/4] ci: format --- lua/preview/compiler.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lua/preview/compiler.lua b/lua/preview/compiler.lua index 8482b38..4c78574 100644 --- a/lua/preview/compiler.lua +++ b/lua/preview/compiler.lua @@ -408,7 +408,10 @@ end ---@param ctx preview.Context function M.clean(bufnr, name, provider, ctx) if not provider.clean then - vim.notify('[preview.nvim]: provider "' .. name .. '" has no clean command', vim.log.levels.WARN) + vim.notify( + '[preview.nvim]: provider "' .. name .. '" has no clean command', + vim.log.levels.WARN + ) return end