From 4b0e4d2c78c324547e3c5b5f57fd12c172e5dd67 Mon Sep 17 00:00:00 2001 From: Toby Vincent Date: Sun, 28 Aug 2022 13:27:20 -0500 Subject: feat(nvim): various config improvements --- nvim/.config/nvim/lua/tobyvin/autocmds.lua | 16 ++- nvim/.config/nvim/lua/tobyvin/keymaps.lua | 4 + nvim/.config/nvim/lua/tobyvin/lsp/handlers.lua | 82 ++++--------- nvim/.config/nvim/lua/tobyvin/plugins/dressing.lua | 6 +- nvim/.config/nvim/lua/tobyvin/plugins/fidget.lua | 4 +- nvim/.config/nvim/lua/tobyvin/plugins/lualine.lua | 45 +++++-- .../nvim/lua/tobyvin/plugins/refactoring.lua | 67 +++++------ .../nvim/lua/tobyvin/plugins/rust-tools.lua | 57 +-------- nvim/.config/nvim/lua/tobyvin/utils.lua | 129 ++++++++++++++++++--- 9 files changed, 226 insertions(+), 184 deletions(-) (limited to 'nvim') diff --git a/nvim/.config/nvim/lua/tobyvin/autocmds.lua b/nvim/.config/nvim/lua/tobyvin/autocmds.lua index 71fe5d4..e7fcdfa 100644 --- a/nvim/.config/nvim/lua/tobyvin/autocmds.lua +++ b/nvim/.config/nvim/lua/tobyvin/autocmds.lua @@ -1,10 +1,10 @@ local M = {} M.setup = function() - local augroup_user = vim.api.nvim_create_augroup("Default", { clear = true }) + local group = vim.api.nvim_create_augroup("tobyvin", { clear = true }) vim.api.nvim_create_autocmd("User", { - group = augroup_user, + group = group, pattern = "bdelete", callback = function(opts) local windows = vim.tbl_filter(function(win) @@ -35,10 +35,8 @@ M.setup = function() desc = "Sets the window to the alternate buffer for bdelete", }) - local augroup_default = vim.api.nvim_create_augroup("Default", { clear = true }) - vim.api.nvim_create_autocmd("TextYankPost", { - group = augroup_default, + group = group, pattern = "*", callback = function() vim.highlight.on_yank() @@ -47,7 +45,7 @@ M.setup = function() }) vim.api.nvim_create_autocmd("BufWritePre", { - group = augroup_default, + group = group, pattern = "*", callback = function() local cursor = vim.api.nvim_win_get_cursor(0) @@ -58,7 +56,7 @@ M.setup = function() }) vim.api.nvim_create_autocmd("FileType", { - group = augroup_default, + group = group, pattern = "help", callback = function() vim.opt_local.wrap = true @@ -71,7 +69,7 @@ M.setup = function() }) vim.api.nvim_create_autocmd("FileType", { - group = augroup_default, + group = group, pattern = "qf", callback = function() vim.opt_local.buflisted = false @@ -80,7 +78,7 @@ M.setup = function() }) vim.api.nvim_create_autocmd("FileType", { - group = augroup_default, + group = group, pattern = { "xml", "html", "xhtml", "css", "scss", "javascript", "lua", "dart" }, callback = function() vim.opt_local.shiftwidth = 2 diff --git a/nvim/.config/nvim/lua/tobyvin/keymaps.lua b/nvim/.config/nvim/lua/tobyvin/keymaps.lua index 1d88d82..c48acf8 100644 --- a/nvim/.config/nvim/lua/tobyvin/keymaps.lua +++ b/nvim/.config/nvim/lua/tobyvin/keymaps.lua @@ -13,6 +13,10 @@ M.setup = function() nmap("h", utils.hover, { desc = "Hover" }) nmap("H", utils.docs, { desc = "Docs" }) nmap("w", M.write, { desc = "Write" }) + + local nmap_run = utils.create_map_group("n", "r", { desc = "Run" }) + + nmap_run("c", utils.run_cmd_with_args, { desc = "Command" }) end return M diff --git a/nvim/.config/nvim/lua/tobyvin/lsp/handlers.lua b/nvim/.config/nvim/lua/tobyvin/lsp/handlers.lua index 5adda44..cfd2f30 100644 --- a/nvim/.config/nvim/lua/tobyvin/lsp/handlers.lua +++ b/nvim/.config/nvim/lua/tobyvin/lsp/handlers.lua @@ -1,80 +1,42 @@ -local utils = require("tobyvin.utils") local M = {} +local handler_prehook = function(method, pre_hook, post_hook) + local original = vim.lsp.handlers[method] + vim.lsp.handlers[method] = function(...) + if pre_hook ~= nil then + pre_hook(...) + end + original(...) + if post_hook ~= nil then + post_hook(...) + end + end +end + M.setup = function() - vim.lsp.handlers["textDocument/definition"] = function(_, result) + handler_prehook("textDocument/definition", function(_, result) if not result or vim.tbl_isempty(result) then - vim.notify("[LSP] Could not find definition", "info") - return + vim.notify("[LSP] No definition found", "info") end + end) - if vim.tbl_islist(result) then - vim.lsp.util.jump_to_location(result[1], "utf-8", true) - else - vim.lsp.util.jump_to_location(result, "utf-8", true) + handler_prehook("textDocument/implementation", function(_, result) + if not result or vim.tbl_isempty(result) then + vim.notify("[LSP] No implementations found", "info") end - end + end) vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.handlers["textDocument/publishDiagnostics"], { - signs = { - severity_limit = "Error", - }, - underline = { - severity_limit = "Warning", - }, + signs = true, + underline = true, update_in_insert = true, virtual_text = true, }) - -- vim.lsp.handlers["$/progress"] = function(_, result, ctx) - -- local client_id = ctx.client_id - -- local val = result.value - -- if val.kind then - -- if not utils.client_notifs[client_id] then - -- utils.client_notifs[client_id] = {} - -- end - -- local notif_data = utils.client_notifs[client_id][result.token] - -- if val.kind == "begin" then - -- local message = utils.format_message(val.message, val.percentage) - -- local notification = vim.notify(message, "info", { - -- title = utils.format_title(val.title, vim.lsp.get_client_by_id(client_id)), - -- icon = utils.progress_signs.spinner.text[1], - -- timeout = false, - -- hide_from_history = false, - -- }) - -- utils.client_notifs[client_id][result.token] = { - -- notification = notification, - -- spinner = 1, - -- } - -- utils.update_spinner(client_id, result.token) - -- elseif val.kind == "report" and notif_data then - -- local new_notif = vim.notify( - -- utils.format_message(val.message, val.percentage), - -- "info", - -- { replace = notif_data.notification, hide_from_history = false } - -- ) - -- utils.client_notifs[client_id][result.token] = { - -- notification = new_notif, - -- spinner = notif_data.spinner, - -- } - -- elseif val.kind == "end" and notif_data then - -- local new_notif = vim.notify( - -- val.message and utils.format_message(val.message) or "Complete", - -- "info", - -- { icon = utils.progress_signs.complete.text, replace = notif_data.notification, timeout = 3000 } - -- ) - -- utils.client_notifs[client_id][result.token] = { - -- notification = new_notif, - -- } - -- end - -- end - -- end - vim.lsp.handlers["window/showMessage"] = function(_, result, ctx) vim.notify({ result.message }, 5 - result.type, { title = "[LSP] " .. vim.lsp.get_client_by_id(ctx.client_id), - timeout = 2500, }) end end diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/dressing.lua b/nvim/.config/nvim/lua/tobyvin/plugins/dressing.lua index 6ab2227..bde53c1 100644 --- a/nvim/.config/nvim/lua/tobyvin/plugins/dressing.lua +++ b/nvim/.config/nvim/lua/tobyvin/plugins/dressing.lua @@ -20,11 +20,9 @@ M.config_overrides = { }, }, input = { - ["cargo add"] = { - relative = "win", - }, - ["cargo rm"] = { + cmd = { relative = "win", + insert_only = false, }, }, } diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/fidget.lua b/nvim/.config/nvim/lua/tobyvin/plugins/fidget.lua index fcef526..4d925bb 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.progress_signs.spinner.text, - done = vim.trim(utils.progress_signs.complete.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/lualine.lua b/nvim/.config/nvim/lua/tobyvin/plugins/lualine.lua index 220b5ad..f47e3ad 100644 --- a/nvim/.config/nvim/lua/tobyvin/plugins/lualine.lua +++ b/nvim/.config/nvim/lua/tobyvin/plugins/lualine.lua @@ -1,6 +1,10 @@ local utils = require("tobyvin.utils") local M = {} +local function get_short_cwd() + return vim.fn.fnamemodify(vim.fn.getcwd(), ":~") +end + M.to_char = function(str) return str:sub(1, 1) end @@ -152,32 +156,53 @@ M.setup = function() lualine_a = { { "mode", fmt = M.to_char } }, lualine_b = { "branch", - { "diff", source = M.diff_source }, + { + "diff", + source = M.diff_source, + padding = { left = 0, right = 1 }, + }, + { + auto_session_library.current_session_name, + cond = function() + return auto_session_ok + end, + }, { "diagnostics", - sources = { "nvim_workspace_diagnostic", "nvim_lsp" }, + 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, }, + update_in_insert = false, + padding = { left = 0, right = 1 }, }, }, lualine_c = { - { - auto_session_library.current_session_name, - cond = function() - return auto_session_ok - end, - separator = ">", - }, { "filename", path = 1, - separator = ">", shorting_target = 100, }, + { + "diagnostics", + sources = { + function() + 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, + }, + update_in_insert = false, + padding = { left = 0, right = 1 }, + separator = ">", + }, { navic.get_location, cond = function() diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/refactoring.lua b/nvim/.config/nvim/lua/tobyvin/plugins/refactoring.lua index b15068b..c3e6952 100644 --- a/nvim/.config/nvim/lua/tobyvin/plugins/refactoring.lua +++ b/nvim/.config/nvim/lua/tobyvin/plugins/refactoring.lua @@ -2,39 +2,40 @@ local utils = require("tobyvin.utils") local M = {} M.setup = function() - local status_ok, refactoring = pcall(require, "refactoring") - if not status_ok then - vim.notify("Failed to load module 'refactoring'", "error") - return - end - - refactoring.setup() - - local nmap = utils.create_map_group("n", "r", { desc = "Refactor" }) - nmap("b", function() - refactoring.refactor("Extract Block") - end, { desc = "Extract Block" }) - nmap("B", function() - refactoring.refactor("Extract Block To File") - end, { desc = "Extract Block To File" }) - nmap("i", function() - refactoring.refactor("Inline Variable") - end, { desc = "Inline Variable" }) - - -- TODO: Fix needing to exit visual mode - local vmap = utils.create_map_group("v", "r", { desc = "Refactor" }) - vmap("e", function() - refactoring.refactor("Extract Function") - end, { desc = "Extract Function" }) - vmap("f", function() - refactoring.refactor("Extract Function To File") - end, { desc = "Extract Function To File" }) - vmap("v", function() - refactoring.refactor("Extract Variable") - end, { desc = "Extract Variable" }) - vmap("i", function() - refactoring.refactor("Inline Variable") - end, { desc = "Inline Variable" }) + -- TODO: fix or find a better option, also appeared to have a high load time when running packer profile + -- local status_ok, refactoring = pcall(require, "refactoring") + -- if not status_ok then + -- vim.notify("Failed to load module 'refactoring'", "error") + -- return + -- end + -- + -- refactoring.setup() + -- + -- local nmap = utils.create_map_group("n", "r", { desc = "Refactor" }) + -- nmap("b", function() + -- refactoring.refactor("Extract Block") + -- end, { desc = "Extract Block" }) + -- nmap("B", function() + -- refactoring.refactor("Extract Block To File") + -- end, { desc = "Extract Block To File" }) + -- nmap("i", function() + -- refactoring.refactor("Inline Variable") + -- end, { desc = "Inline Variable" }) + -- + -- -- TODO: Fix needing to exit visual mode + -- local vmap = utils.create_map_group("v", "r", { desc = "Refactor" }) + -- vmap("e", function() + -- refactoring.refactor("Extract Function") + -- end, { desc = "Extract Function" }) + -- vmap("f", function() + -- refactoring.refactor("Extract Function To File") + -- end, { desc = "Extract Function To File" }) + -- vmap("v", function() + -- refactoring.refactor("Extract Variable") + -- end, { desc = "Extract Variable" }) + -- vmap("i", function() + -- refactoring.refactor("Inline Variable") + -- end, { desc = "Inline Variable" }) end return M diff --git a/nvim/.config/nvim/lua/tobyvin/plugins/rust-tools.lua b/nvim/.config/nvim/lua/tobyvin/plugins/rust-tools.lua index 4cae3db..98cdcc8 100644 --- a/nvim/.config/nvim/lua/tobyvin/plugins/rust-tools.lua +++ b/nvim/.config/nvim/lua/tobyvin/plugins/rust-tools.lua @@ -1,4 +1,3 @@ -local Job = require("plenary.job") local utils = require("tobyvin.utils") local lsp = require("tobyvin.lsp") local M = { @@ -15,53 +14,8 @@ M.dap_adapter = function() vim.notify("Failed to find codelldb adapter") end -M.cargo_subcmd = function(subcmd) - vim.ui.input({ prompt = string.format("cargo %s", subcmd) }, function(input) - if input == nil then - return - end - local args = { subcmd } - for _, arg in ipairs(vim.split(input, " ", { trimempty = true })) do - table.insert(args, arg) - end - - local cmd = "cargo" - local notification - local output = "" - local length = 0 - local win, height - local on_data = function(_, data) - output = output .. data .. "\n" - notification = vim.notify(vim.trim(output), vim.log.levels.INFO, { - title = string.format("[%s] %s", cmd, subcmd), - replace = notification, - on_open = function(win_) - win, height = win_, vim.api.nvim_win_get_height(win_) - end, - }) - if height then - vim.api.nvim_win_set_height(win, height + length) - end - length = length + 1 - end - - local job = Job:new({ - command = "cargo", - args = args, - on_stdout = vim.schedule_wrap(on_data), - on_stderr = vim.schedule_wrap(on_data), - }) - - job:start() - end) -end - -M.cargo_add = function() - M.cargo_subcmd("add") -end - -M.cargo_rm = function() - M.cargo_subcmd("rm") +M.cargo_cmd = function() + utils.run_cmd_with_args("cargo") end M.setup = function() @@ -102,11 +56,8 @@ M.setup = function() local nmap_run = utils.create_map_group("n", "r", { desc = "Run", buffer = bufnr }) nmap_run("r", rust_tools.runnables.runnables, { desc = "Runnables" }) - - local nmap_run_cargo = utils.create_map_group("n", "rc", { desc = "Cargo", buffer = bufnr }) - nmap_run_cargo("o", rust_tools.open_cargo_toml.open_cargo_toml, { desc = "Open Cargo.toml" }) - nmap_run_cargo("a", M.cargo_add, { desc = "Add Crate" }) - nmap_run_cargo("r", M.cargo_rm, { desc = "Remove Crate" }) + nmap_run("c", M.cargo_cmd, { desc = "Command" }) + nmap_run("o", rust_tools.open_cargo_toml.open_cargo_toml, { desc = "Open Cargo.toml" }) end, }), dap = M.dap_adapter(), diff --git a/nvim/.config/nvim/lua/tobyvin/utils.lua b/nvim/.config/nvim/lua/tobyvin/utils.lua index e51b0b3..6464b2d 100644 --- a/nvim/.config/nvim/lua/tobyvin/utils.lua +++ b/nvim/.config/nvim/lua/tobyvin/utils.lua @@ -1,8 +1,11 @@ ---@diagnostic disable: missing-parameter local M = {} -M.progress_signs = { - complete = { text = " ", texthl = "diffAdded" }, +M.status_signs = { + started = { text = "ﳁ ", texthl = "diffChanged" }, + running = { text = "ﳁ ", texthl = "DiagnosticSignInfo" }, + failed = { text = " ", texthl = "DiagnosticSignError" }, + completed = { text = " ", texthl = "diffAdded" }, spinner = { text = { "⣷", "⣯", "⣟", "⡿", "⢿", "⣻", "⣽", "⣾" }, texthl = "DiagnosticSignInfo" }, } @@ -15,10 +18,10 @@ M.debug_signs = { } M.diagnostic_signs = { - HINT = { text = " ", texthl = "DiagnosticSignHint" }, - INFO = { text = " ", texthl = "DiagnosticSignInfo" }, - WARN = { text = " ", texthl = "DiagnosticSignWarn" }, - ERROR = { text = " ", texthl = "DiagnosticSignError" }, + hint = { text = " ", texthl = "DiagnosticSignHint" }, + info = { text = " ", texthl = "DiagnosticSignInfo" }, + warn = { text = " ", texthl = "DiagnosticSignWarn" }, + error = { text = " ", texthl = "DiagnosticSignError" }, } setmetatable(M.diagnostic_signs, { @@ -26,7 +29,7 @@ setmetatable(M.diagnostic_signs, { if type(k) == "number" then return t[vim.diagnostic.severity[k]] end - return t[k:upper():gsub("WARNING", "WARN")] + return t[k:lower():gsub("warning", "warn")] end, }) @@ -35,6 +38,16 @@ M.diagnostic_count = function(bufnr) 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 @@ -53,12 +66,12 @@ 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.progress_signs.spinner.text + 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.progress_signs.spinner.text[new_spinner], + icon = M.status_signs.spinner.text[new_spinner], replace = notif_data.notification, }) @@ -127,8 +140,6 @@ M.win_buf_kill = function(cmd, force) 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 - - vim.api.nvim_exec_autocmds("User", { pattern = cmd }) end ---@param force boolean @@ -211,8 +222,6 @@ end M.create_map_group = function(mode, group_lhs, group_opts) group_opts = group_opts or {} - local name = group_opts.name - local desc = group_opts.desc group_opts.desc = nil @@ -306,4 +315,98 @@ 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 -- cgit v1.2.3-70-g09d2