Skip to content

Commit d20d19f

Browse files
feat: margin for paragraphs
## Details Request: #200 Adds a new paragraph configuration which has 2 properties in addition to the standard `enabled` field. - `min_width`: allows you to specify a minimum width for each paragraph to improve general alignment when using long and short paragraphs - `left_margin`: this functions in the same way as heading and code block margin where a value < 1 is treated as a fraction of the available window space and values >= 1 are just then number of cells to use for margin. We use margin rather than padding since paragraphs do not support a background so padding would not have any visual distenction. Includes a minor refactor to allow `list.clamp` to resolve either a single value or an array of values rather than only having this availble in the heading module. That's still the only place that it's used but in general I think it makes sense to have it more available.
1 parent 06e6134 commit d20d19f

File tree

11 files changed

+171
-35
lines changed

11 files changed

+171
-35
lines changed

README.md

+36-2
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,15 @@ require('render-markdown').setup({
259259
'RenderMarkdownH6',
260260
},
261261
},
262+
paragraph = {
263+
-- Turn on / off paragraph rendering
264+
enabled = true,
265+
-- Amount of margin to add to the left of paragraphs
266+
-- If a floating point value < 1 is provided it is treated as a percentage of the available window space
267+
left_margin = 0,
268+
-- Minimum width to use for paragraphs
269+
min_width = 0,
270+
},
262271
code = {
263272
-- Turn on / off code block & inline code rendering
264273
enabled = true,
@@ -525,8 +534,9 @@ require('render-markdown').setup({
525534
-- More granular configuration mechanism, allows different aspects of buffers
526535
-- to have their own behavior. Values default to the top level configuration
527536
-- if no override is provided. Supports the following fields:
528-
-- enabled, max_file_size, debounce, render_modes, anti_conceal, padding, heading, code,
529-
-- dash, bullet, checkbox, quote, pipe_table, callout, link, sign, indent, win_options
537+
-- enabled, max_file_size, debounce, render_modes, anti_conceal, padding,
538+
-- heading, paragraph, code, dash, bullet, checkbox, quote, pipe_table,
539+
-- callout, link, sign, indent, win_options
530540
overrides = {
531541
-- Overrides for different buftypes, see :h 'buftype'
532542
buftype = {
@@ -637,6 +647,30 @@ require('render-markdown').setup({
637647

638648
</details>
639649

650+
## Paragraphs
651+
652+
[Wiki Page](https://github.com/MeanderingProgrammer/render-markdown.nvim/wiki/Paragraphs)
653+
654+
<details>
655+
656+
<summary>Paragraph Configuration</summary>
657+
658+
```lua
659+
require('render-markdown').setup({
660+
paragraph = {
661+
-- Turn on / off paragraph rendering
662+
enabled = true,
663+
-- Amount of margin to add to the left of paragraphs
664+
-- If a floating point value < 1 is provided it is treated as a percentage of the available window space
665+
left_margin = 0,
666+
-- Minimum width to use for paragraphs
667+
min_width = 0,
668+
},
669+
})
670+
```
671+
672+
</details>
673+
640674
## Code Blocks
641675

642676
[Wiki Page](https://github.com/MeanderingProgrammer/render-markdown.nvim/wiki/CodeBlocks)

doc/render-markdown.txt

+36-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*render-markdown.txt* For 0.10.0 Last change: 2024 October 04
1+
*render-markdown.txt* For 0.10.0 Last change: 2024 October 07
22

33
==============================================================================
44
Table of Contents *render-markdown-table-of-contents*
@@ -13,6 +13,7 @@ Table of Contents *render-markdown-table-of-contents*
1313
5. Commands |render-markdown-commands|
1414
6. Setup |render-markdown-setup|
1515
- Headings |render-markdown-setup-headings|
16+
- Paragraphs |render-markdown-setup-paragraphs|
1617
- Code Blocks |render-markdown-setup-code-blocks|
1718
- Dashed Line |render-markdown-setup-dashed-line|
1819
- List Bullets |render-markdown-setup-list-bullets|
@@ -307,6 +308,15 @@ Default Configuration ~
307308
'RenderMarkdownH6',
308309
},
309310
},
311+
paragraph = {
312+
-- Turn on / off paragraph rendering
313+
enabled = true,
314+
-- Amount of margin to add to the left of paragraphs
315+
-- If a floating point value < 1 is provided it is treated as a percentage of the available window space
316+
left_margin = 0,
317+
-- Minimum width to use for paragraphs
318+
min_width = 0,
319+
},
310320
code = {
311321
-- Turn on / off code block & inline code rendering
312322
enabled = true,
@@ -573,8 +583,9 @@ Default Configuration ~
573583
-- More granular configuration mechanism, allows different aspects of buffers
574584
-- to have their own behavior. Values default to the top level configuration
575585
-- if no override is provided. Supports the following fields:
576-
-- enabled, max_file_size, debounce, render_modes, anti_conceal, padding, heading, code,
577-
-- dash, bullet, checkbox, quote, pipe_table, callout, link, sign, indent, win_options
586+
-- enabled, max_file_size, debounce, render_modes, anti_conceal, padding,
587+
-- heading, paragraph, code, dash, bullet, checkbox, quote, pipe_table,
588+
-- callout, link, sign, indent, win_options
578589
overrides = {
579590
-- Overrides for different buftypes, see :h 'buftype'
580591
buftype = {
@@ -682,6 +693,28 @@ Heading Configuration ~
682693
<
683694

684695

696+
PARAGRAPHS *render-markdown-setup-paragraphs*
697+
698+
Wiki Page
699+
<https://github.com/MeanderingProgrammer/render-markdown.nvim/wiki/Paragraphs>
700+
701+
Paragraph Configuration ~
702+
703+
>lua
704+
require('render-markdown').setup({
705+
paragraph = {
706+
-- Turn on / off paragraph rendering
707+
enabled = true,
708+
-- Amount of margin to add to the left of paragraphs
709+
-- If a floating point value < 1 is provided it is treated as a percentage of the available window space
710+
left_margin = 0,
711+
-- Minimum width to use for paragraphs
712+
min_width = 0,
713+
},
714+
})
715+
<
716+
717+
685718
CODE BLOCKS *render-markdown-setup-code-blocks*
686719

687720
Wiki Page

lua/render-markdown/core/list.lua

+7-3
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,16 @@ function M.cycle(values, index)
6464
end
6565

6666
---@generic T
67-
---@param values T[]
67+
---@param values `T`|T[]
6868
---@param index integer
6969
---@return T
7070
function M.clamp(values, index)
71-
assert(#values >= 1, 'Must have at least one value')
72-
return values[math.min(index, #values)]
71+
if type(values) == 'table' then
72+
assert(#values >= 1, 'Must have at least one value')
73+
return values[math.min(index, #values)]
74+
else
75+
return values
76+
end
7377
end
7478

7579
return M

lua/render-markdown/handler/markdown.lua

+5-2
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,16 @@ function Handler.new(buf)
3535
] @heading)
3636
(setext_heading) @heading
3737
38+
(section (paragraph) @paragraph)
39+
40+
(fenced_code_block) @code
41+
3842
[
3943
(thematic_break)
4044
(minus_metadata)
4145
(plus_metadata)
4246
] @dash
4347
44-
(fenced_code_block) @code
45-
4648
[
4749
(list_marker_plus)
4850
(list_marker_minus)
@@ -65,6 +67,7 @@ function Handler.new(buf)
6567
dash = require('render-markdown.render.dash'),
6668
heading = require('render-markdown.render.heading'),
6769
list_marker = require('render-markdown.render.list_marker'),
70+
paragraph = require('render-markdown.render.paragraph'),
6871
quote = require('render-markdown.render.quote'),
6972
section = require('render-markdown.render.section'),
7073
table = require('render-markdown.render.table'),

lua/render-markdown/health.lua

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

66
---@private
7-
M.version = '7.3.0'
7+
M.version = '7.3.1'
88

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

lua/render-markdown/init.lua

+18-2
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,11 @@ local M = {}
134134
---@field public highlight? string
135135
---@field public highlight_inline? string
136136

137+
---@class (exact) render.md.UserParagraph
138+
---@field public enabled? boolean
139+
---@field public left_margin? number
140+
---@field public min_width? integer
141+
137142
---@alias render.md.heading.Position 'overlay'|'inline'
138143
---@alias render.md.heading.Width 'full'|'block'
139144

@@ -176,6 +181,7 @@ local M = {}
176181
---@field public anti_conceal? render.md.UserAntiConceal
177182
---@field public padding? render.md.UserPadding
178183
---@field public heading? render.md.UserHeading
184+
---@field public paragraph? render.md.UserParagraph
179185
---@field public code? render.md.UserCode
180186
---@field public dash? render.md.UserDash
181187
---@field public bullet? render.md.UserBullet
@@ -335,6 +341,15 @@ M.default_config = {
335341
'RenderMarkdownH6',
336342
},
337343
},
344+
paragraph = {
345+
-- Turn on / off paragraph rendering
346+
enabled = true,
347+
-- Amount of margin to add to the left of paragraphs
348+
-- If a floating point value < 1 is provided it is treated as a percentage of the available window space
349+
left_margin = 0,
350+
-- Minimum width to use for paragraphs
351+
min_width = 0,
352+
},
338353
code = {
339354
-- Turn on / off code block & inline code rendering
340355
enabled = true,
@@ -601,8 +616,9 @@ M.default_config = {
601616
-- More granular configuration mechanism, allows different aspects of buffers
602617
-- to have their own behavior. Values default to the top level configuration
603618
-- if no override is provided. Supports the following fields:
604-
-- enabled, max_file_size, debounce, render_modes, anti_conceal, padding, heading, code,
605-
-- dash, bullet, checkbox, quote, pipe_table, callout, link, sign, indent, win_options
619+
-- enabled, max_file_size, debounce, render_modes, anti_conceal, padding,
620+
-- heading, paragraph, code, dash, bullet, checkbox, quote, pipe_table,
621+
-- callout, link, sign, indent, win_options
606622
overrides = {
607623
-- Overrides for different buftypes, see :h 'buftype'
608624
buftype = {

lua/render-markdown/render/heading.lua

+5-18
Original file line numberDiff line numberDiff line change
@@ -59,30 +59,17 @@ function Render:setup()
5959
sign = list.cycle(self.heading.signs, level),
6060
foreground = list.clamp(self.heading.foregrounds, level),
6161
background = list.clamp(self.heading.backgrounds, level),
62-
width = Render.resolve(self.heading.width, level),
63-
left_margin = Render.resolve(self.heading.left_margin, level),
64-
left_pad = Render.resolve(self.heading.left_pad, level),
65-
right_pad = Render.resolve(self.heading.right_pad, level),
66-
min_width = Render.resolve(self.heading.min_width, level),
62+
width = list.clamp(self.heading.width, level),
63+
left_margin = list.clamp(self.heading.left_margin, level),
64+
left_pad = list.clamp(self.heading.left_pad, level),
65+
right_pad = list.clamp(self.heading.right_pad, level),
66+
min_width = list.clamp(self.heading.min_width, level),
6767
end_row = self.info.end_row + (atx and 1 or 0),
6868
}
6969

7070
return true
7171
end
7272

73-
---@private
74-
---@generic T
75-
---@param values `T`|T[]
76-
---@param level integer
77-
---@return T
78-
function Render.resolve(values, level)
79-
if type(values) == 'table' then
80-
return list.clamp(values, level)
81-
else
82-
return values
83-
end
84-
end
85-
8673
function Render:render()
8774
local width = self:width(self:icon())
8875
if self.heading.sign then
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
local Base = require('render-markdown.render.base')
2+
local Iter = require('render-markdown.core.iter')
3+
local str = require('render-markdown.core.str')
4+
5+
---@class render.md.render.Paragraph: render.md.Renderer
6+
---@field private paragraph render.md.Paragraph
7+
local Render = setmetatable({}, Base)
8+
Render.__index = Render
9+
10+
---@param marks render.md.Marks
11+
---@param config render.md.buffer.Config
12+
---@param context render.md.Context
13+
---@param info render.md.NodeInfo
14+
---@return render.md.Renderer
15+
function Render:new(marks, config, context, info)
16+
return Base.new(self, marks, config, context, info)
17+
end
18+
19+
---@return boolean
20+
function Render:setup()
21+
self.paragraph = self.config.paragraph
22+
return self.paragraph.enabled and self.paragraph.left_margin > 0
23+
end
24+
25+
function Render:render()
26+
local width = vim.fn.max(Iter.list.map(self.info:lines(), str.width))
27+
width = math.max(width, self.paragraph.min_width)
28+
local margin = self.context:resolve_offset(self.paragraph.left_margin, width)
29+
if margin <= 0 then
30+
return
31+
end
32+
33+
local virt_text = { { str.pad(margin), self.config.padding.highlight } }
34+
for row = self.info.start_row, self.info.end_row - 1 do
35+
self.marks:add(false, row, 0, {
36+
priority = 0,
37+
virt_text = virt_text,
38+
virt_text_pos = 'inline',
39+
})
40+
end
41+
end
42+
43+
return Render

lua/render-markdown/state.lua

+13-4
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ function M.default_buffer_config()
104104
anti_conceal = config.anti_conceal,
105105
padding = config.padding,
106106
heading = config.heading,
107+
paragraph = config.paragraph,
107108
code = config.code,
108109
dash = config.dash,
109110
bullet = config.bullet,
@@ -145,6 +146,12 @@ function M.validate()
145146
:one_or_list_of('width', { 'full', 'block' })
146147
:check()
147148

149+
validator
150+
:spec(path, config, 'paragraph', nilable)
151+
:type('enabled', 'boolean')
152+
:type({ 'left_margin', 'min_width' }, 'number')
153+
:check()
154+
148155
validator
149156
:spec(path, config, 'code', nilable)
150157
:type({ 'enabled', 'sign' }, 'boolean')
@@ -241,8 +248,9 @@ function M.validate()
241248
:spec('', config)
242249
:type('enabled', 'boolean')
243250
:type({ 'max_file_size', 'debounce' }, 'number')
244-
:type({ 'anti_conceal', 'padding', 'heading', 'code', 'dash', 'bullet', 'checkbox' }, 'table')
245-
:type({ 'quote', 'pipe_table', 'callout', 'link', 'sign', 'indent', 'win_options' }, 'table')
251+
:type({ 'anti_conceal', 'padding', 'heading', 'paragraph', 'code' }, 'table')
252+
:type({ 'dash', 'bullet', 'checkbox', 'quote', 'pipe_table' }, 'table')
253+
:type({ 'callout', 'link', 'sign', 'indent', 'win_options' }, 'table')
246254
:list('render_modes', 'string', 'boolean')
247255
:type('log_runtime', 'boolean')
248256
:type({ 'injections', 'latex', 'overrides', 'custom_handlers' }, 'table')
@@ -270,8 +278,9 @@ function M.validate()
270278
override_spec:for_each(function(spec)
271279
spec:type('enabled', 'boolean')
272280
:type({ 'max_file_size', 'debounce' }, 'number')
273-
:type({ 'anti_conceal', 'padding', 'heading', 'code', 'dash', 'bullet', 'checkbox' }, 'table')
274-
:type({ 'quote', 'pipe_table', 'callout', 'link', 'sign', 'indent', 'win_options' }, 'table')
281+
:type({ 'anti_conceal', 'padding', 'heading', 'paragraph', 'code' }, 'table')
282+
:type({ 'dash', 'bullet', 'checkbox', 'quote', 'pipe_table' }, 'table')
283+
:type({ 'callout', 'link', 'sign', 'indent', 'win_options' }, 'table')
275284
:list('render_modes', 'string', 'boolean')
276285
:check()
277286
validate_buffer_config(spec:get_suffix(), spec:get_input(), true)

lua/render-markdown/types.lua

+6
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@
110110
---@field public highlight string
111111
---@field public highlight_inline string
112112

113+
---@class (exact) render.md.Paragraph
114+
---@field public enabled boolean
115+
---@field public left_margin number
116+
---@field public min_width integer
117+
113118
---@class (exact) render.md.Heading
114119
---@field public enabled boolean
115120
---@field public sign boolean
@@ -149,6 +154,7 @@
149154
---@field public anti_conceal render.md.AntiConceal
150155
---@field public padding render.md.Padding
151156
---@field public heading render.md.Heading
157+
---@field public paragraph render.md.Paragraph
152158
---@field public code render.md.Code
153159
---@field public dash render.md.Dash
154160
---@field public bullet render.md.Bullet

scripts/update.py

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ def update_readme(init_file: Path, readme_file: Path) -> None:
8383

8484
parameters: list[str] = [
8585
"heading",
86+
"paragraph",
8687
"code",
8788
"dash",
8889
"bullet",

0 commit comments

Comments
 (0)