Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
c0bf5c5ce1
feat(commands): add :Preview open subcommand
Problem: after closing a viewer, there was no way to re-open the last
compiled output without recompiling.

Solution: track the most recent output file per buffer in a `last_output`
table that persists after compilation finishes. Add `compiler.open()`,
`M.open()`, and wire it into the command dispatch.
2026-03-03 13:33:13 -05:00
5 changed files with 76 additions and 2 deletions

View file

@ -1,6 +1,6 @@
local M = {}
local subcommands = { 'compile', 'stop', 'clean', 'toggle', 'status' }
local subcommands = { 'compile', 'stop', 'clean', 'toggle', 'open', 'status' }
---@param args string
local function dispatch(args)
@ -14,6 +14,8 @@ local function dispatch(args)
require('preview').clean()
elseif subcmd == 'toggle' then
require('preview').toggle()
elseif subcmd == 'open' then
require('preview').open()
elseif subcmd == 'status' then
local s = require('preview').status()
local parts = {}
@ -47,7 +49,7 @@ function M.setup()
complete = function(lead)
return complete(lead)
end,
desc = 'Compile, stop, clean, toggle, or check status of document preview',
desc = 'Compile, stop, clean, toggle, open, or check status of document preview',
})
end

View file

@ -12,6 +12,9 @@ local watching = {}
---@type table<integer, true>
local opened = {}
---@type table<integer, string>
local last_output = {}
---@param val string[]|fun(ctx: preview.Context): string[]
---@param ctx preview.Context
---@return string[]
@ -61,6 +64,10 @@ function M.compile(bufnr, name, provider, ctx)
output_file = eval_string(provider.output, ctx)
end
if output_file ~= '' then
last_output[bufnr] = output_file
end
log.dbg('compiling buffer %d with provider "%s": %s', bufnr, name, table.concat(cmd, ' '))
local obj = vim.system(
@ -117,6 +124,7 @@ function M.compile(bufnr, name, provider, ctx)
once = true,
callback = function()
M.stop(bufnr)
last_output[bufnr] = nil
end,
})
@ -235,6 +243,18 @@ function M.clean(bufnr, name, provider, ctx)
)
end
---@param bufnr integer
---@return boolean
function M.open(bufnr)
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)
return true
end
---@param bufnr integer
---@return preview.Status
function M.status(bufnr)
@ -254,6 +274,7 @@ M._test = {
active = active,
watching = watching,
opened = opened,
last_output = last_output,
}
return M

View file

@ -39,6 +39,7 @@
---@field stop fun(bufnr?: integer)
---@field clean fun(bufnr?: integer)
---@field toggle fun(bufnr?: integer)
---@field open fun(bufnr?: integer)
---@field status fun(bufnr?: integer): preview.Status
---@field get_config fun(): preview.Config
local M = {}
@ -166,6 +167,14 @@ function M.toggle(bufnr)
compiler.toggle(bufnr, name, provider, M.build_context)
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)
end
end
---@class preview.Status
---@field compiling boolean
---@field watching boolean

View file

@ -35,6 +35,13 @@ describe('commands', function()
end)
end)
it('does not error on :Preview open', function()
require('preview.commands').setup()
assert.has_no.errors(function()
vim.cmd('Preview open')
end)
end)
it('does not error on :Preview toggle with no provider', function()
require('preview.commands').setup()
assert.has_no.errors(function()

View file

@ -174,6 +174,41 @@ describe('compiler', function()
end)
end)
describe('open', function()
it('returns false when no output exists', function()
assert.is_false(compiler.open(999))
end)
it('returns true after compilation stores output', function()
local bufnr = helpers.create_buffer({ 'hello' }, 'text')
vim.api.nvim_buf_set_name(bufnr, '/tmp/preview_test_open.txt')
vim.bo[bufnr].modified = false
local provider = {
cmd = { 'true' },
output = function()
return '/tmp/preview_test_open.pdf'
end,
}
local ctx = {
bufnr = bufnr,
file = '/tmp/preview_test_open.txt',
root = '/tmp',
ft = 'text',
}
compiler.compile(bufnr, 'testprov', provider, ctx)
assert.is_not_nil(compiler._test.last_output[bufnr])
assert.are.equal('/tmp/preview_test_open.pdf', compiler._test.last_output[bufnr])
vim.wait(2000, function()
return compiler._test.active[bufnr] == nil
end, 50)
helpers.delete_buffer(bufnr)
end)
end)
describe('toggle', function()
it('registers autocmd and tracks in watching table', function()
local bufnr = helpers.create_buffer({ 'hello' }, 'text')