Skip to content

Commit bee16b2

Browse files
feat: Support disabling background for all languages but keep borders
## Details Request: #220 This allows the existing `code.disable_background` option to now be a boolean in addition to a list of languages. Booleans apply the same behavior for all languages so when set to `true` all languages will have their backgrounds disabled. This does alter the behavior of a disabled background, now borders above and below the code block will continue to be rendered. If anyone wants to disable the border as well as the background I can add another flag for that. Decoupling these 2 concepts matches how we handle headings as well. Other changes: - Window options are now set for all windows attached to the buffer - Adds `padding_text` method to Base to share common pattern - Removes most usage of window width, replace with number of columns
1 parent 901838c commit bee16b2

23 files changed

+139
-104
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,8 @@ require('render-markdown').setup({
306306
language_name = true,
307307
-- A list of language names for which background highlighting will be disabled
308308
-- Likely because that language has background highlights itself
309+
-- Or a boolean to make behavior apply to all languages
310+
-- Borders above & below blocks will continue to be rendered
309311
disable_background = { 'diff' },
310312
-- Width of the code block background:
311313
-- block: width of the code block
@@ -732,6 +734,8 @@ require('render-markdown').setup({
732734
language_name = true,
733735
-- A list of language names for which background highlighting will be disabled
734736
-- Likely because that language has background highlights itself
737+
-- Or a boolean to make behavior apply to all languages
738+
-- Borders above & below blocks will continue to be rendered
735739
disable_background = { 'diff' },
736740
-- Width of the code block background:
737741
-- block: width of the code block

doc/render-markdown.txt

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*render-markdown.txt* For 0.10.0 Last change: 2024 November 05
1+
*render-markdown.txt* For 0.10.0 Last change: 2024 November 07
22

33
==============================================================================
44
Table of Contents *render-markdown-table-of-contents*
@@ -353,6 +353,8 @@ Default Configuration ~
353353
language_name = true,
354354
-- A list of language names for which background highlighting will be disabled
355355
-- Likely because that language has background highlights itself
356+
-- Or a boolean to make behavior apply to all languages
357+
-- Borders above & below blocks will continue to be rendered
356358
disable_background = { 'diff' },
357359
-- Width of the code block background:
358360
-- block: width of the code block
@@ -773,6 +775,8 @@ Code Block Configuration ~
773775
language_name = true,
774776
-- A list of language names for which background highlighting will be disabled
775777
-- Likely because that language has background highlights itself
778+
-- Or a boolean to make behavior apply to all languages
779+
-- Borders above & below blocks will continue to be rendered
776780
disable_background = { 'diff' },
777781
-- Width of the code block background:
778782
-- block: width of the code block

lua/render-markdown/core/context.lua

+4-3
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ function Context.new(buf, win, mode, offset)
2929
self.win = win
3030

3131
local ranges = { Context.compute_range(self.buf, self.win, offset) }
32-
for _, buf_win in ipairs(vim.fn.win_findbuf(buf)) do
33-
if buf_win ~= self.win then
34-
table.insert(ranges, Context.compute_range(self.buf, buf_win, offset))
32+
for _, window in ipairs(util.windows(buf)) do
33+
if window ~= self.win then
34+
table.insert(ranges, Context.compute_range(self.buf, window, offset))
3535
end
3636
end
3737
self.ranges = Range.coalesce(ranges)
@@ -139,6 +139,7 @@ function Context:resolve_offset(offset, width)
139139
end
140140
end
141141

142+
---@private
142143
---@return integer
143144
function Context:get_width()
144145
if self.window_width == nil then

lua/render-markdown/core/ui.lua

+4-2
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,10 @@ function M.run_update(buf, win, parse)
112112
local next_state = M.next_state(config, win, mode)
113113

114114
log.buf('info', 'state', buf, next_state)
115-
for name, value in pairs(config.win_options) do
116-
util.set('win', win, name, value[next_state])
115+
for _, window in ipairs(util.windows(buf)) do
116+
for name, value in pairs(config.win_options) do
117+
util.set('win', window, name, value[next_state])
118+
end
117119
end
118120

119121
if next_state == 'rendered' then

lua/render-markdown/core/util.lua

+6
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ function M.mode()
4646
return vim.fn.mode(true)
4747
end
4848

49+
---@param buf integer
50+
---@return integer[]
51+
function M.windows(buf)
52+
return vim.fn.win_findbuf(buf)
53+
end
54+
4955
---@param buf integer
5056
---@param win integer
5157
---@return integer?

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.5.0'
7+
M.version = '7.5.1'
88

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

lua/render-markdown/init.lua

+3-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ local M = {}
134134
---@field public position? render.md.code.Position
135135
---@field public language_pad? number
136136
---@field public language_name? boolean
137-
---@field public disable_background? string[]
137+
---@field public disable_background? string[]|boolean
138138
---@field public width? render.md.code.Width
139139
---@field public left_margin? number
140140
---@field public left_pad? number
@@ -419,6 +419,8 @@ M.default_config = {
419419
language_name = true,
420420
-- A list of language names for which background highlighting will be disabled
421421
-- Likely because that language has background highlights itself
422+
-- Or a boolean to make behavior apply to all languages
423+
-- Borders above & below blocks will continue to be rendered
422424
disable_background = { 'diff' },
423425
-- Width of the code block background:
424426
-- block: width of the code block

lua/render-markdown/manager.lua

+2-2
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ function M.attach(buf)
7171
if not state.enabled then
7272
return
7373
end
74-
local win, wins = util.current('win'), vim.fn.win_findbuf(buf)
75-
win = vim.tbl_contains(wins, win) and win or wins[1]
74+
local win, windows = util.current('win'), util.windows(buf)
75+
win = vim.tbl_contains(windows, win) and win or windows[1]
7676
local event = args.event
7777
ui.update(buf, win, event, vim.tbl_contains(change_events, event))
7878
end,

lua/render-markdown/render/base.lua

+9-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ end
8383
function Base:indent_virt_line(line, level)
8484
local amount = self:indent(level)
8585
if amount > 0 then
86-
table.insert(line, 1, { Str.pad(amount), self.config.padding.highlight })
86+
table.insert(line, 1, self:padding_text(amount))
8787
end
8888
return line
8989
end
@@ -109,4 +109,12 @@ function Base:indent(level)
109109
return indent.per_level * level
110110
end
111111

112+
---@protected
113+
---@param width integer
114+
---@param highlight? string
115+
---@return { [1]: string, [2]: string }
116+
function Base:padding_text(width, highlight)
117+
return { Str.pad(width), highlight or self.config.padding.highlight }
118+
end
119+
112120
return Base

lua/render-markdown/render/code.lua

+46-60
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ local colors = require('render-markdown.colors')
66

77
---@class render.md.data.Code
88
---@field col integer
9-
---@field start_row integer
10-
---@field end_row integer
119
---@field code_node? render.md.Node
1210
---@field language_node? render.md.Node
1311
---@field language? string
@@ -55,8 +53,6 @@ function Render:setup()
5553

5654
self.data = {
5755
col = self.node.start_col,
58-
start_row = self.node.start_row,
59-
end_row = self.node.end_row,
6056
code_node = code_node,
6157
language_node = language_node,
6258
language = (language_node or {}).text,
@@ -72,20 +68,23 @@ function Render:setup()
7268
end
7369

7470
function Render:render()
75-
local disabled_language = vim.tbl_contains(self.code.disable_background, self.data.language)
76-
local add_background = vim.tbl_contains({ 'normal', 'full' }, self.code.style) and not disabled_language
71+
local disabled_language = self.code.disable_background
72+
if type(disabled_language) == 'table' then
73+
disabled_language = vim.tbl_contains(disabled_language, self.data.language)
74+
end
75+
local background = vim.tbl_contains({ 'normal', 'full' }, self.code.style) and not disabled_language
7776

78-
local icon_added = self:language(add_background)
79-
if add_background then
80-
self:background(icon_added)
77+
local icon = self:language()
78+
self:border(icon)
79+
if background then
80+
self:background(self.node.start_row + 1, self.node.end_row - 2)
8181
end
82-
self:left_pad(add_background, icon_added)
82+
self:left_pad(background)
8383
end
8484

8585
---@private
86-
---@param add_background boolean
8786
---@return boolean
88-
function Render:language(add_background)
87+
function Render:language()
8988
if not vim.tbl_contains({ 'language', 'full' }, self.code.style) then
9089
return false
9190
end
@@ -103,11 +102,8 @@ function Render:language(add_background)
103102
if self.code.sign then
104103
self:sign(icon, icon_highlight)
105104
end
106-
local highlight = { icon_highlight }
107-
if add_background then
108-
table.insert(highlight, self.code.highlight)
109-
end
110105
local icon_text = icon .. ' '
106+
local highlight = { icon_highlight, self.code.highlight }
111107
if self.code.position == 'left' then
112108
if self.code.language_name and self.context:hidden(node) then
113109
-- Code blocks will pick up varying amounts of leading white space depending on the
@@ -138,40 +134,38 @@ function Render:language(add_background)
138134
end
139135

140136
---@private
141-
---@param icon_added boolean
142-
function Render:background(icon_added)
143-
local width = self.code.width == 'block' and self.data.max_width or self.context:get_width()
144-
145-
if self.code.border == 'thin' then
146-
---@param row integer
147-
---@param icon string
148-
local function add_border(row, icon)
149-
local virt_text = {}
150-
if self.data.margin > 0 then
151-
table.insert(virt_text, { Str.pad(self.data.margin), self.config.padding.highlight })
152-
end
153-
table.insert(virt_text, { icon:rep(width - self.data.col), colors.bg_to_fg(self.code.highlight) })
137+
---@param icon boolean
138+
function Render:border(icon)
139+
---@param row integer
140+
---@param border string
141+
---@param context_hidden boolean
142+
local function add_border(row, border, context_hidden)
143+
local delim_hidden = self.context:hidden(self.node:child('fenced_code_block_delimiter', row))
144+
if self.code.border == 'thin' and context_hidden and delim_hidden then
145+
local width = self.code.width == 'block' and self.data.max_width or vim.o.columns
154146
self.marks:add('code_border', row, self.data.col, {
155-
virt_text = virt_text,
147+
virt_text = { { border:rep(width - self.data.col), colors.bg_to_fg(self.code.highlight) } },
156148
virt_text_pos = 'overlay',
157149
})
158-
end
159-
if not icon_added and self.context:hidden(self.data.code_node) and self:delim_hidden(self.data.start_row) then
160-
add_border(self.data.start_row, self.code.above)
161-
self.data.start_row = self.data.start_row + 1
162-
end
163-
if self:delim_hidden(self.data.end_row - 1) then
164-
add_border(self.data.end_row - 1, self.code.below)
165-
self.data.end_row = self.data.end_row - 1
150+
else
151+
self:background(row, row)
166152
end
167153
end
168154

155+
add_border(self.node.start_row, self.code.above, not icon and self.context:hidden(self.data.code_node))
156+
add_border(self.node.end_row - 1, self.code.below, true)
157+
end
158+
159+
---@private
160+
---@param start_row integer
161+
---@param end_row integer
162+
function Render:background(start_row, end_row)
169163
local win_col, padding = 0, {}
170164
if self.code.width == 'block' then
171-
win_col = self.data.margin + width + self.data.indent
172-
table.insert(padding, { Str.pad(vim.o.columns * 2), self.config.padding.highlight })
165+
win_col = self.data.margin + self.data.max_width + self.data.indent
166+
table.insert(padding, self:padding_text(vim.o.columns * 2))
173167
end
174-
for row = self.data.start_row, self.data.end_row - 1 do
168+
for row = start_row, end_row do
175169
self.marks:add('code_background', row, self.data.col, {
176170
end_row = row + 1,
177171
hl_group = self.code.highlight,
@@ -189,38 +183,30 @@ function Render:background(icon_added)
189183
end
190184

191185
---@private
192-
---@param row integer
193-
---@return boolean
194-
function Render:delim_hidden(row)
195-
return self.context:hidden(self.node:child('fenced_code_block_delimiter', row))
196-
end
197-
198-
---@private
199-
---@param add_background boolean
200-
---@param icon_added boolean
201-
function Render:left_pad(add_background, icon_added)
186+
---@param background boolean
187+
function Render:left_pad(background)
202188
local margin, padding = self.data.margin, self.data.padding
203189
if (self.data.col == 0 or #self.data.empty_rows == 0) and margin <= 0 and padding <= 0 then
204190
return
205191
end
206192

207-
-- Use low priority to include other marks in padding when code block is at edge
208-
local priority = self.data.col == 0 and 0 or nil
209-
local fill_text = { Str.pad(self.data.col), self.config.padding.highlight }
210-
local margin_text = { Str.pad(margin), self.config.padding.highlight }
211-
local background = add_background and self.code.highlight or self.config.padding.highlight
212-
local padding_text = { Str.pad(padding), background }
193+
-- Use lowest priority (0) to include all other marks in padding when code block is at edge
194+
-- Use medium priority (1000) to include border marks while likely avoiding other plugin
195+
local priority = self.data.col == 0 and 0 or 1000
196+
local fill_text = self:padding_text(self.data.col)
197+
local margin_text = self:padding_text(margin)
198+
local padding_text = self:padding_text(padding, background and self.code.highlight or nil)
213199

214-
for row = self.data.start_row, self.data.end_row - 1 do
200+
local start_row, end_row = self.node.start_row, (self.node.end_row - 1)
201+
for row = start_row, end_row do
215202
local virt_text = {}
216203
if self.data.col > 0 and vim.tbl_contains(self.data.empty_rows, row) then
217204
table.insert(virt_text, fill_text)
218205
end
219206
if margin > 0 then
220207
table.insert(virt_text, margin_text)
221208
end
222-
local skip_padding = row == self.data.start_row and icon_added
223-
if not skip_padding and padding > 0 then
209+
if padding > 0 and row > start_row and row < end_row then
224210
table.insert(virt_text, padding_text)
225211
end
226212
if #virt_text > 0 then

lua/render-markdown/render/dash.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ end
1616

1717
function Render:render()
1818
local width = self.dash.width
19-
width = type(width) == 'number' and width or self.context:get_width()
19+
width = type(width) == 'number' and width or vim.o.columns
2020
local virt_text = { self.dash.icon:rep(width), self.dash.highlight }
2121

2222
local start_row, end_row = self.node.start_row, self.node.end_row - 1

lua/render-markdown/render/heading.lua

+10-12
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ function Render:width(icon_width)
147147
return {
148148
margin = self.context:resolve_offset(self.data.left_margin, width),
149149
padding = left_padding,
150-
content = self.data.width == 'block' and width or self.context:get_width(),
150+
content = width,
151151
}
152152
end
153153

@@ -161,7 +161,7 @@ function Render:background(width)
161161
local win_col, padding = 0, {}
162162
if self.data.width == 'block' then
163163
win_col = width.margin + width.content + self:indent(self.data.level)
164-
table.insert(padding, { Str.pad(vim.o.columns * 2), self.config.padding.highlight })
164+
table.insert(padding, self:padding_text(vim.o.columns * 2))
165165
end
166166
for row = self.node.start_row, self.data.end_row - 1 do
167167
self.marks:add('head_background', row, 0, {
@@ -203,14 +203,15 @@ function Render:border(width)
203203
if highlight ~= nil then
204204
return { icon:rep(size), highlight }
205205
else
206-
return { Str.pad(size), self.config.padding.highlight }
206+
return self:padding_text(size)
207207
end
208208
end
209+
local content_width = self.data.width == 'block' and width.content or vim.o.columns
209210
return {
210211
section(width.margin, nil),
211212
section(width.padding, background),
212213
section(prefix, foreground),
213-
section(width.content - width.padding - prefix, background),
214+
section(content_width - width.padding - prefix, background),
214215
}
215216
end
216217

@@ -253,15 +254,12 @@ end
253254
---@param width render.md.width.Heading
254255
function Render:left_pad(width)
255256
local virt_text = {}
256-
---@param size integer
257-
---@param highlight? string
258-
local function append(size, highlight)
259-
if size > 0 then
260-
table.insert(virt_text, { Str.pad(size), highlight or self.config.padding.highlight })
261-
end
257+
if width.margin > 0 then
258+
table.insert(virt_text, self:padding_text(width.margin))
259+
end
260+
if width.padding > 0 then
261+
table.insert(virt_text, self:padding_text(width.padding, self.data.background))
262262
end
263-
append(width.margin, nil)
264-
append(width.padding, self.data.background)
265263
if #virt_text > 0 then
266264
for row = self.node.start_row, self.data.end_row - 1 do
267265
self.marks:add(false, row, 0, {

0 commit comments

Comments
 (0)