diff options
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 |