require('snacks').setup({ animate = { enabled = false, duration = { step = 1, total = 1 }, easing = "linear", }, bigfile = { enabled = true }, dashboard = { enabled = false }, explorer = { enabled = false }, image = { enabled = false, inline = false, scale = 3, -- nil | 1 (default) | 2 | 3 | ... doc = { inline = true, enabled = true, max_width = nil, max_height = nil, conceal = true, }, math = { enabled = true, } }, terminal = { bo = { filetype = "snacks_terminal", }, win = { style = "terminal" }, wo = {}, keys = { q = "hide", gf = function(self) local f = vim.fn.findfile(vim.fn.expand(""), "**") if f == "" then Snacks.notify.warn("No file under cursor") else self:hide() vim.schedule(function() vim.cmd("e " .. f) end) end end, -- term_normal = { -- "", -- function(self) -- self.esc_timer = self.esc_timer or (vim.uv or vim.loop).new_timer() -- if self.esc_timer:is_active() then -- self.esc_timer:stop() -- vim.cmd("stopinsert") -- else -- self.esc_timer:start(250, 0, function() end) -- return "" -- end -- end, -- mode = "t", -- expr = true, -- desc = "Double escape to normal mode", -- }, }, }, indent = { enabled = false }, notifier = { enabled = true, timeout = 1000, }, picker = { enabled = true, layout = { preset = "ivy", layout = { position = "bottom" } }, frecency = true, history_bonus = true, projects = { dev = { "~/Projects", }, }, actions = { flash = function(picker) require("flash").jump({ pattern = "^", label = { after = { 0, 0 } }, search = { mode = "search", exclude = { function(win) return vim.bo[vim.api.nvim_win_get_buf(win)].filetype ~= "snacks_picker_list" end, }, }, action = function(match) local idx = picker.list:row2idx(match.pos[1]) picker.list:_move(idx, true, true) end, }) end, }, win = { input = { keys = { [''] = { 'layout_right', mode = { 'i', 'n' } }, [""] = { "flash", mode = { "n", "i" } }, ["s"] = { "flash" }, }, }, }, sources = { files = { -- add a custom action actions = { create_if_missing = function(picker, item) -- When typing in the input, item may be nil. -- We'll use the input text as the intended file path. local input = picker.input and picker.input:get() or "" if input == "" then return end -- Make it relative to picker cwd if it’s not absolute local cwd = picker.opts.cwd or vim.loop.cwd() local path = input if not path:match("^/") and not path:match("^%a:[/\\]") then path = cwd .. "/" .. path end -- Normalize path (optional) path = vim.fn.fnamemodify(path, ":p") -- If file exists, just open it if vim.loop.fs_stat(path) then picker:close() vim.cmd.edit(path) return end -- Ensure parent dirs exist (optional but nice) vim.fn.mkdir(vim.fn.fnamemodify(path, ":h"), "p") -- Open a new buffer at that path (creates buffer even if file missing) picker:close() vim.cmd.edit(path) -- At this point buffer is new + unnamed-on-disk until you :w end, }, -- bind the action to a key in the picker UI win = { input = { keys = { [""] = { "create_if_missing", mode = { "i", "n" }, desc = "Create file from input" }, }, }, list = { keys = { [""] = { "create_if_missing", mode = { "n" }, desc = "Create file from input" }, }, }, }, }, }, }, scope = { enabled = false }, scratch = { ft = "markdown", }, statuscolumn = { enabled = true }, styles = { notification = { -- wo = { wrap = true } -- Wrap notifications } } }) vim.keymap.set('n', "o/", function() Snacks.picker.grep({dirs = { os.getenv("HOME") .. "/Documents/notes" }}) end, { desc = "Search Org Files" }) vim.keymap.set('n', "", function() Snacks.picker.smart() end, { desc = "Smart Find Files" }) vim.keymap.set('n', "j", function() Snacks.picker.files({args = { "--no-require-git" }}) end, { desc = "Find Files" }) vim.keymap.set('n', ",", function() Snacks.picker.buffers() end, { desc = "Buffers" }) vim.keymap.set('n', "/", function() Snacks.picker.grep() end, { desc = "Grep" }) vim.keymap.set('n', ":", function() Snacks.picker.command_history() end, { desc = "Command History" }) vim.keymap.set('n', "n", function() Snacks.picker.notifications() end, { desc = "Notification History" }) vim.keymap.set('n', "i", function() Snacks.picker.lsp_symbols() end, { desc = "Symbols" }) vim.keymap.set('n', "I", function() Snacks.picker.lsp_workspace_symbols() end, { desc = "LSP Workspace Symbols" }) vim.keymap.set('n', "fb", function() Snacks.picker.buffers() end, { desc = "Buffers" }) vim.keymap.set('n', "fc", function() Snacks.picker.files({ cwd = vim.fn.stdpath("config") }) end, { desc = "Find Config File" }) vim.keymap.set('n', "ff", function() Snacks.picker.files() end, { desc = "Find Files" }) vim.keymap.set('n', "fg", function() Snacks.picker.git_files() end, { desc = "Find Git Files" }) vim.keymap.set('n', "fp", function() Snacks.picker.projects() end, { desc = "Projects" }) vim.keymap.set('n', "fr", function() Snacks.picker.recent() end, { desc = "Recent" }) vim.keymap.set('n', "gb", function() Snacks.picker.git_branches() end, { desc = "Git Branches" }) vim.keymap.set('n', "gl", function() Snacks.picker.git_log() end, { desc = "Git Log" }) vim.keymap.set('n', "gL", function() Snacks.picker.git_log_line() end, { desc = "Git Log Line" }) vim.keymap.set('n', "gs", function() Snacks.picker.git_status() end, { desc = "Git Status" }) vim.keymap.set('n', "gS", function() Snacks.picker.git_stash() end, { desc = "Git Stash" }) vim.keymap.set('n', "gd", function() Snacks.picker.git_diff() end, { desc = "Git Diff (Hunks)" }) vim.keymap.set('n', "gf", function() Snacks.picker.git_log_file() end, { desc = "Git Log File" }) vim.keymap.set('n', "sb", function() Snacks.picker.lines() end, { desc = "Buffer Lines" }) vim.keymap.set('n', "sB", function() Snacks.picker.grep_buffers() end, { desc = "Grep Open Buffers" }) vim.keymap.set('n', "sg", function() Snacks.picker.grep() end, { desc = "Grep" }) vim.keymap.set('n', 's"', function() Snacks.picker.registers() end, { desc = "Registers" }) vim.keymap.set('n', 's/', function() Snacks.picker.search_history() end, { desc = "Search History" }) vim.keymap.set('n', "sa", function() Snacks.picker.autocmds() end, { desc = "Autocmds" }) vim.keymap.set('n', "sb", function() Snacks.picker.lines() end, { desc = "Buffer Lines" }) vim.keymap.set('n', "sc", function() Snacks.picker.command_history() end, { desc = "Command History" }) vim.keymap.set('n', "sC", function() Snacks.picker.commands() end, { desc = "Commands" }) vim.keymap.set('n', "sd", function() Snacks.picker.diagnostics() end, { desc = "Diagnostics" }) vim.keymap.set('n', "sD", function() Snacks.picker.diagnostics_buffer() end, { desc = "Buffer Diagnostics" }) vim.keymap.set('n', "sh", function() Snacks.picker.help() end, { desc = "Help Pages" }) vim.keymap.set('n', "sH", function() Snacks.picker.highlights() end, { desc = "Highlights" }) vim.keymap.set('n', "si", function() Snacks.picker.icons() end, { desc = "Icons" }) vim.keymap.set('n', "sj", function() Snacks.picker.jumps() end, { desc = "Jumps" }) vim.keymap.set('n', "sk", function() Snacks.picker.keymaps() end, { desc = "Keymaps" }) vim.keymap.set('n', "sl", function() Snacks.picker.loclist() end, { desc = "Location List" }) vim.keymap.set('n', "sm", function() Snacks.picker.marks() end, { desc = "Marks" }) vim.keymap.set('n', "sM", function() Snacks.picker.man() end, { desc = "Man Pages" }) -- vim.keymap.set('n', "sp", function() Snacks.picker.lazy() end, { desc = "Search for Plugin Spec" }) vim.keymap.set('n', "sq", function() Snacks.picker.qflist() end, { desc = "Quickfix List" }) vim.keymap.set('n', "sR", function() Snacks.picker.resume() end, { desc = "Resume" }) vim.keymap.set('n', "su", function() Snacks.picker.undo() end, { desc = "Undo History" }) vim.keymap.set('n', "sz", function() Snacks.picker.zoxide() end, { desc = "Zoxide" }) vim.keymap.set('n', "uC", function() Snacks.picker.colorschemes() end, { desc = "Colorschemes" }) vim.keymap.set('n', "gd", function() Snacks.picker.lsp_definitions() end, { desc = "Goto Definition" }) vim.keymap.set('n', "gD", function() Snacks.picker.lsp_declarations() end, { desc = "Goto Declaration" }) vim.keymap.set('n', "gri", function() Snacks.picker.lsp_implementations() end, { desc = "Goto Implementation" }) vim.keymap.set('n', "gy", function() Snacks.picker.lsp_type_definitions() end, { desc = "Goto T[y]pe Definition" }) vim.keymap.set('n', "ss", function() Snacks.picker.lsp_symbols() end, { desc = "LSP Symbols" }) vim.keymap.set('n', "sS", function() Snacks.picker.lsp_workspace_symbols() end, { desc = "LSP Workspace Symbols" }) vim.keymap.set('n', "Z", function() Snacks.zen() end, { desc = "Toggle Zen Mode" }) vim.keymap.set('n', "z", function() Snacks.zen.zoom() end, { desc = "Toggle Zoom" }) vim.keymap.set('n', ".", function() Snacks.scratch() end, { desc = "Toggle Scratch Buffer" }) vim.keymap.set('n', "S", function() Snacks.scratch.select() end, { desc = "Select Scratch Buffer" }) vim.keymap.set('n', "bd", function() Snacks.bufdelete() end, { desc = "Delete Buffer" }) vim.keymap.set('n', "bR", function() Snacks.rename.rename_file() end, { desc = "Rename File" }) vim.keymap.set('n', "gg", function() Snacks.lazygit() end, { desc = "Lazygit" }) vim.keymap.set('n', "un", function() Snacks.notifier.hide() end, { desc = "Dismiss All Notifications" }) vim.keymap.set('n', "grr", function() Snacks.picker.lsp_references() end, { nowait = true, desc = "References" }) vim.keymap.set({ "n", "x" }, "sw", function() Snacks.picker.grep_word() end, { desc = "Visual selection or word" }) vim.keymap.set({ "n", "v" }, "gB", function() Snacks.gitbrowse() end, { desc = "Git Browse" }) vim.keymap.set({ "n", "t" }, "", function() Snacks.terminal.toggle() end, { desc = "Toggle Terminal" }) vim.keymap.set({ "n", "t" }, "]]", function() Snacks.words.jump(vim.v.count1) end, { desc = "Next Reference" }) vim.keymap.set({ "n", "t" }, "[[", function() Snacks.words.jump(-vim.v.count1) end, { desc = "Prev Reference" }) vim.keymap.set('n', 'xN', function() Snacks.win({ file = vim.api.nvim_get_runtime_file("doc/news.txt", false)[1], width = 0.6, height = 0.6, wo = { spell = false, wrap = false, signcolumn = "yes", statuscolumn = " ", conceallevel = 3, }, }) end, { desc = "Neovim News" }) vim.api.nvim_create_autocmd("User", { 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 -- Create some toggle mappings Snacks.toggle.option("spell", { name = "Spelling" }):map("us") Snacks.toggle.option("wrap", { name = "Wrap" }):map("uw") Snacks.toggle.option("relativenumber", { name = "Relative Number" }):map("uL") Snacks.toggle.diagnostics():map("ud") Snacks.toggle.line_number():map("ul") Snacks.toggle.option("conceallevel", { off = 0, on = vim.o.conceallevel > 0 and vim.o.conceallevel or 2 }):map("uc") Snacks.toggle.treesitter():map("uT") Snacks.toggle.option("background", { off = "light", on = "dark", name = "Dark Background" }):map("ub") Snacks.toggle.inlay_hints():map("uh") Snacks.toggle.indent():map("ug") Snacks.toggle.dim():map("uD") end, })