diff --git a/lua/user/types/user/util.lua b/lua/user/types/user/util.lua index 21d6d59b..b50b7401 100644 --- a/lua/user/types/user/util.lua +++ b/lua/user/types/user/util.lua @@ -1,7 +1,33 @@ ---@diagnostic disable:unused-local ---@diagnostic disable:unused-function +---@alias VimNotifyLvl +---|0 +---|1 +---|2 +---|3 +---|4 +---|5 + +---@alias NotifyLvl NotifyLevel + +---@class NotifyOpts +---@field title? string Defaults to `'Message'` +---@field icon? string +---@field timeout? number|boolean Defaults to `1500` +---@field on_open? fun(...) +---@field on_close? fun(...) +---@field keep? fun(...) +---@field render? string|fun(...) +---@field replace? integer|notify.Record +---@field hide_from_history? boolean Defaults to `false` +---@field animate? boolean Defaults to `true` + +---@class UserUtils.Notify +---@field notify fun(msg: string, lvl: NotifyLvl|VimNotifyLvl?, opts: NotifyOpts?) + ---@class UserUtils ---@field strip_fields fun(T: table, fields: string|string[]): table ---@field ft_set fun(s: string, bufnr: integer?): fun() ---@field ft_get fun(bufnr: integer?): string +---@field notify UserUtils.Notify diff --git a/lua/user/util/init.lua b/lua/user/util/init.lua index 446ef984..911f2e33 100644 --- a/lua/user/util/init.lua +++ b/lua/user/util/init.lua @@ -66,4 +66,6 @@ function M.ft_get(bufnr) return vim.api.nvim_get_option_value('ft', { buf = bufnr }) end +M.notify = require('user.util.notify') + return M diff --git a/lua/user/util/notify.lua b/lua/user/util/notify.lua new file mode 100644 index 00000000..67144bab --- /dev/null +++ b/lua/user/util/notify.lua @@ -0,0 +1,85 @@ +---@diagnostic disable:unused-function +---@diagnostic disable:unused-local +---@diagnostic disable:missing-fields + +require('user.types.user.util') + +--- Can't use `check.exists.module()` here as its module might require this module, +--- so let's avoid an import loop, shall we? +---@type fun(mod: string): boolean +local function exists(mod) + local ok, _ = pcall(require, mod) + + return ok +end + +---@type UserUtils.Notify +local M = {} + +function M.notify(msg, lvl, opts) + if type(msg) ~= 'string' then + error('(user.util.notify.notify): Empty message', vim.log.levels.WARN) + end + + local vim_lvl = vim.log.levels + + local DEFAULT_LVLS = { + [vim_lvl.TRACE + 1] = 'trace', + [vim_lvl.DEBUG + 1] = 'debug', + [vim_lvl.INFO + 1] = 'info', + [vim_lvl.WARN + 1] = 'warn', + [vim_lvl.ERROR + 1] = 'error', + [vim_lvl.OFF + 1] = 'off', + } + + ---@type notify.Options + local DEFAULT_OPTS = { + animate = true, + hide_from_history = false, + title = 'Message', + timeout = 1500, + } + + if exists('notify') then + local notify = require('notify') + + if type(lvl) == 'number' and (lvl >= vim_lvl.TRACE and lvl <= vim_lvl.OFF) then + lvl = DEFAULT_LVLS[math.floor(lvl) + 1] + else + lvl = DEFAULT_LVLS[vim_lvl.INFO + 1] + end + + if opts ~= nil and type(opts) == 'table' and not vim.tbl_isempty(opts) then + for key, v in next, DEFAULT_OPTS do + opts[key] = (opts[key] ~= nil and type(v) == type(opts[key])) and opts[key] or v + end + else + for key, v in next, DEFAULT_OPTS do + opts[key] = v + end + end + + notify(msg, lvl, opts) + else + if type(lvl) == 'string' then + for k, v in next, DEFAULT_LVLS do + if lvl == v then + lvl = k - 1 + break + end + end + + if type(lvl) == 'string' then + lvl = vim_lvl.INFO + end + end + + if opts ~= nil and type(opts) == 'table' and not vim.tbl_isempty(opts) then + vim.notify(msg, lvl, opts) + else + vim.notify(msg, lvl) + end + end +end + +return M