diff --git a/lua/preview/compiler.lua b/lua/preview/compiler.lua index 90f7367..c3ffbfa 100644 --- a/lua/preview/compiler.lua +++ b/lua/preview/compiler.lua @@ -16,7 +16,7 @@ local log = require('preview.log') ---@field has_errors? boolean ---@field debounce? uv.uv_timer_t ---@field bwp_autocmd? integer ----@field unload_autocmd? integer +---@field cleanup_autocmd? integer ---@type table local state = {} @@ -189,7 +189,7 @@ local function stop_watching(bufnr, s) close_viewer(bufnr) s.viewer_open = nil if s.bwp_autocmd then - vim.api.nvim_del_autocmd(s.bwp_autocmd) + pcall(vim.api.nvim_del_autocmd, s.bwp_autocmd) s.bwp_autocmd = nil end if s.debounce then @@ -215,8 +215,14 @@ function M.compile(bufnr, name, provider, ctx, opts) return end - if vim.bo[bufnr].modified then - vim.cmd('silent! update') + local buf_file = vim.api.nvim_buf_get_name(bufnr) + if buf_file ~= '' and buf_file == ctx.file then + if vim.bo[bufnr].modified then + vim.cmd('silent! update') + end + else + local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) + vim.fn.writefile(lines, ctx.file) end local s = get_state(bufnr) @@ -508,8 +514,8 @@ end function M.stop_all() for bufnr, s in pairs(state) do stop_watching(bufnr, s) - if s.unload_autocmd then - vim.api.nvim_del_autocmd(s.unload_autocmd) + if s.cleanup_autocmd then + pcall(vim.api.nvim_del_autocmd, s.cleanup_autocmd) end state[bufnr] = nil end @@ -541,10 +547,10 @@ function M.toggle(bufnr, name, provider, ctx_builder) log.dbg('toggle on for buffer %d', bufnr) s.watching = true - if s.unload_autocmd then - vim.api.nvim_del_autocmd(s.unload_autocmd) + if s.cleanup_autocmd then + vim.api.nvim_del_autocmd(s.cleanup_autocmd) end - s.unload_autocmd = vim.api.nvim_create_autocmd('BufUnload', { + s.cleanup_autocmd = vim.api.nvim_create_autocmd('BufDelete', { buffer = bufnr, once = true, callback = function() diff --git a/lua/preview/init.lua b/lua/preview/init.lua index 489679f..5383623 100644 --- a/lua/preview/init.lua +++ b/lua/preview/init.lua @@ -139,27 +139,49 @@ function M.resolve_provider(bufnr) return ft end +local ft_ext = { + markdown = 'md', + typst = 'typ', + tex = 'tex', + asciidoc = 'adoc', + plantuml = 'puml', + mermaid = 'mmd', + quarto = 'qmd', +} + ---@param bufnr? integer ---@return preview.Context function M.build_context(bufnr) bufnr = bufnr or vim.api.nvim_get_current_buf() local file = vim.api.nvim_buf_get_name(bufnr) - local root = vim.fs.root(bufnr, { '.git' }) or vim.fn.fnamemodify(file, ':h') + local ft = vim.bo[bufnr].filetype + local root + + if file ~= '' and vim.uv.fs_stat(file) then + root = vim.fs.root(bufnr, { '.git' }) or vim.fn.fnamemodify(file, ':h') + else + local basename + if file ~= '' then + basename = string.format('%d-%s', bufnr, vim.fn.fnamemodify(file, ':t')) + else + local ext = ft_ext[ft] or ft + basename = string.format('preview-%d.%s', bufnr, ext) + end + file = '/tmp/' .. basename + root = '/tmp' + end + return { bufnr = bufnr, file = file, root = root, - ft = vim.bo[bufnr].filetype, + ft = ft, } end ---@param bufnr? integer function M.compile(bufnr) bufnr = bufnr or vim.api.nvim_get_current_buf() - if vim.api.nvim_buf_get_name(bufnr) == '' then - vim.notify('[preview.nvim]: buffer has no file name', vim.log.levels.WARN) - return - end local name = M.resolve_provider(bufnr) if not name then vim.notify('[preview.nvim]: no provider configured for this filetype', vim.log.levels.WARN) @@ -179,10 +201,6 @@ end ---@param bufnr? integer function M.clean(bufnr) bufnr = bufnr or vim.api.nvim_get_current_buf() - if vim.api.nvim_buf_get_name(bufnr) == '' then - vim.notify('[preview.nvim]: buffer has no file name', vim.log.levels.WARN) - return - end local name = M.resolve_provider(bufnr) if not name then vim.notify('[preview.nvim]: no provider configured for this filetype', vim.log.levels.WARN) @@ -196,10 +214,6 @@ end ---@param bufnr? integer function M.toggle(bufnr) bufnr = bufnr or vim.api.nvim_get_current_buf() - if vim.api.nvim_buf_get_name(bufnr) == '' then - vim.notify('[preview.nvim]: buffer has no file name', vim.log.levels.WARN) - return - end local name = M.resolve_provider(bufnr) if not name then vim.notify('[preview.nvim]: no provider configured for this filetype', vim.log.levels.WARN) @@ -212,10 +226,6 @@ end ---@param bufnr? integer function M.open(bufnr) bufnr = bufnr or vim.api.nvim_get_current_buf() - if vim.api.nvim_buf_get_name(bufnr) == '' then - vim.notify('[preview.nvim]: buffer has no file name', vim.log.levels.WARN) - return - end 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 diff --git a/spec/init_spec.lua b/spec/init_spec.lua index f68438c..55c2391 100644 --- a/spec/init_spec.lua +++ b/spec/init_spec.lua @@ -126,43 +126,43 @@ describe('preview', function() return msg end - it('compile warns on unnamed buffer', function() - local bufnr = helpers.create_buffer({}, 'typst') + it('compile falls through to provider check on unnamed buffer', function() + local bufnr = helpers.create_buffer({}, 'lua') local msg = capture_notify(function() preview.compile(bufnr) end) assert.is_not_nil(msg) - assert.is_truthy(msg:find('no file name')) + assert.is_truthy(msg:find('no provider configured')) helpers.delete_buffer(bufnr) end) - it('toggle warns on unnamed buffer', function() - local bufnr = helpers.create_buffer({}, 'typst') + it('toggle falls through to provider check on unnamed buffer', function() + local bufnr = helpers.create_buffer({}, 'lua') local msg = capture_notify(function() preview.toggle(bufnr) end) assert.is_not_nil(msg) - assert.is_truthy(msg:find('no file name')) + assert.is_truthy(msg:find('no provider configured')) helpers.delete_buffer(bufnr) end) - it('clean warns on unnamed buffer', function() - local bufnr = helpers.create_buffer({}, 'typst') + it('clean falls through to provider check on unnamed buffer', function() + local bufnr = helpers.create_buffer({}, 'lua') local msg = capture_notify(function() preview.clean(bufnr) end) assert.is_not_nil(msg) - assert.is_truthy(msg:find('no file name')) + assert.is_truthy(msg:find('no provider configured')) helpers.delete_buffer(bufnr) end) - it('open warns on unnamed buffer', function() - local bufnr = helpers.create_buffer({}, 'typst') + it('open warns no output on unnamed buffer', function() + local bufnr = helpers.create_buffer({}, 'lua') local msg = capture_notify(function() preview.open(bufnr) end) assert.is_not_nil(msg) - assert.is_truthy(msg:find('no file name')) + assert.is_truthy(msg:find('no output file')) helpers.delete_buffer(bufnr) end) end)