Files
nvim/lua/core/misc.lua
2025-05-18 13:03:31 -05:00

191 lines
5.1 KiB
Lua

local M = {}
--- vim.notify title
M.appid = "Nvim Config"
--- safe version of require
---@param fn string name of file to include
---@return any
function M.include(fn)
local ok, r = pcall(require, fn)
if not ok then
vim.notify("Could not find '"..fn.."': "..r, vim.log.levels.WARN, { title = M.appid })
return ok
end
return r
end
--- loop through files in directory
---@param path string absolute path of directory to be looped through
---@param body function function to use on every recursion of the loop
---@param ext string? desired file extension of files to be returned from directory
function M.loopf(path, body, ext)
ext = ext and [[v:val =~ '\.]]..ext..[[$']] or nil
for _, file in ipairs(vim.fn.readdir(path, ext)) do
body(file)
end
end
--- extend vim.kemap.set
---@param mode string|table mode for the keymap
---@param bind string|table keymap
---@param cmd function|string command to run
---@param opts vim.keymap.set.Opts? keymap options
function M.map(mode, bind, cmd, opts)
opts = opts or {}
opts["noremap"] = true
opts["silent"] = true
-- attempt to autogenerate a basic description
if not opts["desc"] then
if type(cmd) == "string" then
opts["desc"] = cmd:gsub("<%a+>", "")
elseif type(cmd) == "function" then
-- TODO: find a way to generate a better name
local file_name = vim.fn.fnamemodify(debug.getinfo(cmd, "S").short_src, ":t")
opts["desc"] = "origin@"..file_name
end
end
-- define the keybinds
if type(bind) == "table" then
for i in pairs(bind) do
vim.keymap.set(mode, bind[i], cmd, opts)
end
elseif type(bind) == "string" then
vim.keymap.set(mode, bind, cmd, opts)
end
end
--- a small map wrapper to easily create local buffer mappings
---@param mode string|table mode for the keymap
---@param bind string|table keymap
---@param cmd function|string command to run
---@param opts table? keymap options
function M.map_local(mode, bind, cmd, opts)
opts = opts or {}
opts["buffer"] = 0
M.map(mode, bind, cmd, opts)
end
--- extend vim.api.nvim_create_autocmd
---@param event string|table event or events
---@param opts vim.api.keyset.create_autocmd options
function M.auto(event, opts)
vim.api.nvim_create_autocmd(event, opts)
end
--- extend auto group
---@param name string name of the autogroup
---@param opts table? table of options
function M.augroup(name, opts)
opts = opts or {}
vim.api.nvim_create_augroup(name, opts)
end
--- extend vim.api.nvim_set_hl
---@param group string|table highlight group
---@param opts table highlight options
---@param namespace? number highlight space
function M.highlight(group, opts, namespace)
namespace = namespace or 0
if type(group) == "table" then
for i in pairs(group) do
vim.api.nvim_set_hl(namespace, group[i], opts)
end
elseif type(group) == "string" then
vim.api.nvim_set_hl(namespace, group, opts)
end
end
--- copy highlight group
---@param hlgroup string highlight group to copy
---@param namespace? number highlight space
---@return table
function M.cpyhl(hlgroup, namespace)
namespace = namespace or 0
local ok, hl = pcall(vim.api.nvim_get_hl, namespace, {
name = hlgroup,
create = false
})
if not ok then
return {}
end
for _, key in pairs({ "foreground", "background", "special" }) do
if hl[key] then
hl[key] = string.format("#%06x", hl[key])
end
end
return hl
end
--- highlight something with some highlight group for a certain amount of time
--- example:
--- ```lua
--- {
--- -- highlight group to use
--- hl = "IncSearch",
---
--- -- # of ms to stay highlighted for
--- timeout = 250,
---
--- -- line to highlight
--- line = vim.api.nvim_win_get_cursor(0)[1],
---
--- -- range to highlight if this is used line will be ignored
--- range = {
--- { 0, 0 },
--- { 0, 0 }
--- }
--- }
--- ```
--- opts is optional and if empty will simply highlight the current line for
--- 250ms using IncSearch as the highlight group
---@param opts table? options
function M.timeout_highlight(opts)
opts = opts or {}
opts.hl = opts.hl or "IncSearch"
opts.timeout = opts.timeout or 250
if type(opts.range) ~= "table" or type(opts.range[1]) ~= "table" or
type(opts.range[2]) ~= "table" then
local curline = opts.line or vim.api.nvim_win_get_cursor(0)[1]
opts.range = {
{ curline - 1, 0 },
{ curline, 0 }
}
end
local namespaceid = vim.api.nvim_create_namespace("timeout_highlight")
-- timer code was happily stolen from neovim/runtime/lua/vim/highlight.lua :)
local timer, timer_cancel
if not vim.fn.has("nvim-0.11") then
if timer then
timer:close()
assert(timer_cancel)
timer_cancel()
end
end
-- set the highlight
vim.highlight.range(0, namespaceid, opts.hl, opts.range[1], opts.range[2], {
opts.timeout,
})
if not vim.fn.has("nvim-0.11") then
timer_cancel = function()
timer = nil
timer_cancel = nil
pcall(vim.api.nvim_buf_clear_namespace, 0, namespaceid, 0, -1)
pcall(vim.api.nvim_win_remove_ns, 0, namespaceid)
end
timer = vim.defer_fn(timer_cancel, opts.timeout)
end
end
return M