Skip to content

Commit 591e256

Browse files
refactor!: pass context table to all user functions instead of parameters
## Details This modifies every user accessible function to take a single context table as input rather than a growing list of parameters. This makes adding parameters to existing functions as well as using the functions easier since you no longer need to pay attention to the order of arguments but does unfortunately break existing users, hence the major version version bump. The fix to any errors is straightforward as the fields of the context continue to have the same names. So if you have an existing function like: ```lua function(param1, param2) vim.print(param1) vim.print(param2) end ``` The fixed version would be: ```lua function(ctx) vim.print(ctx.param1) vim.print(ctx.param2) end ``` If you use the same parameters many times in the function and don't want to add the `ctx.` prefix everywhere you can add a line at the top to define local variables with the same name as before and keep the rest of the function body unchanged: ```lua function(ctx) local param1, param2 = ctx.param1, ctx.param2 vim.print(param1) vim.print(param2) end ``` The fields impacted are: - The `parse` functions in `custom_handlers`: - `buf` -> `ctx.buf` - `root` -> `ctx.root` - The callbacks in `on`: `on.attach` & `on.render`: - `buf` -> `ctx.buf` - `bullet.icons` & `bullet.ordered_icons` if a non-default function was set: - `level` -> `ctx.level` - `index` -> `ctx.index` - `value` -> `ctx.value` - `heading.icons` if a function was set: - `sections` -> `ctx.sections`
1 parent 2a9e0ab commit 591e256

16 files changed

+105
-92
lines changed

README.md

