diff --git a/nvim/init.lua b/nvim/init.lua index 6a3e42c..33c4d27 100644 --- a/nvim/init.lua +++ b/nvim/init.lua @@ -1,134 +1,222 @@ -vim.opt.termguicolors = true vim.g.mapleader = vim.keycode("") -vim.g.maplocalleader = vim.keycode(",") +vim.g.maplocalleader = vim.keycode("") +vim.o.langmap = "ø:" --- ---------------------------------------- --- SETTINGS --- ---------------------------------------- - --- system -vim.o.shell = "/usr/bin/bash" -vim.o.fileencodings = "utf-8,ucs-bom,gb18030,gbk,gb2312,cp936" -vim.o.fileformats = "unix" -vim.o.swapfile = false +-- general options +vim.o.shell = "/usr/bin/zsh" vim.g.BASH_Ctrl_j = "off" vim.g.BASH_Ctrl_l = "off" --- TODO remove in commands +vim.opt.clipboard = vim.opt.clipboard + { "unnamedplus" } +vim.o.guicursor = "n-v-c:block-CustomCursor,i:ver100-CustomICursor,n-v-c:blinkon0,i:blinkwait10" +vim.o.cursorline = true +vim.o.list = true +vim.o.listchars = "tab:→ ,trail:·,extends:↷,precedes:↶,nbsp:+" +vim.o.mouse = "a" +vim.o.ruler = false +vim.o.scrolloff = 4 +vim.opt.shortmess:append({ W = true, I = true, c = true, C = true }) +vim.o.cmdheight = 0 +vim.o.showmode = false +vim.o.sidescrolloff = 8 +vim.o.timeoutlen = 300 +vim.o.virtualedit = "block" +vim.o.wildmode = "longest:full,full" +vim.o.wrap = false +vim.opt.diffopt:append("linematch:60") -- second stage diff to align lines --- undo +-- File History +vim.o.undofile = true vim.o.undolevels = 100000 vim.o.undoreload = 100000 +vim.o.updatetime = 200 --- buffer -vim.o.hidden = true -- Enable background buffers -vim.o.number = false -vim.o.relativenumber = false -vim.o.cursorline = false -vim.o.switchbuf = "useopen" -- Use existing window if buffer is already open +-- Tab stop +vim.o.expandtab = true +vim.o.shiftround = true +vim.o.shiftwidth = 2 +vim.o.tabstop = 2 +vim.o.smartindent = true --- diffs -vim.o.diffopt = "internal,filler,closeoff,hiddenoff,vertical,algorithm:patience" +-- Session options +vim.opt.sessionoptions = { "buffers", "curdir", "tabpages", "winsize", "help", "globals", "skiprtp", "folds" } --- tabs -vim.o.expandtab = true -- Use spaces instead of tabs -vim.o.shiftround = true -- Round indent -vim.o.tabstop = 4 -- Number of spaces tabs count for -vim.o.shiftwidth = 4 -- Size of an indent -vim.o.listchars = "tab:→ ,trail:·,extends:↷,precedes:↶,nbsp:+" -vim.o.list = true -- Show listchars +-- Completion Window/Popup settings +vim.o.completeopt = "menu,menuone,popup,fuzzy" +vim.o.pumblend = 10 +vim.o.pumheight = 10 +vim.o.winminwidth = 5 --- search -vim.opt.smartcase = false -vim.opt.ignorecase = false -vim.opt.wildmode = { "full" } -- Command-line completion mode -vim.opt.wildignore = vim.opt.wildignore - + { "*swp", "*.class", "*.pyc", "*.png", "*.jpg", "*.gif", "*.zip", "*/tmp/*", "*.o", ".obj", "*.so" } - --- folding -vim.o.foldenable = true -- enable fold -vim.o.foldlevel = 99 -- start editing with all folds opened -vim.o.foldmethod = "expr" -- use tree-sitter for folding method +-- Fold settings +vim.opt.foldlevel = 99 +vim.opt.smoothscroll = true +vim.opt.foldmethod = "expr" +vim.opt.foldtext = "" vim.o.foldexpr = "v:lua.vim.treesitter.foldexpr()" --- cursor -vim.o.scrolloff = 5 -- Lines of context -vim.o.scrolljump = 1 -- Lines to scroll when cursor leaves screen -vim.o.sidescrolloff = 4 -- Columns of context -vim.o.showmatch = true -- Show matching brackets / parentheses +-- Format settings +vim.o.formatoptions = "jroqlnt" --- editing -vim.o.langmap = "å(,¨),ø:,æ^,+$" -vim.opt.clipboard = vim.opt.clipboard + { "unnamedplus" } +-- Grep settings +vim.o.grepformat = "%f:%l:%c:%m" +vim.o.grepprg = "rg --vimgrep" -vim.opt.formatoptions = vim.opt.formatoptions - { "c", "r", "o" } -vim.opt.iskeyword = vim.opt.iskeyword - { "." } +-- Search/subsitute settings +vim.o.ignorecase = false +vim.o.inccommand = "nosplit" +vim.o.jumpoptions = "view" +vim.o.smartcase = false -vim.api.nvim_create_autocmd({ "BufReadPost" }, { - pattern = { "quickfix" }, - callback = function() vim.keymap.set("n", "", "", { buffer = true }) end, -}) +-- Spelling +vim.opt.spelllang = { "en" } + +-- Splits +vim.o.splitbelow = true +vim.o.splitkeep = "screen" +vim.o.splitright = true + +-- Terminal +vim.o.termguicolors = true + +-- Status Column +vim.o.number = true +vim.o.relativenumber = true + +vim.opt.termguicolors = true -- ---------------------------------------- -- MAPS -- ---------------------------------------- local map = vim.keymap.set -map("n", "Q", "", { noremap = true }) -map("n", "q:", "", { noremap = true }) +-- swap ;: +map({ "n", "v" }, ";", ":") +map({ "n", "v" }, ":", ";") -map({ "n", "v" }, "", "", { silent = true }) -map("n", "ww", [[:cd %:p:h]], { noremap = true }) -- change workspace -map("n", "", "noh", { silent = true, noremap = true }) -map("", "", "", { silent = true, noremap = true }) +-- better esc +map({ "i", "n", "s" }, "", function() + vim.cmd("noh") + return "" +end, { expr = true, desc = "Escape and Clear hlsearch" }) --- to navigate the completion menu -map("i", "", [[pumvisible() ? "\" : "\"]], { expr = true, noremap = true }) -map("i", "", [[pumvisible() ? "\" : "\"]], { expr = true, noremap = true }) -vim.opt.pumheight = 0 +-- better up/down +map({ "n", "x" }, "j", "v:count == 0 ? 'gj' : 'j'", { desc = "Down", expr = true, silent = true }) +map({ "n", "x" }, "k", "v:count == 0 ? 'gk' : 'k'", { desc = "Up", expr = true, silent = true }) --- CURSOR --- stay visual when indenting -map({ "n", "v" }, "-", "_", { noremap = true }) -map("v", "v", "", { noremap = true }) -map("v", "", ">gv", { noremap = true }) -map("v", "", "o", "m`o``", { noremap = true }) -- Insert a newline in normal mode --- better indenting -map("v", "<", "", ">gv") --- repeat and next -map("n", "\\", "n.", { noremap = true, silent = true }) +-- Move to window using the hjkl keys +map("n", "", "h", { desc = "Go to Left Window", remap = true }) +map("n", "", "j", { desc = "Go to Lower Window", remap = true }) +map("n", "", "k", { desc = "Go to Upper Window", remap = true }) +map("n", "", "l", { desc = "Go to Right Window", remap = true }) + +-- Resize window using hjkl keys +map("n", "", "resize +2", { desc = "Increase Window Height" }) +map("n", "", "resize -2", { desc = "Decrease Window Height" }) +map("n", "", "vertical resize -2", { desc = "Decrease Window Width" }) +map("n", "", "vertical resize +2", { desc = "Increase Window Width" }) --- WINDOWS / BUFFERS --- make splits and tabs -map("n", "", "vnew", { noremap = true }) -map("n", "", "new", { noremap = true }) -map("n", "", "vsplit", { noremap = true }) -map("n", "", "split", { noremap = true }) -map("n", "", "tabe %", { noremap = true }) -map("n", "", "tabnew", { noremap = true }) --- buffers and tabs -map("n", "", "bprev", { noremap = true }) -map("n", "", "bnext", { noremap = true }) -map("n", "", "tabprev", { noremap = true }) -map("n", "", "tabnext", { noremap = true }) --- resize windows with hjkl -map("n", "", "5<", { noremap = true }) -map("n", "", "5-", { noremap = true }) -map("n", "", "5+", { noremap = true }) -map("n", "", "5>", { noremap = true }) -- Move Lines map("v", "J", ":m '>+1gv=gv", { desc = "Move Down" }) map("v", "K", ":m '<-2gv=gv", { desc = "Move Up" }) + +-- https://github.com/mhinz/vim-galore#tips-1 +-- smarter next/prev in command line +map("n", "", "wildmenumode() ? '' : ''", { expr = true, desc = "Next" }) +map("n", "", "wildmenumode() ? '' : ''", { expr = true, desc = "Prev" }) + +-- Add undo break-points +map("i", ",", ",u") +map("i", ".", ".u") +map("i", ";", ";u") + +--keywordprg +map("n", "K", "norm! K", { desc = "Keywordprg" }) + +-- better indenting +map("v", "<", "", ">gv") +map("v", "", ">gv") +map("v", "", "Vcxnormal gccfxa", { desc = "Add Comment Below" }) +map("n", "gcO", "OVcxnormal gccfxa", { desc = "Add Comment Above" }) + +-- new file +map("n", "n", "enew", { desc = "New File" }) + +-- highlights under cursor +map("n", "ui", vim.show_pos, { desc = "Inspect Pos" }) +map("n", "uI", function() + vim.treesitter.inspect_tree() + vim.api.nvim_input("I") +end, { desc = "Inspect Tree" }) + +-- Terminal Mappings +map("n", "", "terminal", { desc = "Show Terminal" }) +map("t", "", "close", { desc = "Hide Terminal" }) +map("n", "", "terminal", { desc = "which_key_ignore" }) +map("t", "", "close", { desc = "which_key_ignore" }) + +-- windows +map("n", "", "vsplit", { desc = "Split Window Right", remap = true }) +map("n", "", "split", { desc = "Split Window Below", remap = true }) + +-- buffers +map("n", "", "bprev") +map("n", "", "bnext") + -- quickfix window -map("n", "", "lprev", { noremap = true }) -map("n", "", "lnext", { noremap = true }) ---- F keys -map("n", "", "Lazy", { noremap = true }) -map("n", "", "checkt", { noremap = true }) +map("n", "", "lprev") +map("n", "", "lnext") + +-- tabs +map("n", "l", "tablast", { desc = "Last Tab" }) +map("n", "f", "tabfirst", { desc = "First Tab" }) +map("n", "", "tabnew", { desc = "New Tab" }) +map("n", "n", "tabnext", { desc = "Next Tab" }) +map("n", "d", "tabclose", { desc = "Close Tab" }) +map("n", "p", "tabprevious", { desc = "Previous Tab" }) + +-- other +map("n", "ww", [[:cd %:p:h]], { desc = "Set Workspace To Buffer Path" }) +map("n", "o", "m`o``", { desc = "Insert Newline" }) +map("n", "\\", "n.", { noremap = true, silent = true, desc = "Repeat And Goto Next" }) +map("n", "", "Lazy", { desc = "Lazy" }) +map( + "n", + "", + "nohlsearchdiffupdatenormal! ", + { desc = "Redraw / Clear hlsearch / Diff Update / Refresh Buffers" } +) + +-- LSP +map("n", "ll", "e ~/.local/state/nvim/lsp.log") +local diagnostic_goto = function(count, severity) + severity = severity and vim.diagnostic.severity[severity] or nil + return function() vim.diagnostic.jump({ severity, float = true, count = count }) end +end +map("n", "", function() vim.diagnostic.open_float({ source = true }) end) +map("n", "", diagnostic_goto(1), { desc = "Next Diagnostic" }) +map("n", "", diagnostic_goto(-1), { desc = "Prev Diagnostic" }) +map("n", "[e", diagnostic_goto(-1, "ERROR"), { desc = "Prev Error" }) +map("n", "[w", diagnostic_goto(-1, "WARN"), { desc = "Prev Warning" }) +map("n", "]e", diagnostic_goto(1, "ERROR"), { desc = "Next Error" }) +map("n", "]w", diagnostic_goto(1, "WARN"), { desc = "Next Warning" }) +map("n", "gd", vim.lsp.buf.definition, { desc = "Goto Definition" }) +map("n", "gD", vim.lsp.buf.type_definition, { desc = "Goto Type Definition" }) +map("n", "gi", vim.lsp.buf.declaration, { desc = "Goto Declaration" }) +map("n", "gI", vim.lsp.buf.implementation, { desc = "Goto Implementation" }) +map("n", "gl", vim.diagnostic.setloclist, { desc = "Diagnostics to Location List" }) +map("n", "gr", function() vim.lsp.buf.references({ includeDeclaration = false }) end, { desc = "Goto References" }) +map({ "n", "i" }, "", vim.lsp.buf.signature_help) +map("n", "K", vim.lsp.buf.hover) +map("n", "", vim.lsp.buf.rename) +map({ "n", "x" }, "ca", vim.lsp.buf.code_action, { desc = "Code Action" }) +-- replaced by Trouble +-- map("n", "cs", vim.lsp.buf.document_symbol, { desc = "Document Symbols" }) +-- map("n", "cw", vim.lsp.buf.workspace_symbol, { desc = "Workspace Symbols" }) -- VISUALS -vim.o.guicursor = "n-v-c:block-CustomCursor,i:ver100-CustomICursor,n-v-c:blinkon0,i:blinkwait10" -- https://codeyarns.com/tech/2011-07-29-vim-chart-of-color-names.html vim.api.nvim_create_autocmd("ColorScheme", { pattern = { "*" }, @@ -157,45 +245,11 @@ vim.api.nvim_create_autocmd("BufEnter", { local function lspsetup() vim.lsp.set_log_level(2) - vim.keymap.set("n", "ll", "e ~/.local/state/nvim/lsp.log", { noremap = true }) local lspgroup = vim.api.nvim_create_augroup("lsp", { clear = true }) vim.api.nvim_create_autocmd("LspAttach", { group = lspgroup, - callback = function(ev) - vim.lsp.completion.enable(true, ev.data.client_id, ev.buf) - local diag = vim.diagnostic - local severity = diag.severity.HINT - local keyspec = { - -- workspaces - -- { "wa", vim.lsp.buf.add_workspace_folder }, - -- { "wr", vim.lsp.buf.remove_workspace_folder }, - -- { "wl", function() print(vim.inspect(vim.lsp.buf.list_workspace_folders())) end }, - -- jump - { "", function() diag.open_float({ source = true }) end }, - { "", function() diag.jump({ severity = { min = severity }, float = true, count = 1 }) end }, - { "", function() diag.jump({ severity = { min = severity }, float = true, count = -1 }) end }, - { "gd", vim.lsp.buf.definition }, - { "gD", vim.lsp.buf.type_definition }, - { "gi", vim.lsp.buf.declaration }, - { "gI", vim.lsp.buf.implementation }, - -- quickfix - { "gl", diag.setloclist }, - { "gr", function() vim.lsp.buf.references({ includeDeclaration = false }) end }, - -- popups - { "", vim.lsp.buf.signature_help, { "n", "i" } }, - -- symbols - -- { "ds", vim.lsp.buf.document_symbol }, - -- { "ws", vim.lsp.buf.workspace_symbol }, - -- other - { "K", vim.lsp.buf.hover }, - { "", vim.lsp.buf.rename }, - { "ca", vim.lsp.buf.code_action, { "n", "x" } }, - } - for _, key in ipairs(keyspec) do - vim.keymap.set(key[3] or { "n" }, key[1], key[2], { buffer = ev.buf }) - end - end, + callback = function(ev) vim.lsp.completion.enable(true, ev.data.client_id, ev.buf) end, }) vim.api.nvim_create_user_command("LspStop", function(kwargs) local name = kwargs.fargs[1] @@ -269,7 +323,7 @@ local function lspsetup() progress[client.id] = vim.tbl_filter(function(v) return table.insert(msg, v.msg) or not v.done end, p) local spinner = { "⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏" } - vim.notify(table.concat(msg, "\n"), "info", { + vim.notify(table.concat(msg, "\n"), vim.log.levels.INFO, { id = "lsp_progress", title = client.name, timeout = 1200, @@ -548,8 +602,8 @@ local function makespec_oil() view_options = { show_hidden = true }, }, keys = { - { "e", "Oil .", noremap = true }, - { "E", "Oil --float .", noremap = true }, + { "fe", "Oil .", desc = "Oil Explorer (buffer)" }, + { "ff", "Oil --float .", desc = "Oil Explorer (float)" }, }, init = function() vim.api.nvim_create_autocmd("User", { @@ -572,7 +626,7 @@ local function makespec_neotree() cmd = { "Neotree" }, dependencies = { "nvim-lua/plenary.nvim", "mini.icons", "MunifTanjim/nui.nvim" }, opts = { hijack_netrw_behavior = "disabled" }, - keys = { { "", "Neotree", noremap = true } }, + keys = { { "ft", "Neotree", desc = "Neotree Explorer (sidebar)" } }, }, } end @@ -637,8 +691,8 @@ local function makespec_vimflog() } end, keys = { - { "gl", "vertical Flogsplit -path=%" }, - { "gL", "vertical Flogsplit" }, + { "gf", "vertical Flogsplit -path=%", desc = "Git Flog File" }, + { "gc", "vertical Flogsplit", desc = "Git Flog" }, }, }, } @@ -655,8 +709,8 @@ local function makespec_diffview() "DiffviewFileHistory", }, keys = { - { "gd", "DiffviewOpen", noremap = true }, - { "gh", "DiffviewFileHistory", noremap = true }, + { "gd", "DiffviewOpen", desc = "DiffView Tab" }, + { "gh", "DiffviewFileHistory", desc = "File History Tab" }, }, } end @@ -689,9 +743,9 @@ local function makespec_fugitive() }) end, keys = { - { "", "vertical Git" }, - { "gp", "Git! push" }, - { "gP", "Git! push -f" }, + { "gg", "vertical Git", desc = "Fugitive" }, + { "gp", "Git! push", desc = "Git Push" }, + { "gP", "Git! push -f", desc = "Git Force Push" }, }, } end @@ -701,44 +755,50 @@ local function makespec_gitsigns() local gs = require("gitsigns") local function next_hunk() if vim.wo.diff then return "]c" end - vim.schedule(function() gs.next_hunk() end) + vim.schedule(function() gs.nav_hunk("next") end) return "" end local function prev_hunk() if vim.wo.diff then return "[c" end - vim.schedule(function() gs.prev_hunk() end) + vim.schedule(function() gs.nav_hunk("prev") end) return "" end - local function bmap(mode, l, r, opts) - opts = opts or {} - opts.buffer = bufnr - vim.keymap.set(mode, l, r, opts) - end + local function bmap(mode, l, r, desc) vim.keymap.set(mode, l, r, { buffer = bufnr, desc = desc }) end -- Navigation - bmap("n", "", next_hunk, { expr = true }) - bmap("n", "", prev_hunk, { expr = true }) + bmap("n", "", next_hunk, "Prev Hunk") + bmap("n", "", prev_hunk, "Next Hunk") + bmap("n", "[h", prev_hunk, "Prev Hunk") + bmap("n", "]h", next_hunk, "Next Hunk") - -- Actions - bmap("v", "gs", function() gs.stage_hunk({ vim.fn.line("."), vim.fn.line("v") }) end) - bmap("v", "gx", function() gs.reset_hunk({ vim.fn.line("."), vim.fn.line("v") }) end) - bmap("n", "gs", gs.stage_hunk) - bmap("n", "gx", gs.reset_hunk) - bmap("n", "gu", gs.undo_stage_hunk) - bmap("n", "gi", gs.preview_hunk) - bmap("n", "gb", function() gs.blame_line({ full = true }) end) - bmap("n", "gB", gs.blame) - bmap("n", "gS", gs.stage_buffer) - bmap("n", "gX", gs.reset_buffer) - bmap("n", "td", gs.toggle_deleted) - bmap("n", "tl", gs.toggle_linehl) - bmap("n", "tb", gs.toggle_current_line_blame) - bmap("n", "th", gs.toggle_word_diff) - bmap("n", "tn", gs.toggle_numhl) + -- Blame + bmap("n", "gB", gs.blame, "Blame Buffer") + bmap("n", "gb", function() gs.blame_line({ full = true }) end, "Blame Line") - -- Text object - bmap({ "o", "x" }, "ih", "Gitsigns select_hunk") + -- Hunk + bmap("n", "hp", gs.preview_hunk_inline, "Preview Hunk Inline") + bmap("n", "hi", gs.preview_hunk, "Preview Hunk") + bmap("n", "hq", gs.setqflist, "File Hunks to QuickFix") + bmap("n", "hQ", function() gs.setqflist("all") end, "All Hunks to QuickFix") + bmap("n", "hx", gs.reset_hunk, "Reset Hunk") + bmap("v", "hx", function() gs.reset_hunk({ vim.fn.line("."), vim.fn.line("v") }) end, "Reset Hunk") + bmap("n", "hR", gs.reset_buffer, "Reset Buffer") + bmap("n", "hs", gs.stage_hunk, "Stage Hunk") + bmap("v", "hs", function() gs.stage_hunk({ vim.fn.line("."), vim.fn.line("v") }) end, "Stage Hunk") + bmap("n", "hS", gs.stage_buffer, "Stage Buffer") + bmap("n", "hu", gs.undo_stage_hunk, "Undo Stage Hunk") + bmap({ "n", "v" }, "hv", gs.select_hunk, "Select Hunk") + + -- Toggles + bmap("n", "hd", gs.toggle_deleted, "Toggle Show Deleted Lines") + bmap("n", "hl", gs.toggle_linehl, "Toggle Diff Line Highlight") + bmap("n", "hb", gs.toggle_current_line_blame, "Toggle Line Blame") + bmap("n", "hh", gs.toggle_word_diff, "Toggle Diff Word Colors") + bmap("n", "hn", gs.toggle_numhl, "Toggle Diff Line Number Highlight") + + -- Text object, e.g. for dih to delete hunk + bmap({ "o", "x" }, "ih", "Gitsigns select_hunk") end return { @@ -770,7 +830,66 @@ local function makespec_gitsigns() } end +local function makespec_whichkey() + return { + "folke/which-key.nvim", + event = "VeryLazy", + opts = { + defaults = {}, + spec = { + { + mode = { "n", "v" }, + { "c", group = "code/content" }, + { "f", group = "file/find" }, + { "g", group = "git" }, + { "h", group = "hunks" }, + { "l", group = "logs" }, + { "p", group = "autoformat" }, + { "s", group = "search" }, + { "u", group = "ui", icon = { icon = "󰙵 ", color = "cyan" } }, + { "[", group = "prev" }, + { "]", group = "next" }, + { "g", group = "goto" }, + { "gs", group = "surround" }, + { "z", group = "fold" }, + { "", group = "tabs" }, + { + "w", + group = "windows", + proxy = "", + expand = function() return require("which-key.extras").expand.win() end, + }, + -- better descriptions + { "gx", desc = "Open with system app" }, + }, + }, + }, + keys = { + { + "?", + function() require("which-key").show({ global = false }) end, + desc = "Buffer Keymaps (which-key)", + }, + { + "", + function() require("which-key").show({ keys = "", loop = true }) end, + desc = "Window Hydra Mode (which-key)", + }, + }, + config = function(_, opts) + local wk = require("which-key") + wk.setup(opts) + end, + } +end + local function makespec_snacks() + local function term_nav(dir) + ---@param self snacks.terminal + return function(self) + return self:is_floating() and "" or vim.schedule(function() vim.cmd.wincmd(dir) end) + end + end return { "folke/snacks.nvim", priority = 1000, @@ -793,6 +912,7 @@ local function makespec_snacks() end, }, bufdelete = { enabled = true }, + debug = { enabled = true }, image = { enabled = true }, indent = { enabled = true }, lazygit = { enabled = vim.fn.has("lazygit") == 1 }, @@ -809,39 +929,85 @@ local function makespec_snacks() }, quickfile = { enabled = true }, rename = { enabled = true }, + scope = { enabled = true }, + terminal = { + win = { + keys = { + nav_h = { "", term_nav("h"), desc = "Go to Left Window", expr = true, mode = "t" }, + nav_j = { "", term_nav("j"), desc = "Go to Lower Window", expr = true, mode = "t" }, + nav_k = { "", term_nav("k"), desc = "Go to Upper Window", expr = true, mode = "t" }, + nav_l = { "", term_nav("l"), desc = "Go to Right Window", expr = true, mode = "t" }, + }, + }, + }, + toggle = { enabled = true }, + words = { enabled = true }, }, -- stylua: ignore keys = { - { "R", function() Snacks.rename.rename_file() end, desc = "Rename File" }, - { "", function() Snacks.bufdelete() end, desc = "Delete Buffer" }, - { "G", function() Snacks.lazygit() end, desc = "Launch Lazygit" }, + { "fr", function() Snacks.rename.rename_file() end, desc = "Rename File" }, + { "d", function() Snacks.bufdelete() end, desc = "Delete Buffer" }, + { "gl", function() Snacks.lazygit() end, desc = "Launch Lazygit" }, { ".", function() Snacks.scratch.open() end, desc = "Scratch Buffer" }, -- find { "", function() Snacks.picker.git_files() end, desc = "Find Git Files" }, - { "", function() Snacks.picker.files() end, desc = "Find Files" }, - { "", function() Snacks.picker.buffers() end, desc = "Find Buffers" }, - { "d", function() Snacks.picker.files({ cwd = "/home/hjalmarlucius/dotfiles" }) end, desc = "Find Config" }, - { "n", function() Snacks.picker.files({ cwd = "/home/hjalmarlucius/notes" }) end, desc = "Find Note", }, + { "fg", function() Snacks.picker.git_files() end, desc = "Find Git Files" }, + { "fa", function() Snacks.picker.files() end, desc = "Find Files" }, + { "fc", function() Snacks.picker.files({ cwd = "/home/hjalmarlucius/dotfiles" }) end, desc = "Find Config" }, + { "fn", function() Snacks.picker.files({ cwd = "/home/hjalmarlucius/notes" }) end, desc = "Find Note", }, + -- logs + { "lm", function() Snacks.picker.notifications() end, desc = "Notification History" }, + -- code + { "cS", function() Snacks.picker.lsp_symbols() end, desc = "LSP Symbols" }, + -- replaced by Trouble + -- { "cW", function() Snacks.picker.lsp_workspace_symbols() end, desc = "LSP Workspace Symbols" }, + -- { "cd", function() Snacks.picker.diagnostics() end, desc = "Diagnostics" }, + -- terminal + { "", function() Snacks.terminal.toggle() end, desc = "Snacks Terminal", mode={"n", "t"} }, + { "", function() Snacks.terminal.toggle() end, desc = "which_key_ignore", mode={'n', "t"} }, -- search - { "", function() Snacks.picker.help() end, desc = "Help Pages" }, + { "", function() Snacks.picker.help() end, desc = "Help Pages" }, { "", function() Snacks.picker.colorschemes() end, desc = "Colorschemes" }, - { "", function() Snacks.picker.grep() end, desc = "Grep" }, + { "", function() Snacks.picker.grep() end, desc = "Grep" }, { "*", function() Snacks.picker.grep_word() end, desc = "Visual selection or word", mode = { "n", "x" }, }, { "/", function() Snacks.picker.search_history() end, desc = "Search History" }, - { "b", function() Snacks.picker.lines() end, desc = "Grep Buffer" }, - { "B", function() Snacks.picker.grep_buffers() end, desc = "Grep Buffers" }, - { "D", function() Snacks.picker.grep({ cwd = "/home/hjalmarlucius/dotfiles" }) end, desc = "Find Config Content" }, - { "N", function() Snacks.picker.grep({ cwd = "/home/hjalmarlucius/notes" }) end, desc = "Find Notes Content", }, - { "i", function() Snacks.picker.diagnostics() end, desc = "Diagnostics" }, - { "l", function() Snacks.picker.loclist() end, desc = "Location List" }, - { "h", function() Snacks.picker.notifications() end, desc = "Notification History" }, - { "p", function() Snacks.picker.projects() end, desc = "Find Projects" }, - { "q", function() Snacks.picker.qflist() end, desc = "Quickfix List" }, - { "ø", function() Snacks.picker.command_history() end, desc = "Command History" }, - { "ss", function() Snacks.picker.lsp_symbols() end, desc = "LSP Symbols" }, - { "sS", function() Snacks.picker.lsp_workspace_symbols() end, desc = "LSP Workspace Symbols" }, - { "u", function() Snacks.picker.undo() end, desc = "Undo History" }, + { ";", function() Snacks.picker.command_history() end, desc = "Command History" }, + { "sB", function() Snacks.picker.grep_buffers() end, desc = "Grep Buffers" }, + { "sb", function() Snacks.picker.lines() end, desc = "Grep Buffer" }, + { "sc", function() Snacks.picker.grep({ cwd = "/home/hjalmarlucius/dotfiles" }) end, desc = "Grep Configs" }, + { "sl", function() Snacks.picker.loclist() end, desc = "Location List" }, + { "sn", function() Snacks.picker.grep({ cwd = "/home/hjalmarlucius/notes" }) end, desc = "Grep Notes", }, + { "sp", function() Snacks.picker.projects() end, desc = "Find Projects" }, + { "sq", function() Snacks.picker.qflist() end, desc = "Quickfix List" }, + { "su", function() Snacks.picker.undo() end, desc = "Undo History" }, }, + init = function() + vim.api.nvim_create_autocmd("User", { + pattern = "VeryLazy", + callback = function() + -- Setup some globals for debugging (lazy-loaded) + _G.dd = function(...) Snacks.debug.inspect(...) end + _G.bt = function() Snacks.debug.backtrace() end + vim.print = _G.dd -- Override print to use snacks for `:=` command + + Snacks.toggle.indent():map("u") + Snacks.toggle + .option("background", { off = "light", on = "dark", name = "Dark Background" }) + :map("ub") + Snacks.toggle + .option("conceallevel", { off = 0, on = vim.o.conceallevel > 0 and vim.o.conceallevel or 2 }) + :map("uc") + Snacks.toggle.diagnostics():map("ud") + Snacks.toggle.dim():map("uD") + Snacks.toggle.inlay_hints():map("ui") + Snacks.toggle.line_number():map("ul") + Snacks.toggle.option("relativenumber", { name = "Relative Number" }):map("uL") + Snacks.toggle.option("spell", { name = "Spelling" }):map("us") + Snacks.toggle.treesitter():map("ut") + Snacks.toggle.option("wrap", { name = "Wrap" }):map("uw") + end, + }) + end, } end @@ -856,6 +1022,55 @@ local function makespecs_mini() } end +local function makespec_trouble() + return { + "folke/trouble.nvim", + cmd = { "Trouble" }, + opts = { + modes = { + lsp = { win = { position = "right", size = 100 } }, + diagnostics = { win = { position = "right", size = 100 } }, + symbols = { win = { position = "right", size = 100 } }, + loclist = { win = { position = "right", size = 100 } }, + qflist = { win = { position = "right", size = 100 } }, + }, + }, + -- TODO FIX + keys = { + { "cc", "Trouble diagnostics toggle filter.buf=0", desc = "Buffer Diagnostics" }, + { "cd", "Trouble diagnostics toggle", desc = "Diagnostics" }, + { "cr", "Trouble lsp_references toggle", desc = "References" }, + { "cs", "Trouble symbols toggle", desc = "Document Symbols" }, + { "ca", "Trouble lsp toggle", desc = "LSP references/definitions/..." }, + { "cl", "Trouble loclist toggle", desc = "Location List" }, + { "cq", "Trouble qflist toggle", desc = "Quickfix List" }, + { + "[x", + function() + if require("trouble").is_open() then + require("trouble").prev({ skip_groups = true, jump = true }) + else + local ok, err = pcall(vim.cmd.cprev) + if not ok then vim.notify(err, vim.log.levels.ERROR) end + end + end, + desc = "Previous Trouble/Quickfix Item", + }, + { + "]x", + function() + if require("trouble").is_open() then + require("trouble").next({ skip_groups = true, jump = true }) + else + local ok, err = pcall(vim.cmd.cnext) + if not ok then vim.notify(err, vim.log.levels.ERROR) end + end + end, + desc = "Next Trouble/Quickfix Item", + }, + }, + } +end local function makespec_todocomments() return { "folke/todo-comments.nvim", @@ -885,7 +1100,16 @@ local function makespec_todocomments() default = { "#91D0C1" }, }, }, - keys = { { "", "TodoQuickFix", noremap = true } }, + keys = { + { "]t", function() require("todo-comments").jump_next() end, desc = "Next Todo Comment" }, + { "[t", function() require("todo-comments").jump_prev() end, desc = "Previous Todo Comment" }, + { "ct", "Trouble todo toggle", desc = "Comments list" }, + { + "cT", + "Trouble todo toggle filter = {tag = {TODO,FIX,FIXME}}", + desc = "Todo/Fix/Fixme list", + }, + }, } end @@ -913,7 +1137,7 @@ local function makespec_mason() "williamboman/mason.nvim", lazy = false, opts = {}, - keys = { { "", "Mason", noremap = true } }, + keys = { { "", "Mason", desc = "Mason" } }, } end @@ -948,7 +1172,7 @@ local function makespec_grugfar() cmd = "GrugFar", keys = { { - "r", + "sr", function() local grug = require("grug-far") local ext = vim.bo.buftype == "" and vim.fn.expand("%:e") @@ -986,15 +1210,7 @@ local function makespec_treesitter() auto_install = true, highlight = { enable = true }, indent = { enable = true, disable = { "python" }, additional_vim_regex_highlighting = { "python" } }, - incremental_selection = { - enable = true, - keymaps = { - init_selection = "gnn", - node_decremental = "", - node_incremental = "", - scope_incremental = "", - }, - }, + -- incremental_selection done by flash plugin }, }, config = function() vim.opt.foldexpr = "nvim_treesitter#foldexpr()" end, @@ -1013,20 +1229,8 @@ local function makespec_hlslens() { "#", [[(asterisk-z#)lua require('hlslens').start()]], mode = { "n", "x" }, {} }, { "g*", [[(asterisk-gz*)lua require('hlslens').start()]], mode = { "n", "x" }, {} }, { "g#", [[(asterisk-gz#)lua require('hlslens').start()]], mode = { "n", "x" }, {} }, - { - "n", - [[nlua require('hlslens').start()]], - mode = { "n", "x" }, - noremap = true, - silent = true, - }, - { - "N", - [[Nlua require('hlslens').start()]], - mode = { "n", "x" }, - noremap = true, - silent = true, - }, + { "n", [[nlua require('hlslens').start()]], mode = { "n", "x" }, noremap = true, silent = true }, + { "N", [[Nlua require('hlslens').start()]], mode = { "n", "x" }, noremap = true, silent = true }, }, init = function() vim.g["asterisk#keeppos"] = 1 end, } @@ -1064,8 +1268,8 @@ local function makespec_conform() lazy = true, cmd = { "ConformInfo" }, keys = { - { "f", function() require("conform").format() end, silent = true, noremap = true }, - { "lf", "e ~/.local/state/nvim/conform.log", noremap = true }, + { "p", function() require("conform").format() end, silent = true, desc = "Autoformat" }, + { "lp", "e ~/.local/state/nvim/conform.log", desc = "Conform log" }, }, opts = { formatters_by_ft = { @@ -1140,6 +1344,14 @@ local function makespec_noice() { filter = { kind = "", min_height = 2 }, view = "split" }, }, }, + keys = { + { "ld", function() require("noice").cmd("dismiss") end, desc = "Noice dismiss" }, + { "le", function() require("noice").cmd("errors") end, desc = "Noice errors" }, + { "lh", function() require("noice").cmd("history") end, desc = "Noice history" }, + { "ls", function() require("noice").cmd("stats") end, desc = "Noice stats" }, + { "un", function() require("noice").cmd("enable") end, desc = "Enable Noice" }, + { "uN", function() require("noice").cmd("disable") end, desc = "Disable Noice" }, + }, } end @@ -1160,10 +1372,12 @@ for _, spec in ipairs({ makespec_conform(), -- autoformat makespec_treesitter(), makespec_todocomments(), + makespec_trouble(), makespec_autotag(), makespec_lint(), makespec_mason(), -- navigation + makespec_whichkey(), makespec_tmuxnav(), makespec_hlslens(), makespec_flash(),