All checks were successful
NeoVim tests / plenary-tests (push) Successful in 10s
138 lines
3.7 KiB
Lua
138 lines
3.7 KiB
Lua
local Buffer = require 'u.buffer'
|
|
local TreeBuilder = require('u.renderer').TreeBuilder
|
|
local tracker = require 'u.tracker'
|
|
local utils = require 'u.utils'
|
|
local Window = require 'my.window'
|
|
|
|
local TIMEOUT = 4000
|
|
local ICONS = {
|
|
[vim.log.levels.TRACE] = { text = '', group = 'DiagnosticSignOk' },
|
|
[vim.log.levels.DEBUG] = { text = '', group = 'DiagnosticSignOk' },
|
|
[vim.log.levels.INFO] = { text = '', group = 'DiagnosticSignInfo' },
|
|
[vim.log.levels.WARN] = { text = '', group = 'DiagnosticSignWarn' },
|
|
[vim.log.levels.ERROR] = { text = '', group = 'DiagnosticSignError' },
|
|
}
|
|
local DEFAULT_ICON = { text = '', group = 'DiagnosticSignOk' }
|
|
|
|
--- @alias Notification {
|
|
--- kind: number;
|
|
--- id: number;
|
|
--- text: string;
|
|
--- }
|
|
|
|
local M = {}
|
|
|
|
--- @type Window | nil
|
|
local notifs_w
|
|
|
|
local s_notifications_raw = tracker.create_signal {}
|
|
local s_notifications = s_notifications_raw:debounce(50)
|
|
|
|
-- Render effect:
|
|
tracker.create_effect(function()
|
|
--- @type Notification[]
|
|
local notifs = s_notifications:get()
|
|
|
|
if #notifs == 0 then
|
|
if notifs_w then
|
|
notifs_w:close(true)
|
|
notifs_w = nil
|
|
end
|
|
return
|
|
end
|
|
|
|
vim.schedule(function()
|
|
local editor_size = utils.get_editor_dimensions()
|
|
local avail_width = editor_size.width
|
|
local float_width = 40
|
|
local win_config = {
|
|
relative = 'editor',
|
|
anchor = 'NE',
|
|
row = 0,
|
|
col = avail_width,
|
|
width = float_width,
|
|
height = math.min(#notifs, editor_size.height - 3),
|
|
border = 'single',
|
|
focusable = false,
|
|
}
|
|
if not notifs_w or not vim.api.nvim_win_is_valid(notifs_w.win) then
|
|
notifs_w = Window.new(Buffer.create(false, true), win_config)
|
|
vim.wo[notifs_w.win].cursorline = false
|
|
vim.wo[notifs_w.win].list = false
|
|
vim.wo[notifs_w.win].listchars = ''
|
|
vim.wo[notifs_w.win].number = false
|
|
vim.wo[notifs_w.win].relativenumber = false
|
|
vim.wo[notifs_w.win].wrap = false
|
|
else
|
|
notifs_w:set_config(win_config)
|
|
end
|
|
|
|
notifs_w:render(TreeBuilder.new()
|
|
:nest(function(tb)
|
|
for idx, notif in ipairs(notifs) do
|
|
if idx > 1 then tb:put '\n' end
|
|
|
|
local notif_icon = ICONS[notif.kind] or DEFAULT_ICON
|
|
tb:put_h('text', { hl = notif_icon.group }, notif_icon.text)
|
|
tb:put { ' ', notif.text }
|
|
end
|
|
end)
|
|
:tree())
|
|
vim.api.nvim_win_call(notifs_w.win, function()
|
|
-- scroll to bottom:
|
|
vim.cmd.normal 'G'
|
|
-- scroll all the way to the left:
|
|
vim.cmd.normal '9999zh'
|
|
end)
|
|
end)
|
|
end)
|
|
|
|
local _orig_notify
|
|
|
|
--- @param msg string
|
|
--- @param level integer|nil
|
|
--- @param opts table|nil
|
|
local function my_notify(msg, level, opts)
|
|
vim.schedule(function() _orig_notify(msg, level, opts) end)
|
|
if level == nil then level = vim.log.levels.INFO end
|
|
if level < vim.log.levels.INFO then return end
|
|
|
|
local id = math.random(math.huge)
|
|
|
|
--- @param notifs Notification[]
|
|
s_notifications_raw:schedule_update(function(notifs)
|
|
table.insert(notifs, { kind = level, id = id, text = msg })
|
|
return notifs
|
|
end)
|
|
|
|
vim.defer_fn(function()
|
|
--- @param notifs Notification[]
|
|
s_notifications_raw:schedule_update(function(notifs)
|
|
for i, notif in ipairs(notifs) do
|
|
if notif.id == id then
|
|
table.remove(notifs, i)
|
|
break
|
|
end
|
|
end
|
|
return notifs
|
|
end)
|
|
end, TIMEOUT)
|
|
end
|
|
|
|
local _once_msgs = {}
|
|
local function my_notify_once(msg, level, opts)
|
|
if vim.tbl_contains(_once_msgs, msg) then return false end
|
|
table.insert(_once_msgs, msg)
|
|
vim.notify(msg, level, opts)
|
|
return true
|
|
end
|
|
|
|
function M.setup()
|
|
if _orig_notify == nil then _orig_notify = vim.notify end
|
|
|
|
vim.notify = my_notify
|
|
vim.notify_once = my_notify_once
|
|
end
|
|
|
|
return M
|