+14-14
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ require('render-markdown').setup({
265265
-- Replaces '#+' of 'atx_h._marker'
266266
-- The number of '#' in the heading determines the 'level'
267267
-- The 'level' is used to index into the list using a cycle
268-
-- If the value is a function the input is the nesting level of the heading within sections
268+
-- If the value is a function the input context contains the nesting level of the heading within sections
269269
icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' },
270270
-- Determines how icons fill the available space:
271271
-- right: '#'s are concealed and icon is appended to right side
@@ -427,20 +427,20 @@ require('render-markdown').setup({
427427
render_modes = false,
428428
-- Replaces '-'|'+'|'*' of 'list_item'
429429
-- How deeply nested the list is determines the 'level', how far down at that level determines the 'index'
430-
-- If a function is provided both of these values are passed in using 1 based indexing
430+
-- If a function is provided both of these values are provided in the context using 1 based indexing
431431
-- If a list is provided we index into it using a cycle based on the level
432432
-- If the value at that level is also a list we further index into it using a clamp based on the index
433433
-- If the item is a 'checkbox' a conceal is used to hide the bullet instead
434434
icons = { '', '', '', '' },
435435
-- Replaces 'n.'|'n)' of 'list_item'
436436
-- How deeply nested the list is determines the 'level', how far down at that level determines the 'index'
437-
-- If a function is provided both of these values are passed in using 1 based indexing
437+
-- If a function is provided both of these values are provided in the context using 1 based indexing
438438
-- If a list is provided we index into it using a cycle based on the level
439439
-- If the value at that level is also a list we further index into it using a clamp based on the index
440-
ordered_icons = function(level, index, value)
441-
value = vim.trim(value)
442-
local value_index = tonumber(value:sub(1, #value - 1))
443-
return string.format('%d.', value_index > 1 and value_index or index)
440+
ordered_icons = function(ctx)
441+
local value = vim.trim(ctx.value)
442+
local index = tonumber(value:sub(1, #value - 1))
443+
return string.format('%d.', index > 1 and index or ctx.index)
444444
end,
445445
-- Padding to add to the left of bullet point
446446
left_pad = 0,
@@ -746,7 +746,7 @@ require('render-markdown').setup({
746746
-- Replaces '#+' of 'atx_h._marker'
747747
-- The number of '#' in the heading determines the 'level'
748748
-- The 'level' is used to index into the list using a cycle
749-
-- If the value is a function the input is the nesting level of the heading within sections
749+
-- If the value is a function the input context contains the nesting level of the heading within sections
750750
icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' },
751751
-- Determines how icons fill the available space:
752752
-- right: '#'s are concealed and icon is appended to right side
@@ -968,20 +968,20 @@ require('render-markdown').setup({
968968
render_modes = false,
969969
-- Replaces '-'|'+'|'*' of 'list_item'
970970
-- How deeply nested the list is determines the 'level', how far down at that level determines the 'index'
971-
-- If a function is provided both of these values are passed in using 1 based indexing
971+
-- If a function is provided both of these values are provided in the context using 1 based indexing
972972
-- If a list is provided we index into it using a cycle based on the level
973973
-- If the value at that level is also a list we further index into it using a clamp based on the index
974974
-- If the item is a 'checkbox' a conceal is used to hide the bullet instead
975975
icons = { '', '', '', '' },
976976
-- Replaces 'n.'|'n)' of 'list_item'
977977
-- How deeply nested the list is determines the 'level', how far down at that level determines the 'index'
978-
-- If a function is provided both of these values are passed in using 1 based indexing
978+
-- If a function is provided both of these values are provided in the context using 1 based indexing
979979
-- If a list is provided we index into it using a cycle based on the level
980980
-- If the value at that level is also a list we further index into it using a clamp based on the index
981-
ordered_icons = function(level, index, value)
982-
value = vim.trim(value)
983-
local value_index = tonumber(value:sub(1, #value - 1))
984-
return string.format('%d.', value_index > 1 and value_index or index)
981+
ordered_icons = function(ctx)
982+
local value = vim.trim(ctx.value)
983+
local index = tonumber(value:sub(1, #value - 1))
984+
return string.format('%d.', index > 1 and index or ctx.index)
985985
end,
986986
-- Padding to add to the left of bullet point
987987
left_pad = 0,

doc/custom-handlers.md

+9-5
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,19 @@ Each handler must conform to the following interface:
1818
---@field public start_col integer
1919
---@field public opts vim.api.keyset.set_extmark
2020

21+
---@class (exact) render.md.HandlerContext
22+
---@field public buf integer
23+
---@field public root TSNode
24+
2125
---@class (exact) render.md.Handler
2226
---@field public extends? boolean
23-
---@field public parse fun(root: TSNode, buf: integer): render.md.Mark[]
27+
---@field public parse fun(ctx: render.md.HandlerContext): render.md.Mark[]
2428
```
2529

26-
The `parse` function parameters are:
30+
The `parse` function takes a `ctx` parameter whose fields are:
2731

28-
- `root`: The root treesitter node for the specified language
2932
- `buf`: The buffer containing the root node
33+
- `root`: The root treesitter node for the specified language
3034

3135
The `extends` parameter defines whether the builtin handler should still be run in
3236
conjunction with this one. Defaults to `false`.
@@ -71,9 +75,9 @@ This will require a treesitter query and using the range values of nodes.
7175
```lua
7276
-- Parse query outside of the function to avoid doing it for each call
7377
local query = vim.treesitter.query.parse('python', '(function_definition) @def')
74-
local function parse_python(root, buf)
78+
local function parse_python(ctx)
7579
local marks = {}
76-
for id, node in query:iter_captures(root, buf) do
80+
for id, node in query:iter_captures(ctx.root, ctx.buf) do
7781
local capture = query.captures[id]
7882
local start_row, _, _, _ = node:range()
7983
if capture == 'def' then

doc/render-markdown.txt

+15-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*render-markdown.txt* For 0.10.0 Last change: 2025 February 02
1+
*render-markdown.txt* For 0.10.0 Last change: 2025 February 06
22

33
==============================================================================
44
Table of Contents *render-markdown-table-of-contents*
@@ -326,7 +326,7 @@ Default Configuration ~
326326
-- Replaces '#+' of 'atx_h._marker'
327327
-- The number of '#' in the heading determines the 'level'
328328
-- The 'level' is used to index into the list using a cycle
329-
-- If the value is a function the input is the nesting level of the heading within sections
329+
-- If the value is a function the input context contains the nesting level of the heading within sections
330330
icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' },
331331
-- Determines how icons fill the available space:
332332
-- right: '#'s are concealed and icon is appended to right side
@@ -488,20 +488,20 @@ Default Configuration ~
488488
render_modes = false,
489489
-- Replaces '-'|'+'|'*' of 'list_item'
490490
-- How deeply nested the list is determines the 'level', how far down at that level determines the 'index'
491-
-- If a function is provided both of these values are passed in using 1 based indexing
491+
-- If a function is provided both of these values are provided in the context using 1 based indexing
492492
-- If a list is provided we index into it using a cycle based on the level
493493
-- If the value at that level is also a list we further index into it using a clamp based on the index
494494
-- If the item is a 'checkbox' a conceal is used to hide the bullet instead
495495
icons = { '●', '○', '◆', '◇' },
496496
-- Replaces 'n.'|'n)' of 'list_item'
497497
-- How deeply nested the list is determines the 'level', how far down at that level determines the 'index'
498-
-- If a function is provided both of these values are passed in using 1 based indexing
498+
-- If a function is provided both of these values are provided in the context using 1 based indexing
499499
-- If a list is provided we index into it using a cycle based on the level
500500
-- If the value at that level is also a list we further index into it using a clamp based on the index
501-
ordered_icons = function(level, index, value)
502-
value = vim.trim(value)
503-
local value_index = tonumber(value:sub(1, #value - 1))
504-
return string.format('%d.', value_index > 1 and value_index or index)
501+
ordered_icons = function(ctx)
502+
local value = vim.trim(ctx.value)
503+
local index = tonumber(value:sub(1, #value - 1))
504+
return string.format('%d.', index > 1 and index or ctx.index)
505505
end,
506506
-- Padding to add to the left of bullet point
507507
left_pad = 0,
@@ -805,7 +805,7 @@ Heading Configuration ~
805805
-- Replaces '#+' of 'atx_h._marker'
806806
-- The number of '#' in the heading determines the 'level'
807807
-- The 'level' is used to index into the list using a cycle
808-
-- If the value is a function the input is the nesting level of the heading within sections
808+
-- If the value is a function the input context contains the nesting level of the heading within sections
809809
icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' },
810810
-- Determines how icons fill the available space:
811811
-- right: '#'s are concealed and icon is appended to right side
@@ -1019,20 +1019,20 @@ Bullet Point Configuration ~
10191019
render_modes = false,
10201020
-- Replaces '-'|'+'|'*' of 'list_item'
10211021
-- How deeply nested the list is determines the 'level', how far down at that level determines the 'index'
1022-
-- If a function is provided both of these values are passed in using 1 based indexing
1022+
-- If a function is provided both of these values are provided in the context using 1 based indexing
10231023
-- If a list is provided we index into it using a cycle based on the level
10241024
-- If the value at that level is also a list we further index into it using a clamp based on the index
10251025
-- If the item is a 'checkbox' a conceal is used to hide the bullet instead
10261026
icons = { '●', '○', '◆', '◇' },
10271027
-- Replaces 'n.'|'n)' of 'list_item'
10281028
-- How deeply nested the list is determines the 'level', how far down at that level determines the 'index'
1029-
-- If a function is provided both of these values are passed in using 1 based indexing
1029+
-- If a function is provided both of these values are provided in the context using 1 based indexing
10301030
-- If a list is provided we index into it using a cycle based on the level
10311031
-- If the value at that level is also a list we further index into it using a clamp based on the index
1032-
ordered_icons = function(level, index, value)
1033-
value = vim.trim(value)
1034-
local value_index = tonumber(value:sub(1, #value - 1))
1035-
return string.format('%d.', value_index > 1 and value_index or index)
1032+
ordered_icons = function(ctx)
1033+
local value = vim.trim(ctx.value)
1034+
local index = tonumber(value:sub(1, #value - 1))
1035+
return string.format('%d.', index > 1 and index or ctx.index)
10361036
end,
10371037
-- Padding to add to the left of bullet point
10381038
left_pad = 0,

lua/render-markdown/core/ui.lua

+11-12
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ function M.run_update(buf, win, parse)
139139
extmark:show(M.namespace, buf)
140140
end
141141
end
142-
state.on.render(buf)
142+
state.on.render({ buf = buf })
143143
else
144144
M.clear(buf, buffer_state)
145145
end
@@ -190,41 +190,40 @@ function M.parse_buffer(props)
190190
if language == 'markdown' then
191191
table.insert(markdown_roots, tree:root())
192192
else
193-
vim.list_extend(marks, M.parse_tree(buf, language, tree:root()))
193+
vim.list_extend(marks, M.parse_tree({ buf = buf, root = tree:root() }, language))
194194
end
195195
end)
196196
for _, root in ipairs(markdown_roots) do
197-
vim.list_extend(marks, M.parse_tree(buf, 'markdown', root))
197+
vim.list_extend(marks, M.parse_tree({ buf = buf, root = root }, 'markdown'))
198198
end
199199
return Iter.list.map(marks, Extmark.new)
200200
end
201201

202202
---Run user & builtin handlers when available. User handler is always executed,
203203
---builtin handler is skipped if user handler does not specify extends.
204204
---@private
205-
---@param buf integer
205+
---@param ctx render.md.HandlerContext
206206
---@param language string
207-
---@param root TSNode
208207
---@return render.md.Mark[]
209-
function M.parse_tree(buf, language, root)
210-
log.buf('debug', 'language', buf, language)
211-
if not Context.get(buf):overlaps_node(root) then
208+
function M.parse_tree(ctx, language)
209+
log.buf('debug', 'language', ctx.buf, language)
210+
if not Context.get(ctx.buf):overlaps_node(ctx.root) then
212211
return {}
213212
end
214213

215214
local marks = {}
216215
local user = state.custom_handlers[language]
217216
if user ~= nil then
218-
log.buf('debug', 'running handler', buf, 'user')
219-
vim.list_extend(marks, user.parse(root, buf))
217+
log.buf('debug', 'running handler', ctx.buf, 'user')
218+
vim.list_extend(marks, user.parse(ctx))
220219
if not user.extends then
221220
return marks
222221
end
223222
end
224223
local builtin = builtin_handlers[language]
225224
if builtin ~= nil then
226-
log.buf('debug', 'running handler', buf, 'builtin')
227-
vim.list_extend(marks, builtin.parse(root, buf))
225+
log.buf('debug', 'running handler', ctx.buf, 'builtin')
226+
vim.list_extend(marks, builtin.parse(ctx))
228227
end
229228
return marks
230229
end

lua/render-markdown/handler/html.lua

+3-4
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,10 @@ end
4646
---@class render.md.handler.Html: render.md.Handler
4747
local M = {}
4848

49-
---@param root TSNode
50-
---@param buf integer
49+
---@param ctx render.md.HandlerContext
5150
---@return render.md.Mark[]
52-
function M.parse(root, buf)
53-
return Handler.new(buf):parse(root)
51+
function M.parse(ctx)
52+
return Handler.new(ctx.buf):parse(ctx.root)
5453
end
5554

5655
return M

lua/render-markdown/handler/latex.lua

+6-7
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,19 @@ local cache = {}
1212
---@class render.md.handler.Latex: render.md.Handler
1313
local M = {}
1414

15-
---@param root TSNode
16-
---@param buf integer
15+
---@param ctx render.md.HandlerContext
1716
---@return render.md.Mark[]
18-
function M.parse(root, buf)
19-
local latex = state.get(buf).latex
20-
if Context.get(buf):skip(latex) then
17+
function M.parse(ctx)
18+
local latex = state.get(ctx.buf).latex
19+
if Context.get(ctx.buf):skip(latex) then
2120
return {}
2221
end
2322
if vim.fn.executable(latex.converter) ~= 1 then
2423
log.add('debug', 'executable not found', latex.converter)
2524
return {}
2625
end
2726

28-
local node = Node.new(buf, root)
27+
local node = Node.new(ctx.buf, ctx.root)
2928
log.node('latex', node)
3029

3130
local raw_expression = cache[node.text]
@@ -53,7 +52,7 @@ function M.parse(root, buf)
5352
return { { expression, latex.highlight } }
5453
end)
5554

56-
local marks = List.new_marks(buf, true)
55+
local marks = List.new_marks(ctx.buf, true)
5756
marks:add_over(false, node, {
5857
virt_lines = latex_lines,
5958
virt_lines_above = true,

lua/render-markdown/handler/markdown.lua

+3-4
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,10 @@ end
8282
---@class render.md.handler.Markdown: render.md.Handler
8383
local M = {}
8484

85-
---@param root TSNode
86-
---@param buf integer
85+
---@param ctx render.md.HandlerContext
8786
---@return render.md.Mark[]
88-
function M.parse(root, buf)
89-
return Handler.new(buf):parse(root)
87+
function M.parse(ctx)
88+
return Handler.new(ctx.buf):parse(ctx.root)
9089
end
9190

9291
return M

lua/render-markdown/handler/markdown_inline.lua

+3-4
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,10 @@ end
6464
---@class render.md.handler.MarkdownInline: render.md.Handler
6565
local M = {}
6666

67-
---@param root TSNode
68-
---@param buf integer
67+
---@param ctx render.md.HandlerContext
6968
---@return render.md.Mark[]
70-
function M.parse(root, buf)
71-
return Handler.new(buf):parse(root)
69+
function M.parse(ctx)
70+
return Handler.new(ctx.buf):parse(ctx.root)
7271
end
7372

7473
return M

lua/render-markdown/health.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ local state = require('render-markdown.state')
55
local M = {}
66

77
---@private
8-
M.version = '7.9.0'
8+
M.version = '8.0.0'
99

1010
function M.check()
1111
M.start('version')

0 commit comments

Comments
 (0)