Skip to content

Commit fbef5d3

Browse files
RenatoValentimrvjs
andauthored
feat: add wrapped-default as render (#286)
* feat: add wrapped-default as render * test(notify): add validation tests for max_width and prefix_length - Added unit tests to validate `max_width` and ensure it does not exceed the terminal width. - Ensured `prefix_length` is within the valid range to prevent 'col out of range' errors. - Improved test coverage for rendering and notification layout in `nvim-notify`. These changes address issues related to invalid column rendering and out-of-bounds errors. --------- Co-authored-by: rvjs <[email protected]>
1 parent d333b6f commit fbef5d3

File tree

4 files changed

+115
-1
lines changed

4 files changed

+115
-1
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,10 @@ Mostly same as `compact`, but lines are wrapped based on `max_width`, some paddi
232232

233233
![image](https://github.com/rcarriga/nvim-notify/assets/73286100/72237d45-6e3b-4c2a-8010-513a26871682)
234234

235+
5. "wrapped-default"
236+
237+
Similar to `default`, but lines are wrapped based on `max_width`, some padding is added.
238+
235239
Feel free to submit custom rendering functions to share with others!
236240

237241
### Animation Style

lua/notify/render/init.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
--- - `"simple"`
1313
--- - `"compact"`
1414
--- - `"wrapped-compact"`
15+
--- - `"wrapped-default"`
1516
---
1617
--- Custom functions should accept a buffer, a notification record and a highlights table
1718
---

lua/notify/render/wrapped-default.lua

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
local vim_api = vim.api
2+
local base = require("notify.render.base")
3+
4+
---@param line string
5+
---@param width number
6+
---@return table
7+
local function split_length(line, width)
8+
local text = {}
9+
local next_line
10+
while true do
11+
if #line == 0 then
12+
return text
13+
end
14+
next_line, line = line:sub(1, width), line:sub(width + 1)
15+
text[#text + 1] = next_line
16+
end
17+
end
18+
19+
---@param lines string[]
20+
---@param max_width number
21+
---@return table
22+
local function custom_wrap(lines, max_width)
23+
local wrapped_lines = {}
24+
for _, line in pairs(lines) do
25+
local new_lines = split_length(line, max_width)
26+
for _, nl in ipairs(new_lines) do
27+
nl = nl:gsub("^%s*", " "):gsub("%s*$", " ")
28+
table.insert(wrapped_lines, nl)
29+
end
30+
end
31+
return wrapped_lines
32+
end
33+
34+
---@param bufnr number
35+
---@param notif notify.Record
36+
---@param highlights notify.Highlights
37+
---@param config notify.Config
38+
return function(bufnr, notif, highlights, config)
39+
local namespace = base.namespace()
40+
local icon = notif.icon .. " "
41+
local title = notif.title[1] or "Notify"
42+
43+
local terminal_width = vim.o.columns
44+
local default_max_width = math.floor((terminal_width * 30) / 100)
45+
local max_width = config.max_width and config.max_width() or default_max_width
46+
47+
-- Ensure max_width is within bounds
48+
max_width = math.max(10, math.min(max_width, terminal_width - 1))
49+
50+
local message = custom_wrap(notif.message, max_width)
51+
52+
local prefix = string.format(" %s %s", icon, title)
53+
table.insert(message, 1, prefix)
54+
table.insert(message, 2, string.rep("", max_width))
55+
56+
vim_api.nvim_buf_set_lines(bufnr, 0, -1, false, message)
57+
58+
local prefix_length = vim.str_utfindex(prefix)
59+
prefix_length = math.min(prefix_length, max_width - 1)
60+
61+
vim_api.nvim_buf_set_extmark(bufnr, namespace, 0, 0, {
62+
virt_text = {
63+
{ " " },
64+
{ icon, highlights.icon },
65+
{ title, highlights.title },
66+
{ " " },
67+
},
68+
virt_text_win_col = 0,
69+
priority = 10,
70+
})
71+
72+
vim_api.nvim_buf_set_extmark(bufnr, namespace, 1, 0, {
73+
virt_text = {
74+
{ string.rep("", max_width), highlights.border },
75+
},
76+
virt_text_win_col = 0,
77+
priority = 10,
78+
})
79+
80+
vim_api.nvim_buf_set_extmark(bufnr, namespace, 2, prefix_length + 1, {
81+
hl_group = highlights.body,
82+
end_line = #message,
83+
end_col = 0,
84+
priority = 50,
85+
})
86+
end

tests/unit/init_spec.lua

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,29 @@ describe("checking public interface", function()
4545
assert.is.True(called)
4646
end)
4747

48+
a.it("validates max width and prefix length", function()
49+
local terminal_width = vim.o.columns
50+
notify.setup({
51+
background_colour = "#000000",
52+
max_width = function()
53+
return math.min(terminal_width, 50)
54+
end,
55+
})
56+
57+
local win = notify.async("test", "info").events.open()
58+
59+
assert.is.True(vim.api.nvim_win_get_width(win) <= terminal_width)
60+
61+
local notif = notify.notify("Test Notification", "info", {
62+
title = "Long Title That Should Be Cut Off",
63+
})
64+
65+
local prefix_title = notif.title and notif.title[1] or "Default Title"
66+
67+
local prefix_length = vim.str_utfindex(prefix_title)
68+
assert.is.True(prefix_length <= terminal_width)
69+
end)
70+
4871
a.it("uses custom render in call", function()
4972
local called = false
5073
notify
@@ -87,7 +110,7 @@ describe("checking public interface", function()
87110
end)
88111
end)
89112

90-
a.it("uses the confgured minimum width", function()
113+
a.it("uses the configured minimum width", function()
91114
notify.setup({
92115
background_colour = "#000000",
93116
minimum_width = 20,

0 commit comments

Comments
 (0)