snacks.lua (8107B)
1 local function symbols() 2 local server_ready = not not vim.lsp.buf_notify(0, '$/progress', {}) 3 if server_ready then 4 Snacks.picker.lsp_symbols() 5 else 6 Snacks.picker.treesitter() 7 end 8 end 9 10 local keys = { 11 -- Top Pickers & Explorer 12 { "<leader>s<space>", function() Snacks.picker.smart() end, desc = "Smart Find Files" }, 13 { "<leader>b", function() Snacks.picker.buffers() end, desc = "Buffers" }, 14 { "<leader>sg", function() Snacks.picker.grep() end, desc = "Grep" }, 15 { "<leader>s;", function() Snacks.picker.command_history() end, desc = "Command History" }, 16 { "<leader>sn", function() Snacks.picker.notifications() end, desc = "Notification History" }, 17 { "<leader>f", function() Snacks.picker.explorer() end, desc = "Explorer" }, 18 -- find 19 { "<leader>sc", function() Snacks.picker.files({ cwd = vim.fn.stdpath("config") }) end, desc = "Find Config File" }, 20 { "<leader>sf", function() Snacks.picker.files() end, desc = "Find Files" }, 21 { "<leader>sv", function() Snacks.picker.git_files() end, desc = "Find Git Files" }, 22 { "<leader>sP", function() Snacks.picker.projects() end, desc = "Projects" }, 23 { "<leader>sp", function() Snacks.picker.recent() end, desc = "Recent" }, 24 -- git 25 { "<leader>gb", function() Snacks.picker.git_branches() end, desc = "Git Branches" }, 26 { "<leader>gl", function() Snacks.picker.git_log() end, desc = "Git Log" }, 27 { "<leader>gL", function() Snacks.picker.git_log_line() end, desc = "Git Log Line" }, 28 { "<leader>gs", function() Snacks.picker.git_status() end, desc = "Git Status" }, 29 { "<leader>gS", function() Snacks.picker.git_stash() end, desc = "Git Stash" }, 30 { "<leader>gd", function() Snacks.picker.git_diff() end, desc = "Git Diff (Hunks)" }, 31 { "<leader>gf", function() Snacks.picker.git_log_file() end, desc = "Git Log File" }, 32 -- Grep 33 { "<leader>sb", function() Snacks.picker.lines() end, desc = "Buffer Lines" }, 34 { "<leader>sB", function() Snacks.picker.grep_buffers() end, desc = "Grep Open Buffers" }, 35 { "<leader>sg", function() Snacks.picker.grep() end, desc = "Grep" }, 36 { "<leader>sw", function() Snacks.picker.grep_word() end, desc = "Visual selection or word", mode = { "n", "x" } }, 37 -- search 38 { '<leader>s"', function() Snacks.picker.registers() end, desc = "Registers" }, 39 { '<leader>s/', function() Snacks.picker.search_history() end, desc = "Search History" }, 40 { "<leader>sa", function() Snacks.picker.autocmds() end, desc = "Autocmds" }, 41 { "<leader>sb", function() Snacks.picker.lines() end, desc = "Buffer Lines" }, 42 { "<leader>sC", function() Snacks.picker.commands() end, desc = "Commands" }, 43 { "<leader>sd", function() Snacks.picker.diagnostics() end, desc = "Diagnostics" }, 44 { "<leader>sD", function() Snacks.picker.diagnostics_buffer() end, desc = "Buffer Diagnostics" }, 45 { "<leader>sh", function() Snacks.picker.help() end, desc = "Help Pages" }, 46 { "<leader>sH", function() Snacks.picker.highlights() end, desc = "Highlights" }, 47 { "<leader>si", function() Snacks.picker.icons() end, desc = "Icons" }, 48 { "<leader>sj", function() Snacks.picker.jumps() end, desc = "Jumps" }, 49 { "<leader>sk", function() Snacks.picker.keymaps() end, desc = "Keymaps" }, 50 { "<leader>sl", function() Snacks.picker.loclist() end, desc = "Location List" }, 51 { "<leader>sm", function() Snacks.picker.marks() end, desc = "Marks" }, 52 { "<leader>sM", function() Snacks.picker.man() end, desc = "Man Pages" }, 53 { "<leader>sq", function() Snacks.picker.qflist() end, desc = "Quickfix List" }, 54 { "<leader>sR", function() Snacks.picker.resume() end, desc = "Resume" }, 55 { "<leader>su", function() Snacks.picker.undo() end, desc = "Undo History" }, 56 { "<leader>uC", function() Snacks.picker.colorschemes() end, desc = "Colorschemes" }, 57 -- LSP 58 { "gd", function() Snacks.picker.lsp_definitions() end, desc = "Goto Definition" }, 59 { "gD", function() Snacks.picker.lsp_declarations() end, desc = "Goto Declaration" }, 60 { "<leader>sr", function() Snacks.picker.lsp_references() end, nowait = true, desc = "References" }, 61 { "gI", function() Snacks.picker.lsp_implementations() end, desc = "Goto Implementation" }, 62 { "gy", function() Snacks.picker.lsp_type_definitions() end, desc = "Goto T[y]pe Definition" }, 63 { "<leader>ss", symbols, desc = "LSP Symbols" }, 64 { "<leader>sS", function() Snacks.picker.lsp_workspace_symbols() end, desc = "LSP Workspace Symbols" }, 65 -- Other 66 } 67 68 ---@type table<number, {token:lsp.ProgressToken, msg:string, done:boolean}[]> 69 local progress = vim.defaulttable() 70 vim.api.nvim_create_autocmd("LspProgress", { 71 desc = 'Show LSP loading progress', 72 group = vim.api.nvim_create_augroup('LspProgress', { clear = true }), 73 74 ---@param ev {data: {client_id: integer, params: lsp.ProgressParams}} 75 callback = function(ev) 76 local client = vim.lsp.get_client_by_id(ev.data.client_id) 77 local value = ev.data.params 78 .value --[[@as {percentage?: number, title?: string, message?: string, kind: "begin" | "report" | "end"}]] 79 if not client or type(value) ~= "table" then 80 return 81 end 82 local p = progress[client.id] 83 84 for i = 1, #p + 1 do 85 if i == #p + 1 or p[i].token == ev.data.params.token then 86 p[i] = { 87 token = ev.data.params.token, 88 msg = ("[%3d%%] %s%s"):format( 89 value.kind == "end" and 100 or value.percentage or 100, 90 value.title or "", 91 value.message and (" **%s**"):format(value.message) or "" 92 ), 93 done = value.kind == "end", 94 } 95 break 96 end 97 end 98 99 local msg = {} ---@type string[] 100 progress[client.id] = vim.tbl_filter(function(v) 101 return table.insert(msg, v.msg) or not v.done 102 end, p) 103 104 local spinner = { "⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏" } 105 vim.notify(table.concat(msg, "\n"), "info", { 106 id = "lsp_progress", 107 title = client.name, 108 opts = function(notif) 109 notif.icon = #progress[client.id] == 0 and " " 110 or spinner[math.floor(vim.uv.hrtime() / (1e6 * 80)) % #spinner + 1] 111 end, 112 }) 113 end, 114 }) 115 116 return { 117 "folke/snacks.nvim", 118 priority = 1000, 119 lazy = false, 120 ---@type snacks.Config 121 opts = { 122 picker = {}, 123 animate = {}, 124 notifier = {}, 125 indent = { 126 enabled = true, 127 indent = { 128 char = '┊', 129 } 130 }, 131 }, 132 keys = keys, 133 }