feat: rename

This commit is contained in:
Barrett Ruth 2026-03-02 21:23:40 -05:00
parent e1d7abf58e
commit 942438f817
Signed by: barrett
GPG key ID: A6C96C9349D2FC81
21 changed files with 660 additions and 305 deletions

View file

@ -1,4 +1,4 @@
# render.nvim # preview.nvim
Async document compilation for Neovim. Async document compilation for Neovim.
@ -10,32 +10,47 @@ your own providers.
- Async compilation via `vim.system()` - Async compilation via `vim.system()`
- Compiler errors as native `vim.diagnostic` - Compiler errors as native `vim.diagnostic`
- User events for extensibility (`RenderCompileStarted`, `RenderCompileSuccess`, - User events for extensibility (`PreviewCompileStarted`, `PreviewCompileSuccess`,
`RenderCompileFailed`) `PreviewCompileFailed`)
- `:checkhealth` integration - `:checkhealth` integration
- Zero dependencies beyond Neovim 0.10.0+ - Zero dependencies beyond Neovim 0.11.0+
## Requirements ## Requirements
- Neovim >= 0.10.0 - Neovim >= 0.11.0
- A compiler binary for each provider you configure - A compiler binary for each provider you configure
## Installation ## Installation
```lua ```lua
-- lazy.nvim -- lazy.nvim
{ 'barrettruth/render.nvim' } { 'barrettruth/preview.nvim' }
``` ```
```vim ```vim
" luarocks " luarocks
:Rocks install render.nvim :Rocks install preview.nvim
``` ```
## Configuration ## Configuration
Use built-in presets for common tools:
```lua ```lua
vim.g.render = { local presets = require('preview.presets')
vim.g.preview = {
providers = {
typst = presets.typst,
tex = presets.latex,
markdown = presets.markdown,
},
}
```
Or define providers manually:
```lua
vim.g.preview = {
providers = { providers = {
typst = { typst = {
cmd = { 'typst', 'compile' }, cmd = { 'typst', 'compile' },
@ -46,19 +61,10 @@ vim.g.render = {
return ctx.file:gsub('%.typ$', '.pdf') return ctx.file:gsub('%.typ$', '.pdf')
end, end,
}, },
latexmk = {
cmd = { 'latexmk' },
args = { '-pdf', '-interaction=nonstopmode' },
clean = { 'latexmk', '-c' },
},
},
providers_by_ft = {
typst = 'typst',
tex = 'latexmk',
}, },
} }
``` ```
## Documentation ## Documentation
See `:help render.nvim` for full documentation. See `:help preview.nvim` for full documentation.

View file

@ -1,83 +1,80 @@
*render.nvim.txt* Async document compilation for Neovim *preview.nvim.txt* Async document compilation for Neovim
Author: Raphael Author: Raphael
License: MIT License: MIT
============================================================================== ==============================================================================
INTRODUCTION *render.nvim* INTRODUCTION *preview.nvim*
render.nvim is an extensible framework for compiling documents asynchronously preview.nvim is an extensible framework for compiling documents asynchronously
in Neovim. It provides a unified interface for any compilation workflow — in Neovim. It provides a unified interface for any compilation workflow —
LaTeX, Typst, Markdown, or anything else with a CLI compiler. LaTeX, Typst, Markdown, or anything else with a CLI compiler.
The plugin ships with zero provider defaults. Users must explicitly configure The plugin ships with zero provider defaults. Users must explicitly configure
their compiler commands. render.nvim is purely an orchestration framework. their compiler commands. preview.nvim is purely an orchestration framework.
============================================================================== ==============================================================================
REQUIREMENTS *render.nvim-requirements* REQUIREMENTS *preview.nvim-requirements*
- Neovim >= 0.10.0 - Neovim >= 0.11.0
- A compiler binary for each configured provider (e.g. `typst`, `latexmk`) - A compiler binary for each configured provider (e.g. `typst`, `latexmk`)
============================================================================== ==============================================================================
INSTALLATION *render.nvim-installation* INSTALLATION *preview.nvim-installation*
With luarocks (recommended): With luarocks (recommended):
> >
:Rocks install render.nvim :Rocks install preview.nvim
< <
With lazy.nvim: With lazy.nvim:
>lua >lua
{ {
'barrettruth/render.nvim', 'barrettruth/preview.nvim',
} }
< <
============================================================================== ==============================================================================
CONFIGURATION *render.nvim-configuration* CONFIGURATION *preview.nvim-configuration*
Configure via the `vim.g.render` global table before the plugin loads. Configure via the `vim.g.preview` global table before the plugin loads.
*render.Config* *preview.Config*
Fields:~ Fields:~
`debug` boolean|string Enable debug logging. A string value `debug` boolean|string Enable debug logging. A string value
is treated as a log file path. is treated as a log file path.
Default: `false` Default: `false`
`providers` table Provider configurations keyed by name. `providers` table Provider configurations keyed by
Default: `{}` filetype. Default: `{}`
`providers_by_ft` table Maps filetypes to provider names. *preview.ProviderConfig*
Default: `{}`
*render.ProviderConfig*
Provider fields:~ Provider fields:~
`cmd` string[] The compiler command (required). `cmd` string[] The compiler command (required).
`args` string[]|function Additional arguments. If a function, `args` string[]|function Additional arguments. If a function,
receives a |render.Context| and returns receives a |preview.Context| and returns
a string[]. a string[].
`cwd` string|function Working directory. If a function, `cwd` string|function Working directory. If a function,
receives a |render.Context|. Default: receives a |preview.Context|. Default:
git root or file directory. git root or file directory.
`env` table Environment variables. `env` table Environment variables.
`output` string|function Output file path. If a function, `output` string|function Output file path. If a function,
receives a |render.Context|. receives a |preview.Context|.
`error_parser` function Receives (stderr, |render.Context|) `error_parser` function Receives (stderr, |preview.Context|)
and returns vim.Diagnostic[]. and returns vim.Diagnostic[].
`clean` string[]|function Command to remove build artifacts. `clean` string[]|function Command to remove build artifacts.
If a function, receives a If a function, receives a
|render.Context|. |preview.Context|.
*render.Context* *preview.Context*
Context fields:~ Context fields:~
`bufnr` integer Buffer number. `bufnr` integer Buffer number.
@ -87,7 +84,7 @@ Context fields:~
Example:~ Example:~
>lua >lua
vim.g.render = { vim.g.preview = {
providers = { providers = {
typst = { typst = {
cmd = { 'typst', 'compile' }, cmd = { 'typst', 'compile' },
@ -110,74 +107,117 @@ Example:~
return diagnostics return diagnostics
end, end,
}, },
latexmk = { tex = {
cmd = { 'latexmk' }, cmd = { 'latexmk' },
args = { '-pdf', '-interaction=nonstopmode' }, args = { '-pdf', '-interaction=nonstopmode' },
clean = { 'latexmk', '-c' }, clean = { 'latexmk', '-c' },
}, },
}, },
providers_by_ft = { }
typst = 'typst', <
tex = 'latexmk',
==============================================================================
PRESETS *preview.nvim-presets*
preview.nvim ships with pre-built provider configurations for common tools.
Import them from `preview.presets`:
`presets.typst` typst compile → PDF
`presets.latex` latexmk -pdf → PDF (with clean support)
`presets.markdown` pandoc → PDF
Example:~
>lua
local presets = require('preview.presets')
vim.g.preview = {
providers = {
typst = presets.typst,
tex = presets.latex,
markdown = presets.markdown,
},
}
<
Override individual fields with `vim.tbl_deep_extend`:
>lua
local presets = require('preview.presets')
vim.g.preview = {
providers = {
typst = vim.tbl_deep_extend('force', presets.typst, {
env = { TYPST_FONT_PATHS = '/usr/share/fonts' },
}),
}, },
} }
< <
============================================================================== ==============================================================================
COMMANDS *render.nvim-commands* COMMANDS *preview.nvim-commands*
:Render [subcommand] *:Render* :Preview [subcommand] *:Preview*
Subcommands:~ Subcommands:~
`compile` Compile the current buffer (default if omitted). `compile` Compile the current buffer (default if omitted).
`stop` Kill active compilation for the current buffer. `stop` Kill active compilation for the current buffer.
`clean` Run the provider's clean command. `clean` Run the provider's clean command.
`status` Echo compilation status (idle or compiling). `watch` Toggle auto-compile on save for the current buffer.
`status` Echo compilation status (idle, compiling, watching).
============================================================================== ==============================================================================
API *render.nvim-api* API *preview.nvim-api*
render.compile({bufnr?}) *render.compile()* preview.compile({bufnr?}) *preview.compile()*
Compile the document in the given buffer (default: current). Compile the document in the given buffer (default: current).
render.stop({bufnr?}) *render.stop()* preview.stop({bufnr?}) *preview.stop()*
Kill the active compilation process for the buffer. Kill the active compilation process for the buffer.
render.clean({bufnr?}) *render.clean()* preview.clean({bufnr?}) *preview.clean()*
Run the provider's clean command for the buffer. Run the provider's clean command for the buffer.
render.status({bufnr?}) *render.status()* preview.watch({bufnr?}) *preview.watch()*
Returns a |render.Status| table. Toggle watch mode for the buffer. When enabled, the buffer is
automatically compiled on each save (`BufWritePost`). Call again
to stop watching.
*render.Status* preview.status({bufnr?}) *preview.status()*
Returns a |preview.Status| table.
*preview.Status*
Status fields:~ Status fields:~
`compiling` boolean Whether compilation is active. `compiling` boolean Whether compilation is active.
`watching` boolean Whether watch mode is active.
`provider` string? Name of the active provider. `provider` string? Name of the active provider.
`output_file` string? Path to the output file. `output_file` string? Path to the output file.
render.get_config() *render.get_config()* preview.get_config() *preview.get_config()*
Returns the resolved |render.Config|. Returns the resolved |preview.Config|.
============================================================================== ==============================================================================
EVENTS *render.nvim-events* EVENTS *preview.nvim-events*
render.nvim fires User autocmds with structured data: preview.nvim fires User autocmds with structured data:
`RenderCompileStarted` Compilation began. `PreviewCompileStarted` Compilation began.
data: `{ bufnr, provider }` data: `{ bufnr, provider }`
`RenderCompileSuccess` Compilation succeeded (exit code 0). `PreviewCompileSuccess` Compilation succeeded (exit code 0).
data: `{ bufnr, provider, output }` data: `{ bufnr, provider, output }`
`RenderCompileFailed` Compilation failed (non-zero exit). `PreviewCompileFailed` Compilation failed (non-zero exit).
data: `{ bufnr, provider, code, stderr }` data: `{ bufnr, provider, code, stderr }`
`PreviewWatchStarted` Watch mode enabled for a buffer.
data: `{ bufnr, provider }`
`PreviewWatchStopped` Watch mode disabled for a buffer.
data: `{ bufnr }`
Example:~ Example:~
>lua >lua
vim.api.nvim_create_autocmd('User', { vim.api.nvim_create_autocmd('User', {
pattern = 'RenderCompileSuccess', pattern = 'PreviewCompileSuccess',
callback = function(args) callback = function(args)
local data = args.data local data = args.data
vim.notify('Compiled ' .. data.output .. ' with ' .. data.provider) vim.notify('Compiled ' .. data.output .. ' with ' .. data.provider)
@ -186,13 +226,13 @@ Example:~
< <
============================================================================== ==============================================================================
HEALTH *render.nvim-health* HEALTH *preview.nvim-health*
Run `:checkhealth render` to verify: Run `:checkhealth preview` to verify:
- Neovim version >= 0.10.0 - Neovim version >= 0.11.0
- Each configured provider's binary is executable - Each configured provider's binary is executable
- Filetype-to-provider mappings are valid - Each configured provider's filetype mapping is valid
============================================================================== ==============================================================================
vim:tw=78:ts=8:ft=help:norl: vim:tw=78:ts=8:ft=help:norl:

View file

@ -1,5 +1,5 @@
{ {
description = "render.nvim async document compilation for Neovim"; description = "preview.nvim async document compilation for Neovim";
inputs = { inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";

54
lua/preview/commands.lua Normal file
View file

@ -0,0 +1,54 @@
local M = {}
local subcommands = { 'compile', 'stop', 'clean', 'watch', 'status' }
---@param args string
local function dispatch(args)
local subcmd = args ~= '' and args or 'compile'
if subcmd == 'compile' then
require('preview').compile()
elseif subcmd == 'stop' then
require('preview').stop()
elseif subcmd == 'clean' then
require('preview').clean()
elseif subcmd == 'watch' then
require('preview').watch()
elseif subcmd == 'status' then
local s = require('preview').status()
local parts = {}
if s.compiling then
table.insert(parts, 'compiling with "' .. s.provider .. '"')
else
table.insert(parts, 'idle')
end
if s.watching then
table.insert(parts, 'watching')
end
vim.notify('[preview.nvim] ' .. table.concat(parts, ', '), vim.log.levels.INFO)
else
vim.notify('[preview.nvim] unknown subcommand: ' .. subcmd, vim.log.levels.ERROR)
end
end
---@param lead string
---@return string[]
local function complete(lead)
return vim.tbl_filter(function(s)
return s:find(lead, 1, true) == 1
end, subcommands)
end
function M.setup()
vim.api.nvim_create_user_command('Preview', function(opts)
dispatch(opts.args)
end, {
nargs = '?',
complete = function(lead)
return complete(lead)
end,
desc = 'Compile, stop, clean, watch, or check status of document preview',
})
end
return M

View file

@ -1,13 +1,16 @@
local M = {} local M = {}
local diagnostic = require('render.diagnostic') local diagnostic = require('preview.diagnostic')
local log = require('render.log') local log = require('preview.log')
---@type table<integer, render.Process> ---@type table<integer, preview.Process>
local active = {} local active = {}
---@param val string[]|fun(ctx: render.Context): string[] ---@type table<integer, integer>
---@param ctx render.Context local watching = {}
---@param val string[]|fun(ctx: preview.Context): string[]
---@param ctx preview.Context
---@return string[] ---@return string[]
local function eval_list(val, ctx) local function eval_list(val, ctx)
if type(val) == 'function' then if type(val) == 'function' then
@ -16,8 +19,8 @@ local function eval_list(val, ctx)
return val return val
end end
---@param val string|fun(ctx: render.Context): string ---@param val string|fun(ctx: preview.Context): string
---@param ctx render.Context ---@param ctx preview.Context
---@return string ---@return string
local function eval_string(val, ctx) local function eval_string(val, ctx)
if type(val) == 'function' then if type(val) == 'function' then
@ -28,8 +31,8 @@ end
---@param bufnr integer ---@param bufnr integer
---@param name string ---@param name string
---@param provider render.ProviderConfig ---@param provider preview.ProviderConfig
---@param ctx render.Context ---@param ctx preview.Context
function M.compile(bufnr, name, provider, ctx) function M.compile(bufnr, name, provider, ctx)
if vim.bo[bufnr].modified then if vim.bo[bufnr].modified then
vim.cmd('silent! update') vim.cmd('silent! update')
@ -70,7 +73,7 @@ function M.compile(bufnr, name, provider, ctx)
log.dbg('compilation succeeded for buffer %d', bufnr) log.dbg('compilation succeeded for buffer %d', bufnr)
diagnostic.clear(bufnr) diagnostic.clear(bufnr)
vim.api.nvim_exec_autocmds('User', { vim.api.nvim_exec_autocmds('User', {
pattern = 'RenderCompileSuccess', pattern = 'PreviewCompileSuccess',
data = { bufnr = bufnr, provider = name, output = output_file }, data = { bufnr = bufnr, provider = name, output = output_file },
}) })
else else
@ -79,7 +82,7 @@ function M.compile(bufnr, name, provider, ctx)
diagnostic.set(bufnr, name, provider.error_parser, result.stderr or '', ctx) diagnostic.set(bufnr, name, provider.error_parser, result.stderr or '', ctx)
end end
vim.api.nvim_exec_autocmds('User', { vim.api.nvim_exec_autocmds('User', {
pattern = 'RenderCompileFailed', pattern = 'PreviewCompileFailed',
data = { data = {
bufnr = bufnr, bufnr = bufnr,
provider = name, provider = name,
@ -102,7 +105,7 @@ function M.compile(bufnr, name, provider, ctx)
}) })
vim.api.nvim_exec_autocmds('User', { vim.api.nvim_exec_autocmds('User', {
pattern = 'RenderCompileStarted', pattern = 'PreviewCompileStarted',
data = { bufnr = bufnr, provider = name }, data = { bufnr = bufnr, provider = name },
}) })
end end
@ -134,15 +137,69 @@ function M.stop_all()
for bufnr, _ in pairs(active) do for bufnr, _ in pairs(active) do
M.stop(bufnr) M.stop(bufnr)
end end
for bufnr, _ in pairs(watching) do
M.unwatch(bufnr)
end
end end
---@param bufnr integer ---@param bufnr integer
---@param name string ---@param name string
---@param provider render.ProviderConfig ---@param provider preview.ProviderConfig
---@param ctx render.Context ---@param ctx_builder fun(bufnr: integer): preview.Context
function M.watch(bufnr, name, provider, ctx_builder)
if watching[bufnr] then
M.unwatch(bufnr)
return
end
local au_id = vim.api.nvim_create_autocmd('BufWritePost', {
buffer = bufnr,
callback = function()
local ctx = ctx_builder(bufnr)
M.compile(bufnr, name, provider, ctx)
end,
})
watching[bufnr] = au_id
log.dbg('watching buffer %d with provider "%s"', bufnr, name)
vim.api.nvim_create_autocmd('BufWipeout', {
buffer = bufnr,
once = true,
callback = function()
M.unwatch(bufnr)
end,
})
vim.api.nvim_exec_autocmds('User', {
pattern = 'PreviewWatchStarted',
data = { bufnr = bufnr, provider = name },
})
end
---@param bufnr integer
function M.unwatch(bufnr)
local au_id = watching[bufnr]
if not au_id then
return
end
vim.api.nvim_del_autocmd(au_id)
watching[bufnr] = nil
log.dbg('unwatched buffer %d', bufnr)
vim.api.nvim_exec_autocmds('User', {
pattern = 'PreviewWatchStopped',
data = { bufnr = bufnr },
})
end
---@param bufnr integer
---@param name string
---@param provider preview.ProviderConfig
---@param ctx preview.Context
function M.clean(bufnr, name, provider, ctx) function M.clean(bufnr, name, provider, ctx)
if not provider.clean then if not provider.clean then
vim.notify('[render.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 return
end end
@ -160,27 +217,33 @@ function M.clean(bufnr, name, provider, ctx)
vim.schedule_wrap(function(result) vim.schedule_wrap(function(result)
if result.code == 0 then if result.code == 0 then
log.dbg('clean succeeded for buffer %d', bufnr) log.dbg('clean succeeded for buffer %d', bufnr)
vim.notify('[render.nvim] clean complete', vim.log.levels.INFO) vim.notify('[preview.nvim] clean complete', vim.log.levels.INFO)
else else
log.dbg('clean failed for buffer %d (exit code %d)', bufnr, result.code) log.dbg('clean failed for buffer %d (exit code %d)', bufnr, result.code)
vim.notify('[render.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
end) end)
) )
end end
---@param bufnr integer ---@param bufnr integer
---@return render.Status ---@return preview.Status
function M.status(bufnr) function M.status(bufnr)
local proc = active[bufnr] local proc = active[bufnr]
if proc then if proc then
return { compiling = true, provider = proc.provider, output_file = proc.output_file } return {
compiling = true,
watching = watching[bufnr] ~= nil,
provider = proc.provider,
output_file = proc.output_file,
}
end end
return { compiling = false } return { compiling = false, watching = watching[bufnr] ~= nil }
end end
M._test = { M._test = {
active = active, active = active,
watching = watching,
} }
return M return M

View file

@ -1,8 +1,8 @@
local M = {} local M = {}
local log = require('render.log') local log = require('preview.log')
local ns = vim.api.nvim_create_namespace('render') local ns = vim.api.nvim_create_namespace('preview')
---@param bufnr integer ---@param bufnr integer
function M.clear(bufnr) function M.clear(bufnr)
@ -12,9 +12,9 @@ end
---@param bufnr integer ---@param bufnr integer
---@param name string ---@param name string
---@param error_parser fun(stderr: string, ctx: render.Context): render.Diagnostic[] ---@param error_parser fun(stderr: string, ctx: preview.Context): preview.Diagnostic[]
---@param stderr string ---@param stderr string
---@param ctx render.Context ---@param ctx preview.Context
function M.set(bufnr, name, error_parser, stderr, ctx) function M.set(bufnr, name, error_parser, stderr, ctx)
local ok, diagnostics = pcall(error_parser, stderr, ctx) local ok, diagnostics = pcall(error_parser, stderr, ctx)
if not ok then if not ok then

31
lua/preview/health.lua Normal file
View file

@ -0,0 +1,31 @@
local M = {}
function M.check()
vim.health.start('preview.nvim')
if vim.fn.has('nvim-0.11.0') == 1 then
vim.health.ok('Neovim 0.11.0+ detected')
else
vim.health.error('preview.nvim requires Neovim 0.11.0+')
end
local config = require('preview').get_config()
local provider_count = vim.tbl_count(config.providers)
if provider_count == 0 then
vim.health.warn('no providers configured')
else
vim.health.ok(provider_count .. ' provider(s) configured')
end
for ft, provider in pairs(config.providers) do
local bin = provider.cmd[1]
if vim.fn.executable(bin) == 1 then
vim.health.ok('filetype "' .. ft .. '": ' .. bin .. ' found')
else
vim.health.error('filetype "' .. ft .. '": ' .. bin .. ' not found')
end
end
end
return M

View file

@ -1,24 +1,23 @@
---@class render.ProviderConfig ---@class preview.ProviderConfig
---@field cmd string[] ---@field cmd string[]
---@field args? string[]|fun(ctx: render.Context): string[] ---@field args? string[]|fun(ctx: preview.Context): string[]
---@field cwd? string|fun(ctx: render.Context): string ---@field cwd? string|fun(ctx: preview.Context): string
---@field env? table<string, string> ---@field env? table<string, string>
---@field output? string|fun(ctx: render.Context): string ---@field output? string|fun(ctx: preview.Context): string
---@field error_parser? fun(stderr: string, ctx: render.Context): render.Diagnostic[] ---@field error_parser? fun(stderr: string, ctx: preview.Context): preview.Diagnostic[]
---@field clean? string[]|fun(ctx: render.Context): string[] ---@field clean? string[]|fun(ctx: preview.Context): string[]
---@class render.Config ---@class preview.Config
---@field debug boolean|string ---@field debug boolean|string
---@field providers table<string, render.ProviderConfig> ---@field providers table<string, preview.ProviderConfig>
---@field providers_by_ft table<string, string>
---@class render.Context ---@class preview.Context
---@field bufnr integer ---@field bufnr integer
---@field file string ---@field file string
---@field root string ---@field root string
---@field ft string ---@field ft string
---@class render.Diagnostic ---@class preview.Diagnostic
---@field lnum integer ---@field lnum integer
---@field col integer ---@field col integer
---@field message string ---@field message string
@ -27,30 +26,30 @@
---@field end_col? integer ---@field end_col? integer
---@field source? string ---@field source? string
---@class render.Process ---@class preview.Process
---@field obj table ---@field obj table
---@field provider string ---@field provider string
---@field output_file string ---@field output_file string
---@class render ---@class preview
---@field compile fun(bufnr?: integer) ---@field compile fun(bufnr?: integer)
---@field stop fun(bufnr?: integer) ---@field stop fun(bufnr?: integer)
---@field clean fun(bufnr?: integer) ---@field clean fun(bufnr?: integer)
---@field status fun(bufnr?: integer): render.Status ---@field watch fun(bufnr?: integer)
---@field get_config fun(): render.Config ---@field status fun(bufnr?: integer): preview.Status
---@field get_config fun(): preview.Config
local M = {} local M = {}
local compiler = require('render.compiler') local compiler = require('preview.compiler')
local log = require('render.log') local log = require('preview.log')
---@type render.Config ---@type preview.Config
local default_config = { local default_config = {
debug = false, debug = false,
providers = {}, providers = {},
providers_by_ft = {},
} }
---@type render.Config ---@type preview.Config
local config = vim.deepcopy(default_config) local config = vim.deepcopy(default_config)
local initialized = false local initialized = false
@ -61,17 +60,14 @@ local function init()
end end
initialized = true initialized = true
local opts = vim.g.render or {} local opts = vim.g.preview or {}
vim.validate('render config', opts, 'table') vim.validate('preview config', opts, 'table')
if opts.debug ~= nil then if opts.debug ~= nil then
vim.validate('render config.debug', opts.debug, { 'boolean', 'string' }) vim.validate('preview config.debug', opts.debug, { 'boolean', 'string' })
end end
if opts.providers ~= nil then if opts.providers ~= nil then
vim.validate('render config.providers', opts.providers, 'table') vim.validate('preview config.providers', opts.providers, 'table')
end
if opts.providers_by_ft ~= nil then
vim.validate('render config.providers_by_ft', opts.providers_by_ft, 'table')
end end
config = vim.tbl_deep_extend('force', default_config, opts) config = vim.tbl_deep_extend('force', default_config, opts)
@ -79,7 +75,7 @@ local function init()
log.dbg('initialized with %d providers', vim.tbl_count(config.providers)) log.dbg('initialized with %d providers', vim.tbl_count(config.providers))
end end
---@return render.Config ---@return preview.Config
function M.get_config() function M.get_config()
init() init()
return config return config
@ -91,20 +87,15 @@ function M.resolve_provider(bufnr)
init() init()
bufnr = bufnr or vim.api.nvim_get_current_buf() bufnr = bufnr or vim.api.nvim_get_current_buf()
local ft = vim.bo[bufnr].filetype local ft = vim.bo[bufnr].filetype
local name = config.providers_by_ft[ft] if not config.providers[ft] then
if not name then log.dbg('no provider configured for filetype: %s', ft)
log.dbg('no provider mapped for filetype: %s', ft)
return nil return nil
end end
if not config.providers[name] then return ft
log.dbg('provider "%s" mapped for ft "%s" but not configured', name, ft)
return nil
end
return name
end end
---@param bufnr? integer ---@param bufnr? integer
---@return render.Context ---@return preview.Context
function M.build_context(bufnr) function M.build_context(bufnr)
init() init()
bufnr = bufnr or vim.api.nvim_get_current_buf() bufnr = bufnr or vim.api.nvim_get_current_buf()
@ -124,7 +115,7 @@ function M.compile(bufnr)
bufnr = bufnr or vim.api.nvim_get_current_buf() bufnr = bufnr or vim.api.nvim_get_current_buf()
local name = M.resolve_provider(bufnr) local name = M.resolve_provider(bufnr)
if not name then if not name then
vim.notify('[render.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 return
end end
local provider = config.providers[name] local provider = config.providers[name]
@ -145,7 +136,7 @@ function M.clean(bufnr)
bufnr = bufnr or vim.api.nvim_get_current_buf() bufnr = bufnr or vim.api.nvim_get_current_buf()
local name = M.resolve_provider(bufnr) local name = M.resolve_provider(bufnr)
if not name then if not name then
vim.notify('[render.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 return
end end
local provider = config.providers[name] local provider = config.providers[name]
@ -153,13 +144,27 @@ function M.clean(bufnr)
compiler.clean(bufnr, name, provider, ctx) compiler.clean(bufnr, name, provider, ctx)
end end
---@class render.Status ---@param bufnr? integer
function M.watch(bufnr)
init()
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)
return
end
local provider = config.providers[name]
compiler.watch(bufnr, name, provider, M.build_context)
end
---@class preview.Status
---@field compiling boolean ---@field compiling boolean
---@field watching boolean
---@field provider? string ---@field provider? string
---@field output_file? string ---@field output_file? string
---@param bufnr? integer ---@param bufnr? integer
---@return render.Status ---@return preview.Status
function M.status(bufnr) function M.status(bufnr)
init() init()
bufnr = bufnr or vim.api.nvim_get_current_buf() bufnr = bufnr or vim.api.nvim_get_current_buf()

View file

@ -20,7 +20,7 @@ function M.dbg(msg, ...)
if not enabled then if not enabled then
return return
end end
local formatted = '[render.nvim]: ' .. string.format(msg, ...) local formatted = '[preview.nvim]: ' .. string.format(msg, ...)
if log_file then if log_file then
local f = io.open(log_file, 'a') local f = io.open(log_file, 'a')
if f then if f then

40
lua/preview/presets.lua Normal file
View file

@ -0,0 +1,40 @@
local M = {}
---@type preview.ProviderConfig
M.typst = {
cmd = { 'typst', 'compile' },
args = function(ctx)
return { ctx.file }
end,
output = function(ctx)
return ctx.file:gsub('%.typ$', '.pdf')
end,
}
---@type preview.ProviderConfig
M.latex = {
cmd = { 'latexmk' },
args = function(ctx)
return { '-pdf', '-interaction=nonstopmode', ctx.file }
end,
output = function(ctx)
return ctx.file:gsub('%.tex$', '.pdf')
end,
clean = function(ctx)
return { 'latexmk', '-c', ctx.file }
end,
}
---@type preview.ProviderConfig
M.markdown = {
cmd = { 'pandoc' },
args = function(ctx)
local output = ctx.file:gsub('%.md$', '.pdf')
return { ctx.file, '-o', output }
end,
output = function(ctx)
return ctx.file:gsub('%.md$', '.pdf')
end,
}
return M

View file

@ -1,47 +0,0 @@
local M = {}
local subcommands = { 'compile', 'stop', 'clean', 'status' }
---@param args string
local function dispatch(args)
local subcmd = args ~= '' and args or 'compile'
if subcmd == 'compile' then
require('render').compile()
elseif subcmd == 'stop' then
require('render').stop()
elseif subcmd == 'clean' then
require('render').clean()
elseif subcmd == 'status' then
local s = require('render').status()
if s.compiling then
vim.notify('[render.nvim] compiling with "' .. s.provider .. '"', vim.log.levels.INFO)
else
vim.notify('[render.nvim] idle', vim.log.levels.INFO)
end
else
vim.notify('[render.nvim] unknown subcommand: ' .. subcmd, vim.log.levels.ERROR)
end
end
---@param lead string
---@return string[]
local function complete(lead)
return vim.tbl_filter(function(s)
return s:find(lead, 1, true) == 1
end, subcommands)
end
function M.setup()
vim.api.nvim_create_user_command('Render', function(opts)
dispatch(opts.args)
end, {
nargs = '?',
complete = function(lead)
return complete(lead)
end,
desc = 'Compile, stop, clean, or check status of document rendering',
})
end
return M

View file

@ -1,42 +0,0 @@
local M = {}
function M.check()
vim.health.start('render.nvim')
if vim.fn.has('nvim-0.10.0') == 1 then
vim.health.ok('Neovim 0.10.0+ detected')
else
vim.health.error('render.nvim requires Neovim 0.10.0+')
end
local config = require('render').get_config()
local provider_count = vim.tbl_count(config.providers)
if provider_count == 0 then
vim.health.warn('no providers configured')
else
vim.health.ok(provider_count .. ' provider(s) configured')
end
for name, provider in pairs(config.providers) do
local bin = provider.cmd[1]
if vim.fn.executable(bin) == 1 then
vim.health.ok('provider "' .. name .. '": ' .. bin .. ' found')
else
vim.health.error('provider "' .. name .. '": ' .. bin .. ' not found')
end
end
local ft_count = vim.tbl_count(config.providers_by_ft)
if ft_count > 0 then
for ft, name in pairs(config.providers_by_ft) do
if config.providers[name] then
vim.health.ok('filetype "' .. ft .. '" -> provider "' .. name .. '"')
else
vim.health.error('filetype "' .. ft .. '" maps to unknown provider "' .. name .. '"')
end
end
end
end
return M

12
plugin/preview.lua Normal file
View file

@ -0,0 +1,12 @@
if vim.g.loaded_preview then
return
end
vim.g.loaded_preview = 1
require('preview.commands').setup()
vim.api.nvim_create_autocmd('VimLeavePre', {
callback = function()
require('preview.compiler').stop_all()
end,
})

View file

@ -1,12 +0,0 @@
if vim.g.loaded_render then
return
end
vim.g.loaded_render = 1
require('render.commands').setup()
vim.api.nvim_create_autocmd('VimLeavePre', {
callback = function()
require('render.compiler').stop_all()
end,
})

View file

@ -1,14 +1,14 @@
rockspec_format = '3.0' rockspec_format = '3.0'
package = 'render.nvim' package = 'preview.nvim'
version = 'scm-1' version = 'scm-1'
source = { source = {
url = 'git+https://github.com/barrettruth/render.nvim.git', url = 'git+https://github.com/barrettruth/preview.nvim.git',
} }
description = { description = {
summary = 'Async document compilation for Neovim', summary = 'Async document compilation for Neovim',
homepage = 'https://github.com/barrettruth/render.nvim', homepage = 'https://github.com/barrettruth/preview.nvim',
license = 'MIT', license = 'MIT',
} }

View file

@ -6,32 +6,39 @@ describe('commands', function()
end) end)
describe('setup', function() describe('setup', function()
it('creates the :Render command', function() it('creates the :Preview command', function()
require('render.commands').setup() require('preview.commands').setup()
local cmds = vim.api.nvim_get_commands({}) local cmds = vim.api.nvim_get_commands({})
assert.is_not_nil(cmds.Render) assert.is_not_nil(cmds.Preview)
end) end)
end) end)
describe('dispatch', function() describe('dispatch', function()
it('does not error on :Render with no provider', function() it('does not error on :Preview with no provider', function()
require('render.commands').setup() require('preview.commands').setup()
assert.has_no.errors(function() assert.has_no.errors(function()
vim.cmd('Render compile') vim.cmd('Preview compile')
end) end)
end) end)
it('does not error on :Render stop', function() it('does not error on :Preview stop', function()
require('render.commands').setup() require('preview.commands').setup()
assert.has_no.errors(function() assert.has_no.errors(function()
vim.cmd('Render stop') vim.cmd('Preview stop')
end) end)
end) end)
it('does not error on :Render status', function() it('does not error on :Preview status', function()
require('render.commands').setup() require('preview.commands').setup()
assert.has_no.errors(function() assert.has_no.errors(function()
vim.cmd('Render status') vim.cmd('Preview status')
end)
end)
it('does not error on :Preview watch with no provider', function()
require('preview.commands').setup()
assert.has_no.errors(function()
vim.cmd('Preview watch')
end) end)
end) end)
end) end)

View file

@ -5,19 +5,19 @@ describe('compiler', function()
before_each(function() before_each(function()
helpers.reset_config() helpers.reset_config()
compiler = require('render.compiler') compiler = require('preview.compiler')
end) end)
describe('compile', function() describe('compile', function()
it('spawns a process and tracks it in active table', function() it('spawns a process and tracks it in active table', function()
local bufnr = helpers.create_buffer({ 'hello' }, 'text') local bufnr = helpers.create_buffer({ 'hello' }, 'text')
vim.api.nvim_buf_set_name(bufnr, '/tmp/render_test.txt') vim.api.nvim_buf_set_name(bufnr, '/tmp/preview_test.txt')
vim.bo[bufnr].modified = false vim.bo[bufnr].modified = false
local provider = { cmd = { 'echo', 'ok' } } local provider = { cmd = { 'echo', 'ok' } }
local ctx = { local ctx = {
bufnr = bufnr, bufnr = bufnr,
file = '/tmp/render_test.txt', file = '/tmp/preview_test.txt',
root = '/tmp', root = '/tmp',
ft = 'text', ft = 'text',
} }
@ -35,14 +35,14 @@ describe('compiler', function()
helpers.delete_buffer(bufnr) helpers.delete_buffer(bufnr)
end) end)
it('fires RenderCompileStarted event', function() it('fires PreviewCompileStarted event', function()
local bufnr = helpers.create_buffer({ 'hello' }, 'text') local bufnr = helpers.create_buffer({ 'hello' }, 'text')
vim.api.nvim_buf_set_name(bufnr, '/tmp/render_test_event.txt') vim.api.nvim_buf_set_name(bufnr, '/tmp/preview_test_event.txt')
vim.bo[bufnr].modified = false vim.bo[bufnr].modified = false
local fired = false local fired = false
vim.api.nvim_create_autocmd('User', { vim.api.nvim_create_autocmd('User', {
pattern = 'RenderCompileStarted', pattern = 'PreviewCompileStarted',
once = true, once = true,
callback = function() callback = function()
fired = true fired = true
@ -52,7 +52,7 @@ describe('compiler', function()
local provider = { cmd = { 'echo', 'ok' } } local provider = { cmd = { 'echo', 'ok' } }
local ctx = { local ctx = {
bufnr = bufnr, bufnr = bufnr,
file = '/tmp/render_test_event.txt', file = '/tmp/preview_test_event.txt',
root = '/tmp', root = '/tmp',
ft = 'text', ft = 'text',
} }
@ -67,14 +67,14 @@ describe('compiler', function()
helpers.delete_buffer(bufnr) helpers.delete_buffer(bufnr)
end) end)
it('fires RenderCompileSuccess on exit code 0', function() it('fires PreviewCompileSuccess on exit code 0', function()
local bufnr = helpers.create_buffer({ 'hello' }, 'text') local bufnr = helpers.create_buffer({ 'hello' }, 'text')
vim.api.nvim_buf_set_name(bufnr, '/tmp/render_test_success.txt') vim.api.nvim_buf_set_name(bufnr, '/tmp/preview_test_success.txt')
vim.bo[bufnr].modified = false vim.bo[bufnr].modified = false
local succeeded = false local succeeded = false
vim.api.nvim_create_autocmd('User', { vim.api.nvim_create_autocmd('User', {
pattern = 'RenderCompileSuccess', pattern = 'PreviewCompileSuccess',
once = true, once = true,
callback = function() callback = function()
succeeded = true succeeded = true
@ -84,7 +84,7 @@ describe('compiler', function()
local provider = { cmd = { 'true' } } local provider = { cmd = { 'true' } }
local ctx = { local ctx = {
bufnr = bufnr, bufnr = bufnr,
file = '/tmp/render_test_success.txt', file = '/tmp/preview_test_success.txt',
root = '/tmp', root = '/tmp',
ft = 'text', ft = 'text',
} }
@ -99,14 +99,14 @@ describe('compiler', function()
helpers.delete_buffer(bufnr) helpers.delete_buffer(bufnr)
end) end)
it('fires RenderCompileFailed on non-zero exit', function() it('fires PreviewCompileFailed on non-zero exit', function()
local bufnr = helpers.create_buffer({ 'hello' }, 'text') local bufnr = helpers.create_buffer({ 'hello' }, 'text')
vim.api.nvim_buf_set_name(bufnr, '/tmp/render_test_fail.txt') vim.api.nvim_buf_set_name(bufnr, '/tmp/preview_test_fail.txt')
vim.bo[bufnr].modified = false vim.bo[bufnr].modified = false
local failed = false local failed = false
vim.api.nvim_create_autocmd('User', { vim.api.nvim_create_autocmd('User', {
pattern = 'RenderCompileFailed', pattern = 'PreviewCompileFailed',
once = true, once = true,
callback = function() callback = function()
failed = true failed = true
@ -116,7 +116,7 @@ describe('compiler', function()
local provider = { cmd = { 'false' } } local provider = { cmd = { 'false' } }
local ctx = { local ctx = {
bufnr = bufnr, bufnr = bufnr,
file = '/tmp/render_test_fail.txt', file = '/tmp/preview_test_fail.txt',
root = '/tmp', root = '/tmp',
ft = 'text', ft = 'text',
} }
@ -148,13 +148,13 @@ describe('compiler', function()
it('returns compiling during active process', function() it('returns compiling during active process', function()
local bufnr = helpers.create_buffer({ 'hello' }, 'text') local bufnr = helpers.create_buffer({ 'hello' }, 'text')
vim.api.nvim_buf_set_name(bufnr, '/tmp/render_test_status.txt') vim.api.nvim_buf_set_name(bufnr, '/tmp/preview_test_status.txt')
vim.bo[bufnr].modified = false vim.bo[bufnr].modified = false
local provider = { cmd = { 'sleep', '10' } } local provider = { cmd = { 'sleep', '10' } }
local ctx = { local ctx = {
bufnr = bufnr, bufnr = bufnr,
file = '/tmp/render_test_status.txt', file = '/tmp/preview_test_status.txt',
root = '/tmp', root = '/tmp',
ft = 'text', ft = 'text',
} }
@ -173,4 +173,133 @@ describe('compiler', function()
helpers.delete_buffer(bufnr) helpers.delete_buffer(bufnr)
end) end)
end) end)
describe('watch', function()
it('registers autocmd and tracks in watching table', function()
local bufnr = helpers.create_buffer({ 'hello' }, 'text')
vim.api.nvim_buf_set_name(bufnr, '/tmp/preview_test_watch.txt')
local provider = { cmd = { 'echo', 'ok' } }
local ctx_builder = function(b)
return { bufnr = b, file = '/tmp/preview_test_watch.txt', root = '/tmp', ft = 'text' }
end
compiler.watch(bufnr, 'echo', provider, ctx_builder)
assert.is_not_nil(compiler._test.watching[bufnr])
helpers.delete_buffer(bufnr)
end)
it('fires PreviewWatchStarted event', function()
local bufnr = helpers.create_buffer({ 'hello' }, 'text')
vim.api.nvim_buf_set_name(bufnr, '/tmp/preview_test_watch_event.txt')
local fired = false
vim.api.nvim_create_autocmd('User', {
pattern = 'PreviewWatchStarted',
once = true,
callback = function()
fired = true
end,
})
local provider = { cmd = { 'echo', 'ok' } }
local ctx_builder = function(b)
return { bufnr = b, file = '/tmp/preview_test_watch_event.txt', root = '/tmp', ft = 'text' }
end
compiler.watch(bufnr, 'echo', provider, ctx_builder)
assert.is_true(fired)
compiler.unwatch(bufnr)
helpers.delete_buffer(bufnr)
end)
it('toggles off when called again', function()
local bufnr = helpers.create_buffer({ 'hello' }, 'text')
vim.api.nvim_buf_set_name(bufnr, '/tmp/preview_test_watch_toggle.txt')
local provider = { cmd = { 'echo', 'ok' } }
local ctx_builder = function(b)
return { bufnr = b, file = '/tmp/preview_test_watch_toggle.txt', root = '/tmp', ft = 'text' }
end
compiler.watch(bufnr, 'echo', provider, ctx_builder)
assert.is_not_nil(compiler._test.watching[bufnr])
compiler.watch(bufnr, 'echo', provider, ctx_builder)
assert.is_nil(compiler._test.watching[bufnr])
helpers.delete_buffer(bufnr)
end)
it('fires PreviewWatchStopped on unwatch', function()
local bufnr = helpers.create_buffer({ 'hello' }, 'text')
vim.api.nvim_buf_set_name(bufnr, '/tmp/preview_test_watch_stop.txt')
local stopped = false
vim.api.nvim_create_autocmd('User', {
pattern = 'PreviewWatchStopped',
once = true,
callback = function()
stopped = true
end,
})
local provider = { cmd = { 'echo', 'ok' } }
local ctx_builder = function(b)
return { bufnr = b, file = '/tmp/preview_test_watch_stop.txt', root = '/tmp', ft = 'text' }
end
compiler.watch(bufnr, 'echo', provider, ctx_builder)
compiler.unwatch(bufnr)
assert.is_true(stopped)
assert.is_nil(compiler._test.watching[bufnr])
helpers.delete_buffer(bufnr)
end)
it('stop_all clears watches', function()
local bufnr = helpers.create_buffer({ 'hello' }, 'text')
vim.api.nvim_buf_set_name(bufnr, '/tmp/preview_test_watch_stopall.txt')
local provider = { cmd = { 'echo', 'ok' } }
local ctx_builder = function(b)
return {
bufnr = b,
file = '/tmp/preview_test_watch_stopall.txt',
root = '/tmp',
ft = 'text',
}
end
compiler.watch(bufnr, 'echo', provider, ctx_builder)
assert.is_not_nil(compiler._test.watching[bufnr])
compiler.stop_all()
assert.is_nil(compiler._test.watching[bufnr])
helpers.delete_buffer(bufnr)
end)
it('status includes watching state', function()
local bufnr = helpers.create_buffer({ 'hello' }, 'text')
vim.api.nvim_buf_set_name(bufnr, '/tmp/preview_test_watch_status.txt')
local s = compiler.status(bufnr)
assert.is_false(s.watching)
local provider = { cmd = { 'echo', 'ok' } }
local ctx_builder = function(b)
return { bufnr = b, file = '/tmp/preview_test_watch_status.txt', root = '/tmp', ft = 'text' }
end
compiler.watch(bufnr, 'echo', provider, ctx_builder)
s = compiler.status(bufnr)
assert.is_true(s.watching)
compiler.unwatch(bufnr)
helpers.delete_buffer(bufnr)
end)
end)
end) end)

View file

@ -5,7 +5,7 @@ describe('diagnostic', function()
before_each(function() before_each(function()
helpers.reset_config() helpers.reset_config()
diagnostic = require('render.diagnostic') diagnostic = require('preview.diagnostic')
end) end)
describe('clear', function() describe('clear', function()

View file

@ -20,8 +20,8 @@ function M.delete_buffer(bufnr)
end end
function M.reset_config(opts) function M.reset_config(opts)
vim.g.render = opts vim.g.preview = opts
require('render')._test.reset() require('preview')._test.reset()
end end
return M return M

View file

@ -1,30 +1,29 @@
local helpers = require('spec.helpers') local helpers = require('spec.helpers')
describe('render', function() describe('preview', function()
local render local preview
before_each(function() before_each(function()
helpers.reset_config() helpers.reset_config()
render = require('render') preview = require('preview')
end) end)
describe('config', function() describe('config', function()
it('accepts nil config', function() it('accepts nil config', function()
assert.has_no.errors(function() assert.has_no.errors(function()
render.get_config() preview.get_config()
end) end)
end) end)
it('applies default values', function() it('applies default values', function()
local config = render.get_config() local config = preview.get_config()
assert.is_false(config.debug) assert.is_false(config.debug)
assert.are.same({}, config.providers) assert.are.same({}, config.providers)
assert.are.same({}, config.providers_by_ft)
end) end)
it('merges user config with defaults', function() it('merges user config with defaults', function()
helpers.reset_config({ debug = true }) helpers.reset_config({ debug = true })
local config = require('render').get_config() local config = require('preview').get_config()
assert.is_true(config.debug) assert.is_true(config.debug)
assert.are.same({}, config.providers) assert.are.same({}, config.providers)
end) end)
@ -37,13 +36,9 @@ describe('render', function()
args = { '%s' }, args = { '%s' },
}, },
}, },
providers_by_ft = {
typst = 'typst',
},
}) })
local config = require('render').get_config() local config = require('preview').get_config()
assert.is_not_nil(config.providers.typst) assert.is_not_nil(config.providers.typst)
assert.are.equal('typst', config.providers_by_ft.typst)
end) end)
end) end)
@ -53,34 +48,20 @@ describe('render', function()
providers = { providers = {
typst = { cmd = { 'typst', 'compile' } }, typst = { cmd = { 'typst', 'compile' } },
}, },
providers_by_ft = {
typst = 'typst',
},
}) })
render = require('render') preview = require('preview')
end) end)
it('returns provider name for mapped filetype', function() it('returns filetype when provider exists', function()
local bufnr = helpers.create_buffer({}, 'typst') local bufnr = helpers.create_buffer({}, 'typst')
local name = render.resolve_provider(bufnr) local name = preview.resolve_provider(bufnr)
assert.are.equal('typst', name) assert.are.equal('typst', name)
helpers.delete_buffer(bufnr) helpers.delete_buffer(bufnr)
end) end)
it('returns nil for unmapped filetype', function() it('returns nil for unconfigured filetype', function()
local bufnr = helpers.create_buffer({}, 'lua') local bufnr = helpers.create_buffer({}, 'lua')
local name = render.resolve_provider(bufnr) local name = preview.resolve_provider(bufnr)
assert.is_nil(name)
helpers.delete_buffer(bufnr)
end)
it('returns nil when provider name maps to missing config', function()
helpers.reset_config({
providers = {},
providers_by_ft = { typst = 'typst' },
})
local bufnr = helpers.create_buffer({}, 'typst')
local name = require('render').resolve_provider(bufnr)
assert.is_nil(name) assert.is_nil(name)
helpers.delete_buffer(bufnr) helpers.delete_buffer(bufnr)
end) end)
@ -89,7 +70,7 @@ describe('render', function()
describe('build_context', function() describe('build_context', function()
it('builds context from buffer', function() it('builds context from buffer', function()
local bufnr = helpers.create_buffer({}, 'typst') local bufnr = helpers.create_buffer({}, 'typst')
local ctx = render.build_context(bufnr) local ctx = preview.build_context(bufnr)
assert.are.equal(bufnr, ctx.bufnr) assert.are.equal(bufnr, ctx.bufnr)
assert.are.equal('typst', ctx.ft) assert.are.equal('typst', ctx.ft)
assert.is_string(ctx.file) assert.is_string(ctx.file)
@ -101,7 +82,7 @@ describe('render', function()
describe('status', function() describe('status', function()
it('returns idle when nothing is compiling', function() it('returns idle when nothing is compiling', function()
local bufnr = helpers.create_buffer({}) local bufnr = helpers.create_buffer({})
local s = render.status(bufnr) local s = preview.status(bufnr)
assert.is_false(s.compiling) assert.is_false(s.compiling)
assert.is_nil(s.provider) assert.is_nil(s.provider)
helpers.delete_buffer(bufnr) helpers.delete_buffer(bufnr)

88
spec/presets_spec.lua Normal file
View file

@ -0,0 +1,88 @@
describe('presets', function()
local presets
before_each(function()
presets = require('preview.presets')
end)
local ctx = {
bufnr = 1,
file = '/tmp/document.typ',
root = '/tmp',
ft = 'typst',
}
describe('typst', function()
it('has cmd', function()
assert.are.same({ 'typst', 'compile' }, presets.typst.cmd)
end)
it('returns args with file path', function()
local args = presets.typst.args(ctx)
assert.is_table(args)
assert.are.same({ '/tmp/document.typ' }, args)
end)
it('returns pdf output path', function()
local output = presets.typst.output(ctx)
assert.is_string(output)
assert.are.equal('/tmp/document.pdf', output)
end)
end)
describe('latex', function()
local tex_ctx = {
bufnr = 1,
file = '/tmp/document.tex',
root = '/tmp',
ft = 'tex',
}
it('has cmd', function()
assert.are.same({ 'latexmk' }, presets.latex.cmd)
end)
it('returns args with pdf flag and file path', function()
local args = presets.latex.args(tex_ctx)
assert.is_table(args)
assert.are.same({ '-pdf', '-interaction=nonstopmode', '/tmp/document.tex' }, args)
end)
it('returns pdf output path', function()
local output = presets.latex.output(tex_ctx)
assert.is_string(output)
assert.are.equal('/tmp/document.pdf', output)
end)
it('returns clean command', function()
local clean = presets.latex.clean(tex_ctx)
assert.is_table(clean)
assert.are.same({ 'latexmk', '-c', '/tmp/document.tex' }, clean)
end)
end)
describe('markdown', function()
local md_ctx = {
bufnr = 1,
file = '/tmp/document.md',
root = '/tmp',
ft = 'markdown',
}
it('has cmd', function()
assert.are.same({ 'pandoc' }, presets.markdown.cmd)
end)
it('returns args with file and output flag', function()
local args = presets.markdown.args(md_ctx)
assert.is_table(args)
assert.are.same({ '/tmp/document.md', '-o', '/tmp/document.pdf' }, args)
end)
it('returns pdf output path', function()
local output = presets.markdown.output(md_ctx)
assert.is_string(output)
assert.are.equal('/tmp/document.pdf', output)
end)
end)
end)