Skip to content

Commit 060c911

Browse files
feat: provide more capable render API
## Details Adds a new wrapper `render` API accessible via: `require('render-markdown').render`, built to integrate with other plugins, be more user friendly, have sane defaults, and a more powerful and extensible set of features. This is meant to (eventually) replace all existing usage of the bare `ui` module's `update` method. This is currently used by picker plugins like `fzf-lua` and `snacks.nvim`. Rather than taking multiple parameters the method accepts a single table as input, with most fields now being optional, only `buf` is mandatory. This method supports taking an input configuration as well, allowing callers of the method to modify rendering settings for buffers owned by them. The majority of the implementation is based on `snacks.nvim`. In the future the current logic: ```lua local UI = require("render-markdown.core.ui") local State = require("render-markdown.state") local s = State.get(buf) s.render_modes = true s.resolved.modes = true local wins = vim.fn.win_findbuf(buf) for _, win in ipairs(wins) do UI.update(buf, win, "Snacks", true) end ``` Can be replaced with the following: ```lua require("render-markdown").render({ buf = buf, event = "Snacks", config = { render_modes = true }, }) ``` Where the `event` value can be removed, defaults to `Api`. > [!NOTE] > While this is added under the API umbrella it cannot be called via the > command line, only through lua code. As part of this change some related changes were made: - The deferred initialization of several components, like completions sources, is moved outside of `manger` and into `state` to handle the case where the API is the first buffer being rendered by this plugin. - Handling preview buffer overrides is now part of the main `config` module rather than partially in `state`. Mostly unrelated changes: - Added `ensure` helper method to `list` module, improves common handling of getting a single value from multiple kinds of input. - Fix presets in preview override, reduce number of empty tables returned by `presets.get`. - Improve type inference in `resolved` module, still not perfect but fewer warnings. - `max_file_size` is no longer a buffer local configuration, decision making on what buffers to attach to should be global, anything more granular should use the `ignore` callback instead.
1 parent a1b2bf0 commit 060c911

File tree

24 files changed

+196
-177
lines changed

24 files changed

