fix(compiler): one-shot builds and :Preview open provider config (#25)

* 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.

* 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.

* fix: normalize notify prefix to [preview.nvim]: everywhere

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.

* ci: format
This commit is contained in:
Barrett Ruth 2026-03-04 02:18:28 -05:00 committed by GitHub
parent da3e3e4249
commit 4732696a62
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 29 additions and 13 deletions

View file

@ -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(
@ -403,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
@ -427,10 +435,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)
)
@ -438,13 +446,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

View file

@ -148,12 +148,12 @@ 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)
local provider = config.providers[name]
compiler.compile(bufnr, name, provider, ctx)
compiler.compile(bufnr, name, provider, ctx, { oneshot = true })
end
---@param bufnr? integer
@ -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]
@ -190,8 +190,10 @@ end
---@param bufnr? integer
function M.open(bufnr)
bufnr = bufnr or vim.api.nvim_get_current_buf()
if not compiler.open(bufnr) then
vim.notify('[preview.nvim] no output file available for this buffer', vim.log.levels.WARN)
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