aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--nvim/.config/nvim/lua/tobyvin/autocmds.lua7
-rw-r--r--nvim/.config/nvim/lua/tobyvin/keymaps.lua13
-rw-r--r--nvim/.config/nvim/lua/tobyvin/lsp/diagnostics.lua12
-rw-r--r--nvim/.config/nvim/lua/tobyvin/lsp/init.lua2
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins.lua4
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins/bufferline.lua4
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins/crates.lua18
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins/dap.lua41
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins/diffview.lua4
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins/fidget.lua4
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins/gitsigns.lua6
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins/lualine.lua22
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins/neogen.lua2
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins/neogit.lua2
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins/notify.lua2
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins/refactoring.lua4
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins/rust-tools.lua4
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins/session_manager.lua2
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins/telescope.lua10
-rw-r--r--nvim/.config/nvim/lua/tobyvin/plugins/trouble.lua7
-rw-r--r--nvim/.config/nvim/lua/tobyvin/utils.lua412
-rw-r--r--nvim/.config/nvim/lua/tobyvin/utils/buffer.lua109
-rw-r--r--nvim/.config/nvim/lua/tobyvin/utils/debug.lua36
-rw-r--r--nvim/.config/nvim/lua/tobyvin/utils/diagnostic.lua48
-rw-r--r--nvim/.config/nvim/lua/tobyvin/utils/documentation.lua27
-rw-r--r--nvim/.config/nvim/lua/tobyvin/utils/fs.lua34
-rw-r--r--nvim/.config/nvim/lua/tobyvin/utils/init.lua12
-rw-r--r--nvim/.config/nvim/lua/tobyvin/utils/job.lua97
-rw-r--r--nvim/.config/nvim/lua/tobyvin/utils/keymap.lua34
-rw-r--r--nvim/.config/nvim/lua/tobyvin/utils/status.lua30
30 files changed, 515 insertions, 494 deletions
diff --git a/nvim/.config/nvim/lua/tobyvin/autocmds.lua b/nvim/.config/nvim/lua/tobyvin/autocmds.lua
index be0589f..4b9e3cb 100644
--- a/nvim/.config/nvim/lua/tobyvin/autocmds.lua
+++ b/nvim/.config/nvim/lua/tobyvin/autocmds.lua
@@ -79,13 +79,6 @@ M.setup = function()
vim.api.nvim_create_autocmd("FileType", {
group = augroup_fmt,
- pattern = "help",
- callback = function() end,
- desc = "Format help window",
- })
-
- vim.api.nvim_create_autocmd("FileType", {
- group = augroup_fmt,
pattern = { "sh", "zsh", "xml", "html", "xhtml", "css", "scss", "javascript", "lua", "dart", "markdown" },
callback = function()
vim.opt_local.tabstop = 2
diff --git a/nvim/.config/nvim/lua/tobyvin/keymaps.lua b/nvim/.config/nvim/lua/tobyvin/keymaps.lua
index c62d36a..1fb779c 100644
--- a/nvim/.config/nvim/lua/tobyvin/keymaps.lua
+++ b/nvim/.config/nvim/lua/tobyvin/keymaps.lua
@@ -10,11 +10,10 @@ M.training_wheels = function()
end
M.setup = function()
- vim.keymap.set("n", "<leader>q", utils.quit, { desc = "Quit" })
- vim.keymap.set("n", "<leader>c", utils.bdelete, { desc = "Close" })
- vim.keymap.set("n", "<leader>x", utils.tabclose, { desc = "Close" })
- vim.keymap.set("n", "<leader>h", utils.hover, { desc = "Hover" })
- vim.keymap.set("n", "<leader>H", utils.docs, { desc = "Docs" })
+ vim.keymap.set("n", "<leader>q", utils.buffer.quit, { desc = "Quit" })
+ vim.keymap.set("n", "<leader>c", utils.buffer.bdelete, { desc = "Close" })
+ vim.keymap.set("n", "<leader>x", utils.buffer.tabclose, { desc = "Close" })
+ vim.keymap.set("n", "<leader>h", utils.documentation.open, { desc = "Docs" })
vim.keymap.set("n", "<leader>w", M.write, { desc = "Write" })
vim.keymap.set("i", "<C-c>", M.training_wheels, { desc = "Helper to quit using <C-c>" })
vim.keymap.set("n", "<C-u>", "<C-u>zz", { desc = "Up half page and center" })
@@ -25,9 +24,9 @@ M.setup = function()
vim.keymap.set("v", "<a-k>", "<CMD>m '<-2<CR>gv=gv", { desc = "Move selection up" })
vim.keymap.set("v", "<a-j>", "<CMD>m '>+1<CR>gv=gv", { desc = "Move selection down" })
- local nmap_run = utils.create_map_group("n", "<leader>r", { desc = "Run" })
+ local nmap_run = utils.keymap.group("n", "<leader>r", { desc = "Run" })
- nmap_run("c", utils.run_cmd_with_args, { desc = "Command" })
+ nmap_run("c", utils.job.cmd, { desc = "Command" })
end
return M
diff --git a/nvim/.config/nvim/lua/tobyvin/lsp/diagnostics.lua b/nvim/.config/nvim/lua/tobyvin/lsp/diagnostics.lua
index 6925ca6..525f1af 100644
--- a/nvim/.config/nvim/lua/tobyvin/lsp/diagnostics.lua
+++ b/nvim/.config/nvim/lua/tobyvin/lsp/diagnostics.lua
@@ -17,8 +17,8 @@ M.on_attach = function(_, bufnr)
end,
})
- vim.keymap.set("n", "<leader>e", vim.diagnostic.open_float, { desc = "Show Diagnostic", buffer = bufnr })
- vim.keymap.set("n", "<leader>E", vim.diagnostic.setloclist, { desc = "List Diagnostic", buffer = bufnr })
+ vim.keymap.set("n", "<leader>e", vim.diagnostic.setloclist, { desc = "Show Buffer Diagnostic", buffer = bufnr })
+ vim.keymap.set("n", "<leader>E", vim.diagnostic.setqflist, { desc = "Show Workspace Diagnostic", buffer = bufnr })
vim.keymap.set("n", "]d", vim.diagnostic.goto_next, { desc = "Next Diagnostic", buffer = bufnr })
vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, { desc = "Prev Diagnostic", buffer = bufnr })
end
@@ -34,10 +34,10 @@ M.setup = function()
severity_sort = true,
})
- vim.fn.sign_define("DiagnosticSignError", utils.diagnostic_signs.error)
- vim.fn.sign_define("DiagnosticSignWarn", utils.diagnostic_signs.warn)
- vim.fn.sign_define("DiagnosticSignInfo", utils.diagnostic_signs.info)
- vim.fn.sign_define("DiagnosticSignHint", utils.diagnostic_signs.hint)
+ vim.fn.sign_define("DiagnosticSignError", utils.diagnostic.signs.error)
+ vim.fn.sign_define("DiagnosticSignWarn", utils.diagnostic.signs.warn)
+ vim.fn.sign_define("DiagnosticSignInfo", utils.diagnostic.signs.info)
+ vim.fn.sign_define("DiagnosticSignHint", utils.diagnostic.signs.hint)
end
return M
diff --git a/nvim/.config/nvim/lua/tobyvin/lsp/init.lua b/nvim/.config/nvim/lua/tobyvin/lsp/init.lua
index 506f59e..f2bd386 100644
--- a/nvim/.config/nvim/lua/tobyvin/lsp/init.lua
+++ b/nvim/.config/nvim/lua/tobyvin/lsp/init.lua
@@ -14,7 +14,7 @@ M.on_attach = function(client, bufnr)
vim.keymap.set("n", "K", vim.lsp.buf.hover, { desc = "Hover", buffer = bufnr })
vim.keymap.set("n", "<C-k>", vim.lsp.buf.signature_help, { desc = "Signature Help", buffer = bufnr })
- utils.create_map_group("n", "<leader>l", { desc = "LSP", buffer = bufnr })
+ utils.keymap.group("n", "<leader>l", { desc = "LSP", buffer = bufnr })
vim.keymap.set("n", "<leader>li", "<CMD>LspInfo<CR>", { desc = "LSP info" })
vim.keymap.set("n", "<leader>lr", vim.lsp.buf.rename, { desc = "Rename", buffer = bufnr })
vim.keymap.set("n", "<leader>la", vim.lsp.buf.code_action, { desc = "Code Action", buffer = bufnr })
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins.lua b/nvim/.config/nvim/lua/tobyvin/plugins.lua
index 1a3d063..3244e3f 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins.lua
@@ -491,7 +491,7 @@ M.plugins = function(use)
end
M.open_log = function()
- utils.popup(vim.fn.stdpath("cache") .. "/packer.nvim.log")
+ utils.buffer.popup(vim.fn.stdpath("cache") .. "/packer.nvim.log")
end
M.setup = function()
@@ -526,7 +526,7 @@ M.setup = function()
profile = { enable = true },
})
- local nmap = utils.create_map_group("n", "<leader>p", { desc = "Packer" })
+ local nmap = utils.keymap.group("n", "<leader>p", { desc = "Packer" })
nmap("c", packer.compile, { desc = "Compile" })
nmap("C", packer.clean, { desc = "Clean" })
nmap("i", packer.install, { desc = "Install" })
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/bufferline.lua b/nvim/.config/nvim/lua/tobyvin/plugins/bufferline.lua
index 7605e7a..772d99e 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins/bufferline.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins/bufferline.lua
@@ -5,7 +5,7 @@ local M = {}
M.diagnostics_indicator = function(_, _, errors, _)
local outstr = " "
for level, count in pairs(errors) do
- local sign = utils.diagnostic_signs[level:gsub("warning", "warn")].text
+ local sign = utils.diagnostic.signs[level:gsub("warning", "warn")].text
-- outstr = outstr .. sign .. (#count > 1 and count or "")
outstr = outstr .. sign .. count
end
@@ -41,7 +41,7 @@ M.setup = function()
},
})
- local nmap = utils.create_map_group("n", "<leader>b", { desc = "Buffers" })
+ local nmap = utils.keymap.group("n", "<leader>b", { desc = "Buffers" })
nmap("c", bufferline.close_with_pick, { desc = "Close Buffer" })
nmap("b", bufferline.pick_buffer, { desc = "Pick Buffer" })
end
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/crates.lua b/nvim/.config/nvim/lua/tobyvin/plugins/crates.lua
index 46f2077..1cfba20 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins/crates.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins/crates.lua
@@ -1,3 +1,4 @@
+local utils = require("tobyvin.utils")
local M = {}
M.setup = function()
@@ -12,6 +13,23 @@ M.setup = function()
enabled = true,
},
})
+
+ vim.api.nvim_create_autocmd("LspAttach", {
+ pattern = "*/Cargo.toml",
+ callback = function()
+ utils.documentation.register("toml", crates.open_documentation)
+
+ -- TODO: impl registration system like documentation (global and buffer?)
+ local original = vim.lsp.handlers["textDocument/hover"]
+ vim.lsp.handlers["textDocument/hover"] = function(...)
+ if crates.popup_available() then
+ crates.show_popup()
+ else
+ original(...)
+ end
+ end
+ end,
+ })
end
return M
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/dap.lua b/nvim/.config/nvim/lua/tobyvin/plugins/dap.lua
index b38f074..7c52f3d 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins/dap.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins/dap.lua
@@ -78,7 +78,7 @@ M.dapui_close = function()
dapui.close({})
- vim.keymap.set("n", "<leader>q", utils.quit, { desc = "Quit" })
+ vim.keymap.set("n", "<leader>q", utils.buffer.quit, { desc = "Quit" })
if M.dapui_tab and vim.api.nvim_tabpage_is_valid(M.dapui_tab) then
local tabnr = vim.api.nvim_tabpage_get_number(M.dapui_tab)
@@ -90,35 +90,36 @@ M.dapui_close = function()
end
M.progress_start = function(session, body)
- local notif_data = utils.get_notif_data("dap", body.progressId)
+ local notif_data = utils.debug.get_notif_data("dap", body.progressId)
- local message = utils.format_message(body.message, body.percentage)
+ local message = utils.debug.format_message(body.message, body.percentage)
notif_data.notification = vim.notify(message, "info", {
- title = utils.format_title(body.title, session.config.type),
- icon = utils.signs.spinner.text[1],
+ title = utils.debug.format_title(body.title, session.config.type),
+ icon = utils.status.signs.spinner.text[1],
timeout = false,
hide_from_history = false,
})
---@diagnostic disable-next-line: redundant-value
- notif_data.notification.spinner = 1, utils.update_spinner("dap", body.progressId)
+ notif_data.notification.spinner = 1, utils.status.update_spinner("dap", body.progressId)
end
M.progress_update = function(_, body)
- local notif_data = utils.get_notif_data("dap", body.progressId)
- notif_data.notification = vim.notify(utils.format_message(body.message, body.percentage), "info", {
+ local notif_data = utils.debug.get_notif_data("dap", body.progressId)
+ notif_data.notification = vim.notify(utils.debug.format_message(body.message, body.percentage), "info", {
replace = notif_data.notification,
hide_from_history = false,
})
end
M.progress_end = function(_, body)
- local notif_data = utils.client_notifs["dap"][body.progressId]
- notif_data.notification = vim.notify(body.message and utils.format_message(body.message) or "Complete", "info", {
- icon = utils.signs.complete.text,
- replace = notif_data.notification,
- timeout = 3000,
- })
+ local notif_data = utils.debug.notifs["dap"][body.progressId]
+ notif_data.notification =
+ vim.notify(body.message and utils.debug.format_message(body.message) or "Complete", "info", {
+ icon = utils.status.signs.complete.text,
+ replace = notif_data.notification,
+ timeout = 3000,
+ })
notif_data.spinner = nil
end
@@ -240,7 +241,7 @@ M.setup = function()
vim.keymap.set("n", "<F11>", dap.step_into, { desc = "Step Into" })
vim.keymap.set("n", "<F12>", dap.step_out, { desc = "Step Out" })
- local nmap = utils.create_map_group("n", "<leader>d", { desc = "Debug" })
+ local nmap = utils.keymap.group("n", "<leader>d", { desc = "Debug" })
nmap("d", require("telescope").extensions.dap.configurations, { desc = "Configurations" })
nmap("c", dap.continue, { desc = "Continue" })
nmap("a", dap.step_over, { desc = "Step Over" })
@@ -263,11 +264,11 @@ M.setup = function()
})
-- Signs
- vim.fn.sign_define("DapBreakpoint", utils.debug_signs.breakpoint)
- vim.fn.sign_define("DapBreakpointCondition", utils.debug_signs.condition)
- vim.fn.sign_define("DapBreakpointRejected", utils.debug_signs.rejected)
- vim.fn.sign_define("DapStopped", utils.debug_signs.stopped)
- vim.fn.sign_define("DapLogPoint", utils.debug_signs.logpoint)
+ vim.fn.sign_define("DapBreakpoint", utils.debug.signs.breakpoint)
+ vim.fn.sign_define("DapBreakpointCondition", utils.debug.signs.condition)
+ vim.fn.sign_define("DapBreakpointRejected", utils.debug.signs.rejected)
+ vim.fn.sign_define("DapStopped", utils.debug.signs.stopped)
+ vim.fn.sign_define("DapLogPoint", utils.debug.signs.logpoint)
end
return M
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/diffview.lua b/nvim/.config/nvim/lua/tobyvin/plugins/diffview.lua
index 461e73c..892f341 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins/diffview.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins/diffview.lua
@@ -24,12 +24,12 @@ M.setup = function()
diffview.setup()
- local nmap = utils.create_map_group("n", "<leader>g", { desc = "Git" })
+ local nmap = utils.keymap.group("n", "<leader>g", { desc = "Git" })
nmap("d", diffview.open, { desc = "Diffview" })
nmap("h", M.file_history, { desc = "File History" })
nmap("H", M.workspace_history, { desc = "Workspace History" })
- local vmap = utils.create_map_group("v", "<leader>g", { desc = "Git" })
+ local vmap = utils.keymap.group("v", "<leader>g", { desc = "Git" })
vmap("h", M.selection_history, { desc = "Selection History" })
end
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/fidget.lua b/nvim/.config/nvim/lua/tobyvin/plugins/fidget.lua
index 4d925bb..98ae6d5 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins/fidget.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins/fidget.lua
@@ -10,8 +10,8 @@ M.setup = function()
fidget.setup({
text = {
- spinner = utils.status_signs.spinner.text,
- done = vim.trim(utils.status_signs.completed.text),
+ spinner = utils.status.signs.spinner.text,
+ done = vim.trim(utils.status.signs.completed.text),
},
window = { blend = 0 },
})
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/gitsigns.lua b/nvim/.config/nvim/lua/tobyvin/plugins/gitsigns.lua
index e68f2dd..2179202 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins/gitsigns.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins/gitsigns.lua
@@ -3,7 +3,7 @@ local M = {}
M.with_selection = function(callback)
return function()
- callback(utils.get_visual_range())
+ callback(utils.buffer.get_visual_range())
end
end
@@ -13,7 +13,7 @@ end
M.on_attach = function(bufnr)
local gitsigns = require("gitsigns")
- local nmap = utils.create_map_group("n", "<leader>g", { desc = "Git", buffer = bufnr })
+ local nmap = utils.keymap.group("n", "<leader>g", { desc = "Git", buffer = bufnr })
nmap("b", gitsigns.blame_line, { desc = "Show blame" })
nmap("B", M.show_blameline, { desc = "Show blame" })
nmap("<C-b>", gitsigns.toggle_current_line_blame, { desc = "Toggle blame line" })
@@ -30,7 +30,7 @@ M.on_attach = function(bufnr)
nmap("S", gitsigns.stage_buffer, { desc = "Stage Buffer" })
nmap("U", gitsigns.reset_buffer_index, { desc = "Undo Stage Buffer" })
- local vmap = utils.create_map_group("v", "<leader>g", { desc = "Git", buffer = bufnr })
+ local vmap = utils.keymap.group("v", "<leader>g", { desc = "Git", buffer = bufnr })
vmap("p", M.with_selection(gitsigns.preview_hunk), { desc = "Preview Hunk" })
vmap("r", M.with_selection(gitsigns.reset_hunk), { desc = "Reset Hunk" })
vmap("s", M.with_selection(gitsigns.stage_hunk), { desc = "Stage Hunk" })
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/lualine.lua b/nvim/.config/nvim/lua/tobyvin/plugins/lualine.lua
index ac544b6..f554b3a 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins/lualine.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins/lualine.lua
@@ -163,12 +163,12 @@ M.setup = function()
},
{
"diagnostics",
- sources = { utils.diagnostic_count },
+ sources = { utils.diagnostic.count },
symbols = {
- error = utils.diagnostic_signs.error.text,
- warn = utils.diagnostic_signs.warn.text,
- info = utils.diagnostic_signs.info.text,
- hint = utils.diagnostic_signs.hint.text,
+ error = utils.diagnostic.signs.error.text,
+ warn = utils.diagnostic.signs.warn.text,
+ info = utils.diagnostic.signs.info.text,
+ hint = utils.diagnostic.signs.hint.text,
},
update_in_insert = false,
padding = { left = 0, right = 1 },
@@ -184,14 +184,14 @@ M.setup = function()
"diagnostics",
sources = {
function()
- return utils.diagnostic_count(0)
+ return utils.diagnostic.count(0)
end,
},
symbols = {
- error = utils.diagnostic_signs.error.text,
- warn = utils.diagnostic_signs.warn.text,
- info = utils.diagnostic_signs.info.text,
- hint = utils.diagnostic_signs.hint.text,
+ error = utils.diagnostic.signs.error.text,
+ warn = utils.diagnostic.signs.warn.text,
+ info = utils.diagnostic.signs.info.text,
+ hint = utils.diagnostic.signs.hint.text,
},
update_in_insert = false,
padding = { left = 0, right = 1 },
@@ -215,7 +215,7 @@ M.setup = function()
{
"buffers",
fmt = function(name, bufnr)
- return string.format("%s %s", name, utils.diagnostic_indicator(bufnr))
+ return string.format("%s %s", name, utils.diagnostic.indicator(bufnr))
end,
},
},
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/neogen.lua b/nvim/.config/nvim/lua/tobyvin/plugins/neogen.lua
index 9d358c0..5e2d225 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins/neogen.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins/neogen.lua
@@ -7,7 +7,7 @@ M.setup = function()
return
end
- local nmap = require("tobyvin.utils").create_map_group("n", "<leader>s", { desc = "Snippets" })
+ local nmap = require("tobyvin.utils").keymap.group("n", "<leader>s", { desc = "Snippets" })
neogen.setup({ snippet_engine = "luasnip" })
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/neogit.lua b/nvim/.config/nvim/lua/tobyvin/plugins/neogit.lua
index a91bf71..d27e683 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins/neogit.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins/neogit.lua
@@ -18,7 +18,7 @@ M.setup = function()
-- kind = "replace",
})
- local nmap = utils.create_map_group("n", "<leader>g", { desc = "Git" })
+ local nmap = utils.keymap.group("n", "<leader>g", { desc = "Git" })
nmap("g", neogit.open, { desc = "Neogit" })
end
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/notify.lua b/nvim/.config/nvim/lua/tobyvin/plugins/notify.lua
index 976e66a..c3b9847 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins/notify.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins/notify.lua
@@ -17,7 +17,7 @@ M.setup = function()
local telescope_ok, telescope = pcall(require, "telescope")
if telescope_ok then
telescope.load_extension("notify")
- local nmap = utils.create_map_group("n", "<leader>f", { desc = "Find" })
+ local nmap = utils.keymap.group("n", "<leader>f", { desc = "Find" })
nmap("n", telescope.extensions.notify.notify, { desc = "Notifications" })
end
end
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/refactoring.lua b/nvim/.config/nvim/lua/tobyvin/plugins/refactoring.lua
index c3e6952..e70fc0a 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins/refactoring.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins/refactoring.lua
@@ -11,7 +11,7 @@ M.setup = function()
--
-- refactoring.setup()
--
- -- local nmap = utils.create_map_group("n", "<leader>r", { desc = "Refactor" })
+ -- local nmap = utils.keymap.group("n", "<leader>r", { desc = "Refactor" })
-- nmap("b", function()
-- refactoring.refactor("Extract Block")
-- end, { desc = "Extract Block" })
@@ -23,7 +23,7 @@ M.setup = function()
-- end, { desc = "Inline Variable" })
--
-- -- TODO: Fix needing to exit visual mode
- -- local vmap = utils.create_map_group("v", "<leader>r", { desc = "Refactor" })
+ -- local vmap = utils.keymap.group("v", "<leader>r", { desc = "Refactor" })
-- vmap("e", function()
-- refactoring.refactor("Extract Function")
-- end, { desc = "Extract Function" })
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/rust-tools.lua b/nvim/.config/nvim/lua/tobyvin/plugins/rust-tools.lua
index 86013b4..fe1099a 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins/rust-tools.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins/rust-tools.lua
@@ -32,13 +32,15 @@ M.setup = function()
local debuggables = rust_tools.debuggables.debuggables
local open_cargo_toml = rust_tools.open_cargo_toml.open_cargo_toml
local run_cargo_cmd = function()
- utils.run_cmd_with_args("cargo")
+ utils.job.cmd("cargo")
end
vim.keymap.set("n", "<leader>rr", runnables, { desc = "Runnables", buffer = bufnr })
vim.keymap.set("n", "<leader>rd", debuggables, { desc = "Debug", buffer = bufnr })
vim.keymap.set("n", "<leader>ro", open_cargo_toml, { desc = "Open Cargo.toml", buffer = bufnr })
vim.keymap.set("n", "<leader>rc", run_cargo_cmd, { desc = "Command", buffer = bufnr })
+
+ utils.documentation.register("rust", require("rust-tools.external_docs").open_external_docs)
end,
}),
dap = {
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/session_manager.lua b/nvim/.config/nvim/lua/tobyvin/plugins/session_manager.lua
index 27aecef..228ac64 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins/session_manager.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins/session_manager.lua
@@ -12,7 +12,7 @@ M.setup = function()
autoload_mode = require("session_manager.config").AutoloadMode.Disabled,
})
- utils.create_map_group("n", "<leader>s", { desc = "Sessions" })
+ utils.keymap.group("n", "<leader>s", { desc = "Sessions" })
vim.keymap.set("n", "<leader>ss", session_manager.save_current_session, { desc = "Save session" })
vim.keymap.set("n", "<leader>sl", session_manager.load_current_dir_session, { desc = "Load current session" })
vim.keymap.set("n", "<leader>sL", session_manager.load_session, { desc = "Load session" })
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/telescope.lua b/nvim/.config/nvim/lua/tobyvin/plugins/telescope.lua
index 430f8f1..e39fba1 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins/telescope.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins/telescope.lua
@@ -65,7 +65,7 @@ M.setup = function()
local builtins = require("telescope.builtin")
- local nmap_find = require("tobyvin.utils").create_map_group("n", "<leader>f", { desc = "Find" })
+ local nmap_find = require("tobyvin.utils").keymap.group("n", "<leader>f", { desc = "Find" })
nmap_find("a", builtins.autocommands, { desc = "Autocommands" })
nmap_find("b", builtins.buffers, { desc = "Buffers" })
nmap_find("c", builtins.commands, { desc = "Commands" })
@@ -91,22 +91,22 @@ M.setup = function()
nmap_find("v", builtins.vim_options, { desc = "Vim Options" })
nmap_find("'", builtins.registers, { desc = "Registers" })
- local nmap_git = require("tobyvin.utils").create_map_group("n", "<leader>g", { desc = "Git" })
+ local nmap_git = require("tobyvin.utils").keymap.group("n", "<leader>g", { desc = "Git" })
nmap_git("b", builtins.git_branches, { desc = "Checkout branch" })
nmap_git("c", builtins.git_commits, { desc = "Checkout commit" })
nmap_git("o", builtins.git_status, { desc = "Open changed file" })
- local nmap_git_wt = require("tobyvin.utils").create_map_group("n", "<leader>gw", { desc = "Worktree" })
+ local nmap_git_wt = require("tobyvin.utils").keymap.group("n", "<leader>gw", { desc = "Worktree" })
nmap_git_wt("s", telescope.extensions.git_worktree.git_worktrees, { desc = "Switch worktree" })
nmap_git_wt("c", telescope.extensions.git_worktree.create_git_worktree, { desc = "Create worktree" })
- local nmap_git_gh = require("tobyvin.utils").create_map_group("n", "<leader>gG", { desc = "Github" })
+ local nmap_git_gh = require("tobyvin.utils").keymap.group("n", "<leader>gG", { desc = "Github" })
nmap_git_gh("i", telescope.extensions.gh.issues, { desc = "Issues" })
nmap_git_gh("p", telescope.extensions.gh.pull_request, { desc = "Pull request" })
nmap_git_gh("g", telescope.extensions.gh.gist, { desc = "Gist" })
nmap_git_gh("r", telescope.extensions.gh.run, { desc = "Run" })
- local nmap_packer = require("tobyvin.utils").create_map_group("n", "<leader>p", { desc = "Packer" })
+ local nmap_packer = require("tobyvin.utils").keymap.group("n", "<leader>p", { desc = "Packer" })
nmap_packer("f", telescope.extensions.packer.packer, { desc = "Find plugins" })
end
diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/trouble.lua b/nvim/.config/nvim/lua/tobyvin/plugins/trouble.lua
index 4dd007a..2d79312 100644
--- a/nvim/.config/nvim/lua/tobyvin/plugins/trouble.lua
+++ b/nvim/.config/nvim/lua/tobyvin/plugins/trouble.lua
@@ -9,13 +9,6 @@ M.setup = function()
end
trouble.setup({
- -- signs = {
- -- error = utils.diagnostic_signs.error.text,
- -- warning = utils.diagnostic_signs.warn.text,
- -- hint = utils.diagnostic_signs.hint.text,
- -- information = utils.diagnostic_signs.info.text,
- -- other = utils.diagnostic_signs.info.text,
- -- },
use_diagnostic_signs = true,
})
end
diff --git a/nvim/.config/nvim/lua/tobyvin/utils.lua b/nvim/.config/nvim/lua/tobyvin/utils.lua
deleted file mode 100644
index 6464b2d..0000000
--- a/nvim/.config/nvim/lua/tobyvin/utils.lua
+++ /dev/null
@@ -1,412 +0,0 @@
----@diagnostic disable: missing-parameter
-local M = {}
-
-M.status_signs = {
- started = { text = "ﳁ ", texthl = "diffChanged" },
- running = { text = "ﳁ ", texthl = "DiagnosticSignInfo" },
- failed = { text = " ", texthl = "DiagnosticSignError" },
- completed = { text = " ", texthl = "diffAdded" },
- spinner = { text = { "⣷", "⣯", "⣟", "⡿", "⢿", "⣻", "⣽", "⣾" }, texthl = "DiagnosticSignInfo" },
-}
-
-M.debug_signs = {
- breakpoint = { text = " ", texthl = "debugBreakpoint" },
- condition = { text = "ﳁ ", texthl = "debugBreakpoint" },
- rejected = { text = " ", texthl = "debugBreakpoint" },
- logpoint = { text = " ", texthl = "debugBreakpoint" },
- stopped = { text = " ", texthl = "debugBreakpoint", linehl = "debugPC", numhl = "debugPC" },
-}
-
-M.diagnostic_signs = {
- hint = { text = " ", texthl = "DiagnosticSignHint" },
- info = { text = " ", texthl = "DiagnosticSignInfo" },
- warn = { text = " ", texthl = "DiagnosticSignWarn" },
- error = { text = " ", texthl = "DiagnosticSignError" },
-}
-
-setmetatable(M.diagnostic_signs, {
- __index = function(t, k)
- if type(k) == "number" then
- return t[vim.diagnostic.severity[k]]
- end
- return t[k:lower():gsub("warning", "warn")]
- end,
-})
-
-M.diagnostic_count = function(bufnr)
- local items = {}
- for i, level in ipairs(vim.diagnostic.severity) do
- items[level] = #vim.diagnostic.get(bufnr, { severity = i })
- end
-
- setmetatable(items, {
- __index = function(t, k)
- if type(k) == "number" then
- return t[vim.diagnostic.severity[k]]
- end
- return t[k:upper():gsub("WARNING", "WARN")]
- end,
- })
-
- return items
-end
-
-M.diagnostic_indicator = function(bufnr)
- local diagnostic_count = M.diagnostic_count(bufnr)
- local tbl = {}
- for level, count in pairs(diagnostic_count) do
- if count > 0 then
- table.insert(tbl, M.diagnostic_signs[level].text .. count)
- end
- end
- return table.concat(tbl, " ")
-end
-
-M.update_spinner = function(client_id, token)
- local notif_data = M.get_notif_data(client_id, token)
-
- if notif_data.spinner then
- local new_spinner = (notif_data.spinner + 1) % #M.status_signs.spinner.text
- notif_data.spinner = new_spinner
-
- notif_data.notification = vim.notify(nil, nil, {
- hide_from_history = true,
- icon = M.status_signs.spinner.text[new_spinner],
- replace = notif_data.notification,
- })
-
- vim.defer_fn(function()
- M.update_spinner(client_id, token)
- end, 100)
- end
-end
-
-M.hover = function()
- if vim.fn.expand("%:t") == "Cargo.toml" then
- require("crates").show_popup()
- else
- vim.lsp.buf.hover()
- end
-end
-
-M.docs = function()
- local filetype = vim.bo.filetype
- if vim.tbl_contains({ "vim", "help" }, filetype) then
- vim.cmd("help " .. vim.fn.expand("<cword>"))
- elseif vim.tbl_contains({ "man" }, filetype) then
- vim.cmd("Man " .. vim.fn.expand("<cword>"))
- elseif vim.tbl_contains({ "rust" }, filetype) then
- require("rust-tools.external_docs").open_external_docs()
- else
- M.hover()
- end
-end
-
----@param retry fun(force:boolean?):nil
-M.modified_prompt_retry = function(retry)
- local bufname = vim.fn.bufname(vim.fn.bufname())
-
- vim.ui.select({ "write", "discard", "abort" }, {
- prompt = string.format("No write since last change for buffer %s:", bufname),
- kind = "select_normal",
- }, function(_, idx)
- if idx == 1 then
- vim.cmd("write")
- retry()
- elseif idx == 2 then
- retry(true)
- else
- vim.notify(
- string.format("No write since last change for buffer %d", bufname),
- vim.log.levels.ERROR,
- { title = "Aborting..." }
- )
- end
- end)
-end
-
----@param cmd string vim command
----@param force boolean
-M.win_buf_kill = function(cmd, force)
- local winid = vim.fn.win_getid()
- local bufnr = vim.fn.winbufnr(winid)
-
- if not force and vim.bo[bufnr].modified then
- return M.modified_prompt_retry(M[cmd])
- end
-
- vim.api.nvim_exec_autocmds("User", { pattern = cmd })
-
- if (string.sub(cmd, 1, 1) == "b" and vim.api.nvim_buf_is_valid(bufnr)) or vim.api.nvim_win_is_valid(winid) then
- vim.cmd(cmd .. (force and "!" or ""))
- end
-end
-
----@param force boolean
-M.bdelete = function(force)
- M.win_buf_kill("bdelete", force)
-end
-
----@param force boolean
-M.bwipeout = function(force)
- M.win_buf_kill("bwipeout", force)
-end
-
----@param force boolean
-M.close = function(force)
- M.win_buf_kill("close", force)
-end
-
----@param force boolean
-M.quit = function(force)
- M.win_buf_kill("quit", force)
-end
-
----@param force boolean
-M.tabclose = function(force)
- local cmd = "tabclose"
- if #vim.api.nvim_list_tabpages() == 1 then
- cmd = "qall"
- end
- vim.cmd(cmd .. (force and "!" or ""))
-end
-
-M.escape = function()
- local key = "<ESC>"
- vim.api.nvim_replace_termcodes(key, true, false, true)
- vim.api.nvim_feedkeys(key, "x", true)
- -- vim.api.nvim_input("<ESC>")
- -- vim.wait(100, function()
- -- return "n" == vim.fn.mode()
- -- end)
-end
-
-M.get_visual_range = function()
- local start_pos = vim.fn.getpos("v")
- local end_pos = vim.fn.getcurpos()
- return { start_pos[2], end_pos[2] }
- -- return { { line = start_pos[2], col = start_pos[3] }, { line = end_pos[2], col = end_pos[3] } }
-end
-
-M.client_notifs = {}
-
-M.get_notif_data = function(client_id, token)
- if not M.client_notifs[client_id] then
- M.client_notifs[client_id] = {}
- end
-
- if not M.client_notifs[client_id][token] then
- M.client_notifs[client_id][token] = {}
- end
-
- return M.client_notifs[client_id][token]
-end
-
-M.format_title = function(title, client)
- if type(client) == "table" then
- client = client.name
- end
- return client .. (#title > 0 and ": " .. title or "")
-end
-
-M.format_message = function(message, percentage)
- return (percentage and percentage .. "%\t" or "") .. (message or "")
-end
-
---- Helper function to create a group of keymaps that share a common prefix and/or options.
----@param mode string|table Same mode short names as vim.keymap.set(). A list will create the group on all modes.
----@param group_lhs string Prefix to prepend to the lhs of all keymaps in the group.
----@param group_opts ?table Options to apply to all keymaps in this group. (Same as options listed in vim.keymap.set)
----@return function Function to create mapping using the groups defaults.
--- TODO: Possibly add memoization to groups/subgroups using the __call metatable attribute
-M.create_map_group = function(mode, group_lhs, group_opts)
- group_opts = group_opts or {}
-
- local desc = group_opts.desc
- group_opts.desc = nil
-
- local status_ok, which_key = pcall(require, "which-key")
- if status_ok and desc ~= nil then
- for _, m in pairs(vim.tbl_flatten({ mode })) do
- which_key.register({ [group_lhs] = { name = desc } }, vim.tbl_extend("force", { mode = m }, group_opts))
- end
- end
-
- return function(lhs, rhs, opts)
- vim.keymap.set(mode, group_lhs .. lhs, rhs, vim.tbl_deep_extend("keep", opts or {}, group_opts))
- end
-end
-
--- TODO: add autocommand/keymap to reload current open file/module
-M.reload = function(name)
- local notify_opts = { title = string.format("[utils] reload module: '%s'", name) }
- local status_ok, result = pcall(require, "plenary.reload")
- if status_ok then
- status_ok, result = pcall(result.reload_module, name)
- end
-
- if status_ok then
- status_ok, result = pcall(require, name)
- end
-
- if status_ok then
- vim.notify("Successfully reloaded module", vim.log.levels.INFO, { title = "[utils]" })
- else
- vim.notify(string.format("Failed to reload module: %s", result), vim.log.levels.ERROR, notify_opts)
- end
-end
-
-M.popup = function(file_path)
- local buf = vim.api.nvim_create_buf(false, true)
-
- vim.api.nvim_buf_set_option(buf, "bufhidden", "wipe")
-
- local width = vim.api.nvim_get_option("columns")
- local height = vim.api.nvim_get_option("lines")
-
- local win_height = math.ceil(height * 0.8 - 4)
- local win_width = math.ceil(width * 0.8)
-
- local row = math.ceil((height - win_height) / 2 - 1)
- local col = math.ceil((width - win_width) / 2)
-
- local opts = {
- style = "minimal",
- relative = "editor",
- width = win_width,
- height = win_height,
- row = row,
- col = col,
- border = "rounded",
- }
-
- local win = vim.api.nvim_open_win(buf, true, opts)
- vim.api.nvim_win_set_option(win, "cursorline", true)
- vim.api.nvim_buf_set_option(buf, "modifiable", true)
- vim.api.nvim_command("$read" .. file_path)
- vim.api.nvim_buf_set_option(0, "modifiable", false)
-end
-
---- count existing buffers
----@param filter function predicate used to filter counted buffers
----@return table
-M.count_bufs_by_type = function(filter)
- local count = { normal = 0, acwrite = 0, help = 0, nofile = 0, nowrite = 0, quickfix = 0, terminal = 0, prompt = 0 }
- local buftypes = vim.api.nvim_list_bufs()
- for _, bufname in pairs(buftypes) do
- if filter == nil or filter(bufname) then
- local buftype = vim.api.nvim_buf_get_option(bufname, "buftype")
- buftype = buftype ~= "" and buftype or "normal"
- count[buftype] = count[buftype] + 1
- end
- end
- return count
-end
-
-M.file_exists = function(file)
- local ok, err, code = os.rename(file, file)
- if not ok and code == 13 then
- return true
- end
- return ok, err
-end
-
-M.isdir = function(path)
- return M.file_exists(path .. "/")
-end
-
----@param cmd? string Default command to run.
----@param args string[]? Default arguments.
----@param quiet boolean? Silence stdout of the job.
-M.run_cmd_with_args = function(cmd, args, quiet)
- quiet = quiet or false
- cmd = cmd or ""
- args = args or {}
- vim.ui.input({
- prompt = "Run command:",
- default = cmd .. " " .. table.concat(args, " "),
- completion = "shellcmd",
- kind = "cmd",
- }, function(input)
- if input ~= nil then
- args = {}
- for i, arg in ipairs(vim.split(input, " ", { trimempty = true })) do
- if i == 1 then
- cmd = arg
- else
- table.insert(args, vim.fn.expand(arg))
- end
- end
- M.job_with_notify(cmd, args, quiet):start()
- end
- end)
-end
-
-M.job_with_notify = function(cmd, args, quiet)
- local Job = require("plenary.job")
- local notification
- local win, height
- local output = ""
- local length = 0
- local width = 0
-
- local on_data = function(status, data)
- if data ~= nil then
- output = output .. data .. "\n"
- width = math.max(width, string.len(data) + 2)
- end
-
- notification = vim.notify(vim.trim(output), vim.log.levels.INFO, {
- title = string.format("[%s] %s", cmd, status),
- icon = M.status_signs[status].text,
- replace = notification,
- on_open = function(win_)
- win, height = win_, vim.api.nvim_win_get_height(win_)
- end,
- timeout = 10000,
- })
-
- vim.api.nvim_win_set_width(win, width)
- if height then
- vim.api.nvim_win_set_height(win, height + length)
- end
-
- length = length + 1
- end
-
- local on_start = function()
- if not quiet then
- on_data("started", string.format("$ %s %s", cmd, table.concat(args, " ")))
- end
- end
-
- local on_stdout = function(_, data)
- if not quiet then
- on_data("running", data)
- end
- end
-
- local on_stderr = function(_, data)
- on_data("running", data)
- end
-
- local on_exit = function(_, code)
- if code ~= 0 then
- on_data("failed")
- elseif not quiet then
- on_data("completed")
- end
- end
-
- return Job:new({
- command = cmd,
- args = args,
- enabled_recording = true,
- on_start = vim.schedule_wrap(on_start),
- on_stdout = vim.schedule_wrap(on_stdout),
- on_stderr = vim.schedule_wrap(on_stderr),
- on_exit = vim.schedule_wrap(on_exit),
- })
-end
-
-return M
diff --git a/nvim/.config/nvim/lua/tobyvin/utils/buffer.lua b/nvim/.config/nvim/lua/tobyvin/utils/buffer.lua
new file mode 100644
index 0000000..2169e30
--- /dev/null
+++ b/nvim/.config/nvim/lua/tobyvin/utils/buffer.lua
@@ -0,0 +1,109 @@
+local M = {}
+
+M.get_visual_range = function()
+ local start_pos = vim.fn.getpos("v")
+ local end_pos = vim.fn.getcurpos()
+ return { start_pos[2], end_pos[2] }
+end
+
+M.popup = function(file_path)
+ local buf = vim.api.nvim_create_buf(false, true)
+
+ vim.api.nvim_buf_set_option(buf, "bufhidden", "wipe")
+
+ local width = vim.api.nvim_get_option("columns")
+ local height = vim.api.nvim_get_option("lines")
+
+ local win_height = math.ceil(height * 0.8 - 4)
+ local win_width = math.ceil(width * 0.8)
+
+ local row = math.ceil((height - win_height) / 2 - 1)
+ local col = math.ceil((width - win_width) / 2)
+
+ local opts = {
+ style = "minimal",
+ relative = "editor",
+ width = win_width,
+ height = win_height,
+ row = row,
+ col = col,
+ border = "rounded",
+ }
+
+ local win = vim.api.nvim_open_win(buf, true, opts)
+ vim.api.nvim_win_set_option(win, "cursorline", true)
+ vim.api.nvim_buf_set_option(buf, "modifiable", true)
+ vim.api.nvim_command("$read" .. file_path)
+ vim.api.nvim_buf_set_option(0, "modifiable", false)
+end
+
+---@param retry fun(force:boolean?):nil
+M.modified_prompt_retry = function(retry)
+ local bufname = vim.fn.bufname(vim.fn.bufname())
+
+ vim.ui.select({ "write", "discard", "abort" }, {
+ prompt = string.format("No write since last change for buffer %s:", bufname),
+ kind = "select_normal",
+ }, function(_, idx)
+ if idx == 1 then
+ vim.cmd("write")
+ retry()
+ elseif idx == 2 then
+ retry(true)
+ else
+ vim.notify(
+ string.format("No write since last change for buffer %d", bufname),
+ vim.log.levels.ERROR,
+ { title = "Aborting..." }
+ )
+ end
+ end)
+end
+
+---@param cmd string vim command
+---@param force boolean
+M.kill = function(cmd, force)
+ local winid = vim.fn.win_getid()
+ local bufnr = vim.fn.winbufnr(winid)
+
+ if not force and vim.bo[bufnr].modified then
+ return M.modified_prompt_retry(M[cmd])
+ end
+
+ vim.api.nvim_exec_autocmds("User", { pattern = cmd })
+
+ if (string.sub(cmd, 1, 1) == "b" and vim.api.nvim_buf_is_valid(bufnr)) or vim.api.nvim_win_is_valid(winid) then
+ vim.cmd(cmd .. (force and "!" or ""))
+ end
+end
+
+---@param force boolean
+M.bdelete = function(force)
+ M.kill("bdelete", force)
+end
+
+---@param force boolean
+M.bwipeout = function(force)
+ M.kill("bwipeout", force)
+end
+
+---@param force boolean
+M.close = function(force)
+ M.kill("close", force)
+end
+
+---@param force boolean
+M.quit = function(force)
+ M.kill("quit", force)
+end
+
+---@param force boolean
+M.tabclose = function(force)
+ local cmd = "tabclose"
+ if #vim.api.nvim_list_tabpages() == 1 then
+ cmd = "qall"
+ end
+ vim.cmd(cmd .. (force and "!" or ""))
+end
+
+return M
diff --git a/nvim/.config/nvim/lua/tobyvin/utils/debug.lua b/nvim/.config/nvim/lua/tobyvin/utils/debug.lua
new file mode 100644
index 0000000..6327ca0
--- /dev/null
+++ b/nvim/.config/nvim/lua/tobyvin/utils/debug.lua
@@ -0,0 +1,36 @@
+local M = {}
+
+M.signs = {
+ breakpoint = { text = " ", texthl = "debugBreakpoint" },
+ condition = { text = "ﳁ ", texthl = "debugBreakpoint" },
+ rejected = { text = " ", texthl = "debugBreakpoint" },
+ logpoint = { text = " ", texthl = "debugBreakpoint" },
+ stopped = { text = " ", texthl = "debugBreakpoint", linehl = "debugPC", numhl = "debugPC" },
+}
+
+M.notifs = {}
+
+M.get_notif_data = function(id, token)
+ if not M.notifs[id] then
+ M.notifs[id] = {}
+ end
+
+ if not M.notifs[id][token] then
+ M.notifs[id][token] = {}
+ end
+
+ return M.notifs[id][token]
+end
+
+M.format_title = function(title, client)
+ if type(client) == "table" then
+ client = client.name
+ end
+ return client .. (#title > 0 and ": " .. title or "")
+end
+
+M.format_message = function(message, percentage)
+ return (percentage and percentage .. "%\t" or "") .. (message or "")
+end
+
+return M
diff --git a/nvim/.config/nvim/lua/tobyvin/utils/diagnostic.lua b/nvim/.config/nvim/lua/tobyvin/utils/diagnostic.lua
new file mode 100644
index 0000000..d4900ed
--- /dev/null
+++ b/nvim/.config/nvim/lua/tobyvin/utils/diagnostic.lua
@@ -0,0 +1,48 @@
+local M = {}
+
+M.signs = {
+ hint = { text = " ", texthl = "DiagnosticSignHint" },
+ info = { text = " ", texthl = "DiagnosticSignInfo" },
+ warn = { text = " ", texthl = "DiagnosticSignWarn" },
+ error = { text = " ", texthl = "DiagnosticSignError" },
+}
+
+setmetatable(M.signs, {
+ __index = function(t, k)
+ if type(k) == "number" then
+ return t[vim.diagnostic.severity[k]]
+ end
+ return t[k:lower():gsub("warning", "warn")]
+ end,
+})
+
+M.count = function(bufnr)
+ local items = {}
+ for i, level in ipairs(vim.diagnostic.severity) do
+ items[level] = #vim.diagnostic.get(bufnr, { severity = i })
+ end
+
+ setmetatable(items, {
+ __index = function(t, k)
+ if type(k) == "number" then
+ return t[vim.diagnostic.severity[k]]
+ end
+ return t[k:upper():gsub("WARNING", "WARN")]
+ end,
+ })
+
+ return items
+end
+
+M.indicator = function(bufnr)
+ local diagnostic_count = M.count(bufnr)
+ local tbl = {}
+ for level, count in pairs(diagnostic_count) do
+ if count > 0 then
+ table.insert(tbl, M.signs[level].text .. count)
+ end
+ end
+ return table.concat(tbl, " ")
+end
+
+return M
diff --git a/nvim/.config/nvim/lua/tobyvin/utils/documentation.lua b/nvim/.config/nvim/lua/tobyvin/utils/documentation.lua
new file mode 100644
index 0000000..1c9eb91
--- /dev/null
+++ b/nvim/.config/nvim/lua/tobyvin/utils/documentation.lua
@@ -0,0 +1,27 @@
+local M = {}
+
+M.sources = {
+ vim = function()
+ vim.cmd("help " .. vim.fn.expand("<cword>"))
+ end,
+ help = function()
+ vim.cmd("Man " .. vim.fn.expand("<cword>"))
+ end,
+}
+
+M.register = function(filetypes, callback)
+ for _, filetype in ipairs(vim.tbl_flatten({ filetypes })) do
+ M.sources[filetype] = callback
+ end
+end
+
+M.open = function()
+ local filetype = vim.bo.filetype
+ if vim.tbl_contains(vim.tbl_keys(M.sources), filetype) then
+ M.sources[filetype]()
+ else
+ vim.notify("[Utils] Documentation not available", "error")
+ end
+end
+
+return M
diff --git a/nvim/.config/nvim/lua/tobyvin/utils/fs.lua b/nvim/.config/nvim/lua/tobyvin/utils/fs.lua
new file mode 100644
index 0000000..9b7c0f0
--- /dev/null
+++ b/nvim/.config/nvim/lua/tobyvin/utils/fs.lua
@@ -0,0 +1,34 @@
+local M = {}
+
+-- TODO: add autocommand/keymap to reload current open file/module
+M.reload = function(name)
+ local notify_opts = { title = string.format("[utils] reload module: '%s'", name) }
+ local status_ok, result = pcall(require, "plenary.reload")
+ if status_ok then
+ status_ok, result = pcall(result.reload_module, name)
+ end
+
+ if status_ok then
+ status_ok, result = pcall(require, name)
+ end
+
+ if status_ok then
+ vim.notify("Successfully reloaded module", vim.log.levels.INFO, { title = "[utils]" })
+ else
+ vim.notify(string.format("Failed to reload module: %s", result), vim.log.levels.ERROR, notify_opts)
+ end
+end
+
+M.file_exists = function(file)
+ local ok, err, code = os.rename(file, file)
+ if not ok and code == 13 then
+ return true
+ end
+ return ok, err
+end
+
+M.isdir = function(path)
+ return M.file_exists(path .. "/")
+end
+
+return M
diff --git a/nvim/.config/nvim/lua/tobyvin/utils/init.lua b/nvim/.config/nvim/lua/tobyvin/utils/init.lua
new file mode 100644
index 0000000..e2084a2
--- /dev/null
+++ b/nvim/.config/nvim/lua/tobyvin/utils/init.lua
@@ -0,0 +1,12 @@
+local M = {
+ keymap = require("tobyvin.utils.keymap"),
+ job = require("tobyvin.utils.job"),
+ fs = require("tobyvin.utils.fs"),
+ buffer = require("tobyvin.utils.buffer"),
+ debug = require("tobyvin.utils.debug"),
+ status = require("tobyvin.utils.status"),
+ diagnostic = require("tobyvin.utils.diagnostic"),
+ documentation = require("tobyvin.utils.documentation"),
+}
+
+return M
diff --git a/nvim/.config/nvim/lua/tobyvin/utils/job.lua b/nvim/.config/nvim/lua/tobyvin/utils/job.lua
new file mode 100644
index 0000000..d5ac03e
--- /dev/null
+++ b/nvim/.config/nvim/lua/tobyvin/utils/job.lua
@@ -0,0 +1,97 @@
+local M = {}
+
+---@param cmd? string Default command to run.
+---@param args string[]? Default arguments.
+---@param quiet boolean? Silence stdout of the job.
+M.cmd = function(cmd, args, quiet)
+ quiet = quiet or false
+ cmd = cmd or ""
+ args = args or {}
+ vim.ui.input({
+ prompt = "Run command:",
+ default = cmd .. " " .. table.concat(args, " "),
+ completion = "shellcmd",
+ kind = "cmd",
+ }, function(input)
+ if input ~= nil then
+ args = {}
+ for i, arg in ipairs(vim.split(input, " ", { trimempty = true })) do
+ if i == 1 then
+ cmd = arg
+ else
+ table.insert(args, vim.fn.expand(arg))
+ end
+ end
+ M.with_notify(cmd, args, quiet):start()
+ end
+ end)
+end
+
+M.with_notify = function(cmd, args, quiet)
+ local Job = require("plenary.job")
+ local notification
+ local win, height
+ local output = ""
+ local length = 0
+ local width = 0
+
+ local on_data = function(status, data)
+ if data ~= nil then
+ output = output .. data .. "\n"
+ width = math.max(width, string.len(data) + 2)
+ end
+
+ notification = vim.notify(vim.trim(output), vim.log.levels.INFO, {
+ title = string.format("[%s] %s", cmd, status),
+ icon = M.status_signs[status].text,
+ replace = notification,
+ on_open = function(win_)
+ win, height = win_, vim.api.nvim_win_get_height(win_)
+ end,
+ timeout = 10000,
+ })
+
+ vim.api.nvim_win_set_width(win, width)
+ if height then
+ vim.api.nvim_win_set_height(win, height + length)
+ end
+
+ length = length + 1
+ end
+
+ local on_start = function()
+ if not quiet then
+ on_data("started", string.format("$ %s %s", cmd, table.concat(args, " ")))
+ end
+ end
+
+ local on_stdout = function(_, data)
+ if not quiet then
+ on_data("running", data)
+ end
+ end
+
+ local on_stderr = function(_, data)
+ on_data("running", data)
+ end
+
+ local on_exit = function(_, code)
+ if code ~= 0 then
+ on_data("failed")
+ elseif not quiet then
+ on_data("completed")
+ end
+ end
+
+ return Job:new({
+ command = cmd,
+ args = args,
+ enabled_recording = true,
+ on_start = vim.schedule_wrap(on_start),
+ on_stdout = vim.schedule_wrap(on_stdout),
+ on_stderr = vim.schedule_wrap(on_stderr),
+ on_exit = vim.schedule_wrap(on_exit),
+ })
+end
+
+return M
diff --git a/nvim/.config/nvim/lua/tobyvin/utils/keymap.lua b/nvim/.config/nvim/lua/tobyvin/utils/keymap.lua
new file mode 100644
index 0000000..83e5c12
--- /dev/null
+++ b/nvim/.config/nvim/lua/tobyvin/utils/keymap.lua
@@ -0,0 +1,34 @@
+local M = {}
+
+M.groups = {}
+
+--- Helper function to create a group of keymaps that share a common prefix and/or options.
+---@param mode string|table Same mode short names as vim.keymap.set(). A list will create the group on all modes.
+---@param group_lhs string Prefix to prepend to the lhs of all keymaps in the group.
+---@param group_opts ?table Options to apply to all keymaps in this group. (Same as options listed in vim.keymap.set)
+---@return function Function to create mapping using the groups defaults.
+-- TODO: Possibly add memoization to groups/subgroups using the __call metatable attribute
+M.group = function(mode, group_lhs, group_opts)
+ group_opts = group_opts or {}
+
+ for _, m in pairs(vim.tbl_flatten({ mode })) do
+ M.groups[m] = M.groups[m] == nil and {} or M.groups[m]
+ M.groups[m][group_lhs] = group_opts
+ end
+
+ local desc = group_opts.desc
+ group_opts.desc = nil
+
+ local status_ok, which_key = pcall(require, "which-key")
+ if status_ok and desc ~= nil then
+ for _, m in pairs(vim.tbl_flatten({ mode })) do
+ which_key.register({ [group_lhs] = { name = desc } }, vim.tbl_extend("force", { mode = m }, group_opts))
+ end
+ end
+
+ return function(lhs, rhs, opts)
+ vim.keymap.set(mode, group_lhs .. lhs, rhs, vim.tbl_deep_extend("keep", opts or {}, group_opts))
+ end
+end
+
+return M
diff --git a/nvim/.config/nvim/lua/tobyvin/utils/status.lua b/nvim/.config/nvim/lua/tobyvin/utils/status.lua
new file mode 100644
index 0000000..173a005
--- /dev/null
+++ b/nvim/.config/nvim/lua/tobyvin/utils/status.lua
@@ -0,0 +1,30 @@
+local M = {}
+
+M.signs = {
+ started = { text = "ﳁ ", texthl = "diffChanged" },
+ running = { text = "ﳁ ", texthl = "DiagnosticSignInfo" },
+ failed = { text = " ", texthl = "DiagnosticSignError" },
+ completed = { text = " ", texthl = "diffAdded" },
+ spinner = { text = { "⣷", "⣯", "⣟", "⡿", "⢿", "⣻", "⣽", "⣾" }, texthl = "DiagnosticSignInfo" },
+}
+
+M.update_spinner = function(client_id, token)
+ local notif_data = M.get_notif_data(client_id, token)
+
+ if notif_data.spinner then
+ local new_spinner = (notif_data.spinner + 1) % #M.status_signs.spinner.text
+ notif_data.spinner = new_spinner
+
+ notif_data.notification = vim.notify(nil, nil, {
+ hide_from_history = true,
+ icon = M.status_signs.spinner.text[new_spinner],
+ replace = notif_data.notification,
+ })
+
+ vim.defer_fn(function()
+ M.update_spinner(client_id, token)
+ end, 100)
+ end
+end
+
+return M