+196
-177
lines changed

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,6 @@ require('render-markdown').setup({
188188
-- components. Individual components can be enabled for other modes. Remaining modes will be
189189
-- unaffected by this plugin.
190190
render_modes = { 'n', 'c', 't' },
191-
-- Maximum file size (in MB) that this plugin will attempt to render.
192-
-- File larger than this will effectively be ignored.
193-
max_file_size = 10.0,
194191
-- Milliseconds that must pass before updating marks, updates occur.
195192
-- within the context of the visible window, not the entire buffer.
196193
debounce = 100,
@@ -208,6 +205,9 @@ require('render-markdown').setup({
208205
log_runtime = false,
209206
-- Filetypes this plugin will run on.
210207
file_types = { 'markdown' },
208+
-- Maximum file size (in MB) that this plugin will attempt to render.
209+
-- File larger than this will effectively be ignored.
210+
max_file_size = 10.0,
211211
-- Takes buffer as input, if it returns true this plugin will not attach to the buffer.
212212
ignore = function()
213213
return false
@@ -912,9 +912,9 @@ require('render-markdown').setup({
912912
-- More granular configuration mechanism, allows different aspects of buffers to have their own
913913
-- behavior. Values default to the top level configuration if no override is provided. Supports
914914
-- the following fields:
915-
-- enabled, render_modes, max_file_size, debounce, anti_conceal, bullet, callout, checkbox,
916-
-- code, dash, document, heading, html, indent, inline_highlight, latex, link, padding,
917-
-- paragraph, pipe_table, quote, sign, win_options, yaml
915+
-- enabled, render_modes, debounce, anti_conceal, bullet, callout, checkbox, code, dash,
916+
-- document, heading, html, indent, inline_highlight, latex, link, padding, paragraph,
917+
-- pipe_table, quote, sign, win_options, yaml
918918

919919
-- Override for different buflisted values, @see :h 'buflisted'.
920920
buflisted = {},

doc/render-markdown.txt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*render-markdown.txt* For NVIM v0.11.5 Last change: 2025 November 03
1+
*render-markdown.txt* For NVIM v0.11.5 Last change: 2025 November 05
22

33
==============================================================================
44
Table of Contents *render-markdown-table-of-contents*
@@ -254,9 +254,6 @@ Default Configuration ~
254254
-- components. Individual components can be enabled for other modes. Remaining modes will be
255255
-- unaffected by this plugin.
256256
render_modes = { 'n', 'c', 't' },
257-
-- Maximum file size (in MB) that this plugin will attempt to render.
258-
-- File larger than this will effectively be ignored.
259-
max_file_size = 10.0,
260257
-- Milliseconds that must pass before updating marks, updates occur.
261258
-- within the context of the visible window, not the entire buffer.
262259
debounce = 100,
@@ -274,6 +271,9 @@ Default Configuration ~
274271
log_runtime = false,
275272
-- Filetypes this plugin will run on.
276273
file_types = { 'markdown' },
274+
-- Maximum file size (in MB) that this plugin will attempt to render.
275+
-- File larger than this will effectively be ignored.
276+
max_file_size = 10.0,
277277
-- Takes buffer as input, if it returns true this plugin will not attach to the buffer.
278278
ignore = function()
279279
return false
@@ -978,9 +978,9 @@ Default Configuration ~
978978
-- More granular configuration mechanism, allows different aspects of buffers to have their own
979979
-- behavior. Values default to the top level configuration if no override is provided. Supports
980980
-- the following fields:
981-
-- enabled, render_modes, max_file_size, debounce, anti_conceal, bullet, callout, checkbox,
982-
-- code, dash, document, heading, html, indent, inline_highlight, latex, link, padding,
983-
-- paragraph, pipe_table, quote, sign, win_options, yaml
981+
-- enabled, render_modes, debounce, anti_conceal, bullet, callout, checkbox, code, dash,
982+
-- document, heading, html, indent, inline_highlight, latex, link, padding, paragraph,
983+
-- pipe_table, quote, sign, win_options, yaml
984984

985985
-- Override for different buflisted values, @see :h 'buflisted'.
986986
buflisted = {},

lua/render-markdown/api.lua

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,31 @@
1+
---@class render.md.render.Context
2+
---@field buf integer
3+
---@field win? integer|integer[]
4+
---@field event? string
5+
---@field config? render.md.partial.UserConfig
6+
17
---@class render.md.Api
28
local M = {}
39

10+
---@param ctx render.md.render.Context
11+
function M.render(ctx)
12+
local env = require('render-markdown.lib.env')
13+
local list = require('render-markdown.lib.list')
14+
local state = require('render-markdown.state')
15+
local ui = require('render-markdown.core.ui')
16+
17+
local buf = ctx.buf
18+
local wins = list.ensure(ctx.win or env.buf.wins(buf))
19+
local event = ctx.event or 'Api'
20+
21+
state.get(buf, ctx.config)
22+
state.attach()
23+
24+
for _, win in ipairs(wins) do
25+
ui.update(buf, win, event, true)
26+
end
27+
end
28+
429
---@return boolean
530
function M.get()
631
return require('render-markdown.state').enabled

lua/render-markdown/core/command.lua

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,36 @@
11
local api = require('render-markdown.api')
22

3-
---@class render.md.Command
4-
local M = {}
5-
6-
---@private
7-
M.name = 'RenderMarkdown'
8-
9-
---@private
10-
M.plugin = 'render-markdown.nvim'
11-
12-
---@private
3+
local name = 'RenderMarkdown'
4+
local plugin = 'render-markdown.nvim'
135
---@type table<string, type?>
14-
M.args = {
6+
local method_args = {
157
set = 'boolean',
168
set_buf = 'boolean',
179
}
10+
---@type string[]
11+
local code_only = { 'render' }
12+
13+
---@class render.md.Command
14+
local M = {}
1815

1916
---called from plugin directory
2017
function M.init()
21-
vim.api.nvim_create_user_command(M.name, M.command, {
18+
vim.api.nvim_create_user_command(name, M.command, {
2219
nargs = '*',
23-
desc = M.plugin .. ' commands',
20+
desc = plugin .. ' commands',
2421
---@param cmdline string
2522
---@param col integer
2623
---@return string[]
2724
complete = function(_, cmdline, col)
28-
local line = cmdline:sub(1, col):match('^' .. M.name .. '%s+(.*)$')
25+
local line = cmdline:sub(1, col):match('^' .. name .. '%s+(.*)$')
2926
if line then
3027
local fargs = vim.split(line, '%s+')
3128
if #fargs == 1 then
32-
return M.matches(fargs[1], vim.tbl_keys(api))
29+
return M.matches(fargs[1], vim.tbl_keys(api), code_only)
3330
elseif #fargs == 2 then
34-
local arg = M.args[fargs[1]]
31+
local arg = method_args[fargs[1]]
3532
if arg == 'boolean' then
36-
return M.matches(fargs[2], { 'true', 'false' })
33+
return M.matches(fargs[2], { 'true', 'false' }, {})
3734
end
3835
end
3936
end
@@ -45,12 +42,15 @@ end
4542
---@private
4643
---@param prefix string
4744
---@param values string[]
45+
---@param skip string[]
4846
---@return string[]
49-
function M.matches(prefix, values)
47+
function M.matches(prefix, values, skip)
5048
local result = {} ---@type string[]
5149
for _, value in ipairs(values) do
52-
if vim.startswith(value, prefix) then
53-
result[#result + 1] = value
50+
if not vim.tbl_contains(skip, value) then
51+
if vim.startswith(value, prefix) then
52+
result[#result + 1] = value
53+
end
5454
end
5555
end
5656
return result
@@ -61,7 +61,7 @@ end
6161
function M.command(args)
6262
local err = M.run(args.fargs)
6363
if err then
64-
vim.notify(('%s: %s'):format(M.plugin, err), vim.log.levels.ERROR)
64+
vim.notify(('%s: %s'):format(plugin, err), vim.log.levels.ERROR)
6565
end
6666
end
6767

@@ -72,23 +72,23 @@ function M.run(fargs)
7272
if #fargs > 2 then
7373
return ('invalid # arguments - %d'):format(#fargs)
7474
end
75-
local name = fargs[1] or 'enable'
76-
local command = api[name] --[[@as fun(enable?: boolean)?]]
77-
if not command then
78-
return ('invalid command - %s'):format(name)
75+
local method = fargs[1] or 'enable'
76+
local command = api[method] --[[@as fun(enable?: boolean)?]]
77+
if not command or vim.tbl_contains(code_only, method) then
78+
return ('invalid command - %s'):format(method)
7979
end
8080
if #fargs == 2 then
81-
local arg = M.args[name]
81+
local arg = method_args[method]
8282
local value = fargs[2]
8383
if not arg then
84-
return ('no arguments allowed - %s'):format(name)
84+
return ('no arguments allowed - %s'):format(method)
8585
elseif arg == 'boolean' then
8686
if value == 'true' then
8787
command(true)
8888
elseif value == 'false' then
8989
command(false)
9090
else
91-
return ('invalid argument - %s(%s)'):format(name, value)
91+
return ('invalid argument - %s(%s)'):format(method, value)
9292
end
9393
else
9494
return ('bug unhandled type - %s'):format(arg)

lua/render-markdown/core/manager.lua

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,7 @@ function M.attach(buf)
8686

8787
local config = state.get(buf)
8888
state.on.attach({ buf = buf })
89-
require('render-markdown.core.ts').init()
90-
if state.completions.lsp.enabled then
91-
require('render-markdown.integ.lsp').init()
92-
elseif state.completions.blink.enabled then
93-
require('render-markdown.integ.blink').init()
94-
elseif state.completions.coq.enabled then
95-
require('render-markdown.integ.coq').init()
96-
else
97-
require('render-markdown.integ.cmp').init()
98-
end
89+
state.attach()
9990

10091
local events = {
10192
'BufWinEnter',
@@ -163,7 +154,7 @@ function M.should_attach(buf)
163154
end
164155

165156
local file_size = env.file_size_mb(buf)
166-
local max_file_size = state.get(buf).max_file_size
157+
local max_file_size = state.max_file_size
167158
if file_size > max_file_size then
168159
local reason = ('%f > %f'):format(file_size, max_file_size)
169160
log.attach(buf, 'skip', 'file size', reason)

lua/render-markdown/core/ts.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function M.setup()
1919
end
2020
end
2121

22-
---called from manager on buffer attach
22+
---called from state on attach
2323
function M.init()
2424
if M.initialized then
2525
return

lua/render-markdown/health.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ local state = require('render-markdown.state')
66
local M = {}
77

88
---@private
9-
M.version = '8.9.13'
9+
M.version = '8.9.14'
1010

1111
function M.check()
1212
M.start('versions')

lua/render-markdown/init.lua

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ local M = {}
88
---@field log_level render.md.log.Level
99
---@field log_runtime boolean
1010
---@field file_types string[]
11+
---@field max_file_size number
1112
---@field ignore fun(buf: integer): boolean
1213
---@field nested boolean
1314
---@field change_events string[]
@@ -20,7 +21,6 @@ local M = {}
2021
---@field custom_handlers table<string, render.md.Handler>
2122

2223
---@class (exact) render.md.partial.Config: render.md.base.Config
23-
---@field max_file_size number
2424
---@field debounce integer
2525
---@field anti_conceal render.md.anti.conceal.Config
2626
---@field bullet render.md.bullet.Config
@@ -55,9 +55,6 @@ M.default = {
5555
-- components. Individual components can be enabled for other modes. Remaining modes will be
5656
-- unaffected by this plugin.
5757
render_modes = { 'n', 'c', 't' },
58-
-- Maximum file size (in MB) that this plugin will attempt to render.
59-
-- File larger than this will effectively be ignored.
60-
max_file_size = 10.0,
6158
-- Milliseconds that must pass before updating marks, updates occur.
6259
-- within the context of the visible window, not the entire buffer.
6360
debounce = 100,
@@ -75,6 +72,9 @@ M.default = {
7572
log_runtime = false,
7673
-- Filetypes this plugin will run on.
7774
file_types = { 'markdown' },
75+
-- Maximum file size (in MB) that this plugin will attempt to render.
76+
-- File larger than this will effectively be ignored.
77+
max_file_size = 10.0,
7878
-- Takes buffer as input, if it returns true this plugin will not attach to the buffer.
7979
ignore = function()
8080
return false

lua/render-markdown/integ/blink.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Source.__index = Source
99
---@type boolean
1010
Source.initialized = false
1111

12-
---called from manager on buffer attach
12+
---called from state on attach
1313
function Source.init()
1414
if Source.initialized then
1515
return

lua/render-markdown/integ/cmp.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ local M = {}
3636
---@type boolean
3737
M.initialized = false
3838

39-
---called from manager on buffer attach
39+
---called from state on attach
4040
function M.init()
4141
if M.initialized then
4242
return

0 commit comments

Comments
 (0)