config(nvim): add AstroNvim config; font: VictorMono NF via packages

nvim added static from live home; vendored .git/tool-state dirs removed
and ignore-gated against re-add. ttf-victor-mono-nerd (arch) and
font-victor-mono-nerd-font cask (darwin) added to packages manifest.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Prad NukalaandClaude Fable 5 committed 2026-08-09 14:52:19 -04:00
1 parent e26ae266b9
commit f30802426d
31 files changed
+1692 -2

No files matched your search

+456
View File
@@ -0,0 +1,456 @@
--- AstroCore configuration (AstroNvim v6 / Neovim 0.12)
--- Core settings, keymappings, and autocmds
--- @module plugins.astrocore
local ignore_patterns = require "config.ignore_patterns"
local file_filter = ignore_patterns.create_picker_filter()
-- Open a snacks picker with trouble.nvim send-to-quickfix action bound to <C-t>.
local function with_trouble(source, opts)
opts = opts or {}
opts.actions = require("trouble.sources.snacks").actions
opts.win = opts.win or {}
opts.win.input = opts.win.input or {}
opts.win.input.keys = vim.tbl_extend("force", opts.win.input.keys or {}, {
["<c-t>"] = { "trouble_open", mode = { "n", "i" } },
})
require("snacks").picker[source](opts)
end
return {
"AstroNvim/astrocore",
---@type AstroCoreOpts
opts = {
sessions = {
autosave = {
last = true,
cwd = true,
},
ignore = {
dirs = {},
filetypes = { "gitcommit", "gitrebase" },
buftypes = {},
},
},
rooter = {
detector = {
"lsp",
{ ".git", "_darcs", ".hg", ".bzr", ".svn" },
{
"package.json",
"lua",
"Cargo.toml",
"Pipfile",
"docs.json",
},
},
ignore = {
servers = { "golangci_lint_ls" },
dirs = {},
},
autochdir = true,
scope = "global",
notify = false,
},
-- v6: features schema changed
-- diagnostics_mode (0-3) -> diagnostics = { virtual_text, virtual_lines }
-- large_buf and cmp are new keys
features = {
large_buf = { size = 1024 * 256, lines = 10000 },
autopairs = true,
cmp = true,
diagnostics = { virtual_text = false, virtual_lines = false },
highlighturl = true,
notifications = false,
},
-- vim.diagnostic.config() values applied when diagnostics are toggled on
diagnostics = {
virtual_text = true,
underline = true,
},
autocmds = {
custom_title = {
{
event = { "BufEnter", "DirChanged" },
desc = "Update terminal title with org/repo format",
callback = function()
local filepath = vim.fn.expand "%:p"
local filename = vim.fn.expand "%:t"
if filename == "" then
local cwd = vim.fn.getcwd()
local github_match = cwd:match "github%.com/([^/]+/[^/]+)"
if github_match then
vim.opt.titlestring = github_match
else
vim.opt.titlestring = "Nvim"
end
return
end
local github_match = filepath:match "github%.com/([^/]+/[^/]+)"
if github_match then
vim.opt.titlestring = string.format("%s | %s", filename, github_match)
else
vim.opt.titlestring = string.format("%s | Nvim", filename)
end
end,
},
},
restore_session = {
{
event = "VimEnter",
desc = "Restore previous directory session if neovim opened with no arguments",
nested = true, -- trigger other autocommands as buffers open
callback = function()
if vim.fn.argc(-1) == 0 then
require("resession").load(
vim.fn.getcwd(),
{ dir = "dirsession", silence_errors = true }
)
end
end,
},
},
},
options = {
opt = {
relativenumber = false,
number = true,
spell = false,
wrap = true,
clipboard = "unnamedplus",
title = true,
titlestring = "",
laststatus = 0,
},
g = {},
},
mappings = {
n = {
-- overrides AstroNvim's default <C-q> = force quit (:q!)
["<C-q>"] = { "<Cmd>wqa<CR>", desc = "Save all buffers and quit Neovim" },
["<C-!>"] = { "<Cmd>suspend<CR>", desc = "Suspend nvim (return with 'fg')" },
["ZZ"] = { "<Cmd>wqa<CR>", desc = "Save all buffers and quit Neovim" },
["<A-q>"] = { "<Cmd>wqa<CR>", desc = "Save all buffers and quit Neovim" },
["<C-c>"] = { "<Cmd>wa<CR><Cmd>bd<CR>", desc = "Save and close buffer" },
["F"] = { "za", desc = "Toggle fold under cursor" },
-- v6: vim.diagnostic.goto_next/goto_prev deprecated in 0.11, use jump()
["J"] = {
function() vim.diagnostic.jump { count = 1, float = true } end,
desc = "Next diagnostic",
},
["K"] = {
function() vim.diagnostic.jump { count = -1, float = true } end,
desc = "Previous diagnostic",
},
["L"] = { "<Cmd>BufferLineCycleNext<CR>", desc = "Next buffer" },
["H"] = { "<Cmd>BufferLineCyclePrev<CR>", desc = "Previous buffer" },
["<Leader>e"] = {
function() require("snacks").picker.git_files { transform = file_filter } end,
desc = "Find git files",
},
["<leader><leader>"] = {
function() require("snacks").picker.smart() end,
desc = "Find files",
},
["<C-b>b"] = { "<Cmd>BufferLinePick<CR>", desc = "Pick buffer" },
["<C-b>f"] = {
function() require("snacks").picker.buffers() end,
desc = "Find buffers",
},
["<C-b><C-c>"] = {
function()
local current_buffer = vim.api.nvim_get_current_buf()
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
if buf ~= current_buffer then vim.api.nvim_buf_delete(buf, { force = true }) end
end
end,
desc = "Close all buffers except the current one",
},
["<C-b>g"] = {
function()
local groups = { "DEX", "DID", "DWN", "SVC", "Tests", "Actions", "Claude", "Docs", "Config" }
for _, group in ipairs(groups) do
vim.cmd("BufferLineGroupToggle " .. group)
end
end,
desc = "Toggle all buffer groups",
},
["<C-b>l"] = {
function() require("snacks").picker.lines() end,
desc = "Find in line",
},
["<C-g>o"] = { "<cmd>!gh repo view --web<CR>", desc = "Open Repo on Web" },
["<C-s>"] = { "<cmd>w<CR>", desc = "Save buffer" },
["<C-w>"] = { "<cmd>w<CR><Cmd>bd<CR>", desc = "Save and close buffer" },
["<C-Tab>"] = { "<cmd>tabnext<CR>", desc = "Next Tab" },
["<C-g><C-i>"] = { "<cmd>Octo issue list<CR>", desc = "List Issues" },
["<C-g><C-l>"] = { "<cmd>Octo label<CR>", desc = "Manage Labels" },
["<C-g><C-p>"] = { "<cmd>Octo pr list<CR>", desc = "List PRs" },
["<C-g>s"] = { "<cmd>Octo search<CR>", desc = "Octo Search" },
["<C-g><C-r>"] = { "<cmd>!gh release list<CR>", desc = "List Releases" },
["<C-g>d"] = {
function() require("snacks").picker.git_diff() end,
desc = "Search git diffs",
},
["<C-g><C-b>"] = {
function() require("snacks").picker.git_branches() end,
desc = "Search git branches",
},
["vv"] = { "gg0VG$", desc = "Select all contents in buffer" },
["T"] = { "gg", desc = "Go to top of file" },
["<C-f>d"] = {
function() require("snacks").picker.diagnostics() end,
desc = "Find diagnostics",
},
["<C-f>l"] = {
function() require("snacks").picker.lines() end,
desc = "Find in line",
},
["<C-f>t"] = {
function() require("snacks").picker.lines() end,
desc = "Find in line",
},
["<C-f>w"] = {
function() require("snacks").picker.grep() end,
desc = "Find word",
},
["<C-f>f"] = {
function() require("snacks").picker.files { transform = file_filter } end,
desc = "Find files (cwd)",
},
["<C-f><C-f>"] = {
function()
require("snacks").picker.lsp_symbols { layout = { preset = "vscode", preview = "main" } }
end,
desc = "Find LSP symbols",
},
["<C-f>o"] = {
function() require("snacks").picker.recent() end,
desc = "Find recent files",
},
["<C-f>p"] = {
function() require("snacks").picker.projects() end,
desc = "Find projects",
},
["<C-f>gc"] = {
function()
local ai_dir = vim.fn.getcwd() .. "/.ai"
if vim.fn.isdirectory(ai_dir) == 0 then
vim.notify("No .ai directory found in current project", vim.log.levels.WARN)
return
end
require("snacks").picker.files {
cwd = ai_dir,
transform = file_filter,
}
end,
desc = "Find AI files",
},
["<C-f>g"] = { desc = "Find by Group" },
["<C-f>gw"] = {
function()
local workflows_dir = vim.fn.getcwd() .. "/.github/workflows"
if vim.fn.isdirectory(workflows_dir) == 0 then
vim.notify("No .github/workflows directory found in current project", vim.log.levels.WARN)
return
end
require("snacks").picker.files {
cwd = workflows_dir,
transform = file_filter,
}
end,
desc = "Find GitHub Workflow files",
},
["<C-f>gd"] = {
function()
require("snacks").picker.files {
cmd = "fd",
args = { "devbox.json|process-compose.yaml|Dockerfile|docker-compose.yaml|compose.yaml" },
}
end,
desc = "Find Devbox/Docker files",
},
["<C-f>gm"] = {
function() require("snacks").picker.files { cmd = "fd", args = { "Makefile" } } end,
desc = "Find Makefile files",
},
["<C-f>gp"] = {
function() require("snacks").picker.files { cmd = "fd", args = { "package.json" } } end,
desc = "Find Package.json files",
},
["<C-p>"] = {
function()
if vim.b.toggle_number == 99 then
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<C-p>", true, false, true), "t", false)
return
end
local content = vim.fn.getreg "+"
vim.api.nvim_paste(content, true, -1)
end,
desc = "Paste from system clipboard",
},
["<C-a>d"] = {
function() with_trouble("diagnostics") end,
desc = "Search diagnostics (<C-t> sends to Trouble)",
},
["<C-a>a"] = {
function() vim.lsp.buf.code_action() end,
desc = "Show code actions",
},
["<C-a>s"] = {
function() with_trouble("lsp_symbols") end,
desc = "Search LSP symbols (<C-t> sends to Trouble)",
},
["<C-a>S"] = {
function() with_trouble("lsp_workspace_symbols") end,
desc = "Search LSP workspace symbols (<C-t> sends to Trouble)",
},
["<C-a><C-s>"] = { "<Cmd>SupermavenToggle<CR>", desc = "Toggle Supermaven" },
["<leader>u"] = { desc = "UI Toggles" },
["<leader>ud"] = {
function() require("snacks").toggle.diagnostics():toggle() end,
desc = "Toggle Diagnostics",
},
["<leader>un"] = {
function() require("snacks").toggle.line_number():toggle() end,
desc = "Toggle Line Numbers",
},
["<leader>ur"] = {
function() require("snacks").toggle.option("relativenumber"):toggle() end,
desc = "Toggle Relative Numbers",
},
["<leader>uw"] = {
function() require("snacks").toggle.option("wrap"):toggle() end,
desc = "Toggle Line Wrap",
},
["<leader>us"] = {
function() require("snacks").toggle.option("spell"):toggle() end,
desc = "Toggle Spelling",
},
["<leader>ui"] = {
function() require("snacks").toggle.inlay_hints():toggle() end,
desc = "Toggle Inlay Hints",
},
["<leader>ut"] = {
function() require("snacks").toggle.treesitter():toggle() end,
desc = "Toggle Treesitter",
},
["<leader>uc"] = {
function() require("snacks").toggle.option("conceallevel", { off = 0, on = 2 }):toggle() end,
desc = "Toggle Conceal",
},
["<leader>uI"] = {
function() require("snacks").toggle.indent():toggle() end,
desc = "Toggle Indent Guides",
},
["<leader>uz"] = {
function() require("snacks").toggle.zen():toggle() end,
desc = "Toggle Zen Mode",
},
["<leader>uZ"] = {
function() require("snacks").toggle.zoom():toggle() end,
desc = "Toggle Zoom",
},
["<leader>ua"] = {
function() require("snacks").toggle.animate():toggle() end,
desc = "Toggle Animations",
},
["<leader>uS"] = {
function() require("snacks").toggle.scroll():toggle() end,
desc = "Toggle Smooth Scroll",
},
["<leader>up"] = {
function() require("snacks").toggle.profiler():toggle() end,
desc = "Toggle Profiler",
},
["<leader>uh"] = {
function() require("snacks").toggle.profiler_highlights():toggle() end,
desc = "Toggle Profiler Highlights",
},
["<leader>ux"] = {
function() require("snacks").toggle.dim():toggle() end,
desc = "Toggle Dim Inactive",
},
["<leader>uf"] = {
function()
vim.g.disable_autoformat = not vim.g.disable_autoformat
local status = vim.g.disable_autoformat and "disabled" or "enabled"
vim.notify("Format on save " .. status, vim.log.levels.INFO)
end,
desc = "Toggle Format on Save",
},
-- v6: virtual_lines is native in vim.diagnostic.config, lsp_lines plugin no longer needed
["<leader>ul"] = {
function()
local cfg = vim.diagnostic.config() or {}
local enabled = not cfg.virtual_lines
vim.diagnostic.config { virtual_lines = enabled, virtual_text = not enabled }
end,
desc = "Toggle Virtual Lines",
},
},
i = {
["<C-s>"] = { "<Cmd>wa<CR><Esc>", desc = "Save buffer, and return to normal mode" },
["<C-c>"] = { "<Cmd>wa<CR><Cmd>bd<CR><Esc>", desc = "Save, close buffer, and return to normal mode" },
["<C-x>"] = { "<Cmd>wa<CR><Cmd>bd<CR><Esc>", desc = "Save, close buffer, and return to normal mode" },
},
v = {
["<C-c>"] = { "<Cmd>w<CR><Cmd>bd<CR>", desc = "Save and close buffer" },
["<C-x>"] = { "<Cmd>w<CR><Cmd>bd<CR>", desc = "Save and close buffer" },
["D"] = {
function()
vim.cmd 'normal! "vy'
local selection = vim.fn.getreg "v"
local escaped = vim.fn.escape(selection, [[/\.*$^~[]])
vim.cmd(string.format([[%%s/%s//ge]], escaped))
vim.notify(string.format("Deleted all occurrences of: %s", selection), vim.log.levels.INFO)
end,
desc = "Delete all occurrences of selected text",
},
["R"] = {
function()
vim.cmd 'normal! "vy'
local selection = vim.fn.getreg "v"
local escaped = vim.fn.escape(selection, [[/\.*$^~[]])
require("snacks").input({
prompt = string.format("Replace '%s' with:", selection),
default = "",
}, function(replacement)
if replacement then
local escaped_replacement = vim.fn.escape(replacement, [[/\&~]])
vim.cmd(string.format([[%%s/%s/%s/ge]], escaped, escaped_replacement))
vim.notify(string.format("Replaced '%s' with '%s'", selection, replacement), vim.log.levels.INFO)
end
end)
end,
desc = "Replace all occurrences of selected text",
},
},
t = {
["<C-p>"] = { function() vim.cmd 'normal! "+p' end, desc = "Paste from system clipboard" },
["<C-b>f"] = {
function() require("snacks").picker.buffers() end,
desc = "Find buffers",
},
["<C-q>"] = {
function()
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes([[<C-\><C-n>]], true, false, true), "n", false)
vim.cmd "close"
end,
desc = "Exit terminal and close window",
},
},
},
},
}
+104
View File
@@ -0,0 +1,104 @@
if true then return {} end -- WARN: REMOVE THIS LINE TO ACTIVATE THIS FILE
-- AstroLSP allows you to customize the features in AstroNvim's LSP configuration engine
-- Configuration documentation can be found with `:h astrolsp`
-- NOTE: We highly recommend setting up the Lua Language Server (`:LspInstall lua_ls`)
-- as this provides autocomplete and documentation while editing
---@type LazySpec
return {
"AstroNvim/astrolsp",
---@type AstroLSPOpts
opts = {
-- Configuration table of features provided by AstroLSP
features = {
codelens = true, -- enable/disable codelens refresh on start
inlay_hints = false, -- enable/disable inlay hints on start
semantic_tokens = true, -- enable/disable semantic token highlighting
},
-- customize lsp formatting options
formatting = {
-- control auto formatting on save
format_on_save = {
enabled = true, -- enable or disable format on save globally
allow_filetypes = { -- enable format on save for specified filetypes only
-- "go",
},
ignore_filetypes = { -- disable format on save for specified filetypes
-- "python",
},
},
disabled = { -- disable formatting capabilities for the listed language servers
-- disable lua_ls formatting capability if you want to use StyLua to format your lua code
-- "lua_ls",
},
timeout_ms = 1000, -- default format timeout
-- filter = function(client) -- fully override the default formatting function
-- return true
-- end
},
-- enable servers that you already have installed without mason
servers = {
-- "pyright"
},
-- customize language server configuration passed to `vim.lsp.config`
-- client specific configuration can also go in `lsp/` in your configuration root (see `:h lsp-config`)
config = {
-- ["*"] = { capabilities = {} }, -- modify default LSP client settings such as capabilities
},
-- customize how language servers are attached
handlers = {
-- a function with the key `*` modifies the default handler, functions takes the server name as the parameter
-- ["*"] = function(server) vim.lsp.enable(server) end
-- the key is the server that is being setup with `vim.lsp.config`
-- rust_analyzer = false, -- setting a handler to false will disable the set up of that language server
},
-- Configure buffer local auto commands to add when attaching a language server
autocmds = {
-- first key is the `augroup` to add the auto commands to (:h augroup)
lsp_codelens_refresh = {
-- Optional condition to create/delete auto command group
-- can either be a string of a client capability or a function of `fun(client, bufnr): boolean`
-- condition will be resolved for each client on each execution and if it ever fails for all clients,
-- the auto commands will be deleted for that buffer
cond = "textDocument/codeLens",
-- cond = function(client, bufnr) return client.name == "lua_ls" end,
-- list of auto commands to set
{
-- events to trigger
event = { "InsertLeave", "BufEnter" },
-- the rest of the autocmd options (:h nvim_create_autocmd)
desc = "Refresh codelens (buffer)",
callback = function(args)
if require("astrolsp").config.features.codelens then vim.lsp.codelens.enable(true, { bufnr = args.buf }) end
end,
},
},
},
-- mappings to be set up on attaching of a language server
mappings = {
n = {
-- a `cond` key can provided as the string of a server capability to be required to attach, or a function with `client` and `bufnr` parameters from the `on_attach` that returns a boolean
gD = {
function() vim.lsp.buf.declaration() end,
desc = "Declaration of current symbol",
cond = "textDocument/declaration",
},
["<Leader>uY"] = {
function() require("astrolsp.toggles").buffer_semantic_tokens() end,
desc = "Toggle LSP semantic highlight (buffer)",
cond = function(client)
return client:supports_method "textDocument/semanticTokens/full" and vim.lsp.semantic_tokens ~= nil
end,
},
},
},
-- A custom `on_attach` function to be run after the default `on_attach` function
-- takes two parameters `client` and `bufnr` (`:h lsp-attach`)
on_attach = function(client, bufnr)
-- this would disable semanticTokensProvider for all clients
-- client.server_capabilities.semanticTokensProvider = nil
end,
},
}
+15
View File
@@ -0,0 +1,15 @@
-- AstroUI provides the basis for configuring the AstroNvim User Interface
-- Configuration documentation can be found with `:h astroui`
-- NOTE: We highly recommend setting up the Lua Language Server (`:LspInstall lua_ls`)
-- as this provides autocomplete and documentation while editing
---@type LazySpec
return {
"AstroNvim/astroui",
---@type AstroUIOpts
opts = {
-- change colorscheme
colorscheme = "cyberdream",
},
}
+105
View File
@@ -0,0 +1,105 @@
-- Run all safe LSP code actions advertised by attached servers before save,
-- then let conform format. The astrocommunity conform-nvim pack wires up
-- format_on_save; this just adds the pre-save code-action pass.
-- Action kinds we consider safe to apply on save. Matches exact kinds and
-- any subkinds via "<kind>." prefix (LSP CodeActionKind is hierarchical).
-- Deliberately NOT the bare "source" umbrella: it covers non-idempotent
-- document rewrites (e.g. marksman's "Create Table of Contents").
local SAFE_KINDS = {
"source.organizeImports",
"source.fixAll",
"quickfix",
}
local function is_safe_kind(kind)
if not kind or kind == "" then return false end
for _, safe in ipairs(SAFE_KINDS) do
if kind == safe or vim.startswith(kind, safe .. ".") then return true end
end
return false
end
-- Pull the kinds a given client advertises support for, filtered to safe ones.
-- If the server returns no kinds list, fall back to the top-level SAFE_KINDS so
-- it gets the chance to satisfy a broad "only" filter.
local function safe_kinds_for(client)
local provider = (client.server_capabilities or {}).codeActionProvider
if not provider then return {} end
local advertised = type(provider) == "table" and provider.codeActionKinds or nil
if not advertised or #advertised == 0 then return vim.deepcopy(SAFE_KINDS) end
local kinds = {}
for _, k in ipairs(advertised) do
if is_safe_kind(k) then table.insert(kinds, k) end
end
return kinds
end
-- Collect LSP-shaped diagnostics so quickfix actions have something to bind to.
local function lsp_diagnostics(bufnr)
local out = {}
for _, d in ipairs(vim.diagnostic.get(bufnr)) do
if d.user_data and d.user_data.lsp then table.insert(out, d.user_data.lsp) end
end
return out
end
-- Servers may ignore context.only (LSP allows it), so re-filter the returned
-- actions by kind before applying. Kind-less actions are skipped: we asked for
-- specific kinds, so anything untagged is not provably safe.
local function apply_result(client, bufnr, result)
if not result then return end
for _, action in ipairs(result) do
if is_safe_kind(action.kind) then
if action.edit then
vim.lsp.util.apply_workspace_edit(action.edit, client.offset_encoding or "utf-8")
end
if type(action.command) == "table" then
client:exec_cmd(action.command, { bufnr = bufnr })
end
end
end
end
local function apply_safe_actions(bufnr)
local clients = vim.lsp.get_clients { bufnr = bufnr, method = "textDocument/codeAction" }
if #clients == 0 then return end
local diagnostics = lsp_diagnostics(bufnr)
for _, client in ipairs(clients) do
local kinds = safe_kinds_for(client)
if #kinds > 0 then
local enc = client.offset_encoding or "utf-8"
local params = vim.lsp.util.make_range_params(0, enc)
params.context = { only = kinds, diagnostics = diagnostics, triggerKind = 2 }
local resp = client:request_sync("textDocument/codeAction", params, 1000, bufnr)
if resp and not resp.err then apply_result(client, bufnr, resp.result) end
end
end
end
---@type LazySpec
return {
"stevearc/conform.nvim",
init = function()
vim.api.nvim_create_autocmd("BufWritePre", {
group = vim.api.nvim_create_augroup("user_lsp_safe_actions", { clear = true }),
desc = "Apply all safe LSP code actions (source.*, quickfix) before save",
callback = function(args)
if vim.bo[args.buf].buftype ~= "" then return end
if vim.g.disable_autoformat or vim.b[args.buf].disable_autoformat then return end
apply_safe_actions(args.buf)
end,
})
end,
opts = function(_, opts)
-- Skip format-on-save for JavaScript buffers (.js/.mjs/.cjs); manual
-- :Format / <Leader>lf still works. Wraps the astrocommunity pack's
-- format_on_save so its autoformat toggle handling is preserved.
local pack_format_on_save = opts.format_on_save
opts.format_on_save = function(bufnr)
if vim.bo[bufnr].filetype == "javascript" then return end
if type(pack_format_on_save) == "function" then return pack_format_on_save(bufnr) end
return pack_format_on_save
end
end,
}
+76
View File
@@ -0,0 +1,76 @@
--- flash.nvim: labeled jumps and enhanced motions
---@type LazySpec
return {
"folke/flash.nvim",
event = "VeryLazy",
---@type Flash.Config
opts = {
modes = {
char = {
-- normal-mode `f` is the Vimium-style word jump and `F` is the
-- search-style jump below, so flash's char mode must not rebind
-- them; t/T/;/, stay enhanced
keys = { "t", "T", ";", "," },
-- show jump labels on the char-motion matches (t/T)
jump_labels = true,
},
-- label-enhanced regular `/` and `?` search; <c-s> in cmdline
-- toggles it off for a plain search
search = { enabled = true },
},
},
keys = {
{
"f",
mode = "n",
function()
-- Vimium-c style: label every visible word start immediately,
-- press a label to jump (no search pattern typed)
require("flash").jump {
search = { mode = "search", max_length = 0 },
label = { after = false, before = { 0, 0 } },
pattern = [[\<]],
}
end,
desc = "Jump to word (Vimium-style)",
},
{
"F",
mode = "n",
function()
-- Search-style flash: type a regex pattern and labels appear on
-- every match. While selecting, `<C-n>`/`<C-b>` cycle to the
-- next/previous result, <CR> confirms the selection, a label jumps
-- directly, <Esc> cancels back to the origin. The pattern is pushed
-- to search history and the `/` register, so `n`/`N` keep working
-- after the jump.
local current ---@type Flash.Match?
require("flash").jump {
search = { mode = "search" },
jump = { history = true, register = true, nohlsearch = true },
actions = {
["<c-n>"] = function(state)
-- first press selects the current target, then cycle forward
current = current and state:find { match = current, forward = true, wrap = true } or state.target
if current then state:jump(current) end
end,
["<c-b>"] = function(state)
current = state:find { match = current or state.target, forward = false, wrap = true }
if current then state:jump(current) end
end,
["<cr>"] = function(state)
state:jump(current) -- nil falls back to state.target
return false -- end the loop
end,
},
}
end,
desc = "Flash search",
},
{ "s", mode = { "n", "x", "o" }, function() require("flash").jump() end, desc = "Flash" },
{ "S", mode = { "n", "x", "o" }, function() require("flash").treesitter() end, desc = "Flash Treesitter" },
{ "r", mode = "o", function() require("flash").remote() end, desc = "Remote Flash" },
{ "R", mode = { "o", "x" }, function() require("flash").treesitter_search() end, desc = "Treesitter Search" },
{ "<c-s>", mode = { "c" }, function() require("flash").toggle() end, desc = "Toggle Flash Search" },
},
}
+42
View File
@@ -0,0 +1,42 @@
local function t_nav(fn)
return function()
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes([[<C-\><C-n>]], true, false, true), "n", false)
vim.schedule(fn)
end
end
return {
"MunsMan/kitty-navigator.nvim",
-- Keep the kitty-side kittens in sync with the plugin. ~/.config/kitty is symlinked into the
-- dotfiles repo, so this copies navigate_kitty.py + pass_keys.py straight into the tracked config.
-- navigate_kitty.py is required for the nvim->kitty edge handoff (init.lua calls `kitty @ kitten
-- navigate_kitty.py <dir>`); pass_keys.py must match the `neighboring_window` map syntax in kitty.conf.
build = {
"cp navigate_kitty.py ~/.config/kitty",
"cp pass_keys.py ~/.config/kitty",
},
-- Disable smart-splits navigation keys (AstroNvim injects these when KITTY_LISTEN_ON is set);
-- kitty-navigator owns <C-h/j/k/l>. Resize bindings (<C-Up/Down/Left/Right>) are left intact.
specs = {
{
"AstroNvim/astrocore",
opts = function(_, opts)
local m = opts.mappings.n
m["<C-H>"] = false
m["<C-J>"] = false
m["<C-K>"] = false
m["<C-L>"] = false
end,
},
},
keys = {
{"<C-h>", function()require("kitty-navigator").navigateLeft()end, desc = "Move left a Split", mode = {"n"}},
{"<C-j>", function()require("kitty-navigator").navigateDown()end, desc = "Move down a Split", mode = {"n"}},
{"<C-k>", function()require("kitty-navigator").navigateUp()end, desc = "Move up a Split", mode = {"n"}},
{"<C-l>", function()require("kitty-navigator").navigateRight()end, desc = "Move right a Split", mode = {"n"}},
{"<C-h>", t_nav(function()require("kitty-navigator").navigateLeft()end), desc = "Move left a Split", mode = {"t"}},
{"<C-j>", t_nav(function()require("kitty-navigator").navigateDown()end), desc = "Move down a Split", mode = {"t"}},
{"<C-k>", t_nav(function()require("kitty-navigator").navigateUp()end), desc = "Move up a Split", mode = {"t"}},
{"<C-l>", t_nav(function()require("kitty-navigator").navigateRight()end), desc = "Move right a Split", mode = {"t"}},
},
}
+28
View File
@@ -0,0 +1,28 @@
if true then return {} end -- WARN: REMOVE THIS LINE TO ACTIVATE THIS FILE
-- Customize Mason
---@type LazySpec
return {
-- use mason-tool-installer for automatically installing Mason packages
{
"WhoIsSethDaniel/mason-tool-installer.nvim",
-- overrides `require("mason-tool-installer").setup(...)`
opts = {
-- Make sure to use the names found in `:Mason`
ensure_installed = {
-- install language servers
"lua-language-server",
-- install formatters
"stylua",
-- install debuggers
"debugpy",
-- install any other package
"tree-sitter-cli",
},
},
},
}
+24
View File
@@ -0,0 +1,24 @@
if true then return {} end -- WARN: REMOVE THIS LINE TO ACTIVATE THIS FILE
-- Customize None-ls sources
---@type LazySpec
return {
"nvimtools/none-ls.nvim",
opts = function(_, opts)
-- opts variable is the default configuration table for the setup function call
-- local null_ls = require "null-ls"
-- Check supported formatters and linters
-- https://github.com/nvimtools/none-ls.nvim/tree/main/lua/null-ls/builtins/formatting
-- https://github.com/nvimtools/none-ls.nvim/tree/main/lua/null-ls/builtins/diagnostics
-- Only insert new sources, do not replace the existing ones
-- (If you wish to replace, use `opts.sources = {}` instead of the `list_insert_unique` function)
opts.sources = require("astrocore").list_insert_unique(opts.sources, {
-- Set a formatter
-- null_ls.builtins.formatting.stylua,
-- null_ls.builtins.formatting.prettier,
})
end,
}
@@ -0,0 +1,24 @@
if true then return {} end -- WARN: REMOVE THIS LINE TO ACTIVATE THIS FILE
-- Customize Treesitter
-- --------------------
-- Treesitter customizations are handled with AstroCore
-- as nvim-treesitter simply provides a download utility for parsers
---@type LazySpec
return {
"AstroNvim/astrocore",
---@type AstroCoreOpts
opts = {
treesitter = {
highlight = true, -- enable/disable treesitter based highlighting
indent = true, -- enable/disable treesitter based indentation
auto_install = true, -- enable/disable automatic installation of detected languages
ensure_installed = {
"lua",
"vim",
-- add more arguments for adding more treesitter parsers
},
},
},
}
+98
View File
@@ -0,0 +1,98 @@
--- User plugins: cursor animation and snacks.nvim (picker + dashboard) customization
-- Confirm action for file-opening pickers: <CR> opens the selection as a
-- tab via `tabdrop` (:tab drop semantics — focus the buffer if it's already
-- visible in any tab, don't spawn a tab from an empty buffer, else open a
-- new tab). Explicit edit-cmd keybinds (<S-CR>/<c-v> vsplit, <c-s> split)
-- carry `action.cmd` and are passed through untouched.
local function tab_confirm(picker, item, action)
local actions = require "snacks.picker.actions"
if action.cmd then return actions.jump(picker, item, action) end
return actions.jump(picker, item, vim.tbl_extend("force", {}, action, { cmd = "tabdrop" }))
end
-- Tab-on-enter + vsplit-on-shift-enter for the file-opening pickers only;
-- location pickers (lsp_*, lines, diagnostics, grep) and sources with their
-- own confirm (git_branches, projects) keep their defaults.
local picker_sources = {}
for _, source in ipairs { "files", "git_files", "smart", "recent", "buffers" } do
picker_sources[source] = {
confirm = tab_confirm,
win = {
input = { keys = { ["<S-CR>"] = { "edit_vsplit", mode = { "n", "i" } } } },
list = { keys = { ["<S-CR>"] = "edit_vsplit" } },
},
}
end
-- Smart picker: anchor to the current git repository. `config` runs when
-- the picker opens: cwd becomes the repo root (so the `files` finder scans
-- the whole repo, not just a rooter-chdir'd subdir) and `filter.cwd` drops
-- buffers/recent entries from other repos. Outside a repo, plain cwd
-- behavior is kept.
picker_sources.smart.config = function(opts)
local root = require("snacks").git.get_root()
if root then
opts.cwd = root
opts.filter = vim.tbl_extend("force", opts.filter or {}, { cwd = true })
end
return opts
end
---@type LazySpec
return {
{ "sphamba/smear-cursor.nvim", opts = {} },
-- terminals are handled by kitty now
{ "akinsho/toggleterm.nvim", enabled = false },
{
"folke/snacks.nvim",
opts = {
picker = {
jump = { reuse_win = true },
sources = picker_sources,
},
dashboard = {
enabled = true,
preset = {
-- "prdlk.nvim" in ansi_regular block style
header = table.concat({
"██████ ██████ ██████ ██ ██ ██ ███ ██ ██ ██ ██ ███ ███",
"██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ████ ████",
"██████ ██████ ██ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ ████ ██",
"██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██",
"██ ██ ██ ██████ ███████ ██ ██ ██ ██ ████ ████ ██ ██ ██",
}, "\n"),
},
sections = {
{ section = "header" },
{ section = "keys", gap = 1, padding = 1 },
{
icon = " ",
desc = "Browse Repo",
padding = 1,
key = "b",
action = function() Snacks.gitbrowse() end,
},
{
icon = " ",
desc = "Projects (ghq)",
padding = 1,
key = "p",
action = function()
local repos = vim.fn.systemlist "ghq list -p"
vim.ui.select(repos, { prompt = "Select repository" }, function(dir)
if not dir then return end
vim.cmd.cd(dir)
Snacks.picker.files()
end)
end,
},
{ section = "startup" },
},
},
},
},
}
+91
View File
@@ -0,0 +1,91 @@
--- Yazi as the default file manager (full neo-tree replacement)
---@type LazySpec
return {
{
"mikavilpas/yazi.nvim",
version = "*", -- latest stable release
event = "VeryLazy",
dependencies = {
{ "nvim-lua/plenary.nvim", lazy = true },
},
keys = {
{
"<leader>-",
mode = { "n", "v" },
"<cmd>Yazi<cr>",
desc = "Open yazi at the current file",
},
{
"<leader>cw",
"<cmd>Yazi cwd<cr>",
desc = "Open yazi in nvim's working directory",
},
{
-- replaces AstroNvim's <Leader>o "Toggle Explorer Focus" (neo-tree)
"<leader>o",
"<cmd>Yazi<cr>",
desc = "Open Explorer (yazi at current file)",
},
{
"<C-e>",
mode = { "n", "v", "t" },
function()
-- true toggle: if a yazi window is already open, quit it instead
-- of nesting a second instance (yazi.nvim's toggle() always spawns)
for _, win in ipairs(vim.api.nvim_list_wins()) do
local buf = vim.api.nvim_win_get_buf(win)
if vim.bo[buf].filetype == "yazi" then
-- send `q` to the yazi process so it exits gracefully and
-- saves its state for the next resume
vim.api.nvim_chan_send(vim.bo[buf].channel, "q")
return
end
end
vim.cmd "Yazi toggle"
end,
desc = "Toggle yazi (resume last session)",
},
},
---@type YaziConfig | {}
opts = {
-- yazi replaces netrw/neo-tree when opening directories (nvim .)
open_for_directories = true,
-- keep a single yazi tab: `true` would pass every visible split as an
-- extra path arg, and each one becomes a yazi tab that then persists
-- across <C-e> toggles (resume), piling up tabs over time
open_multiple_tabs = false,
-- occupy the whole screen instead of a floating popup
floating_window_scaling_factor = 1,
yazi_floating_window_border = "none",
keymaps = {
show_help = "<f1>",
-- Open the hovered/selected file(s) as nvim splits. These are
-- buffer-local terminal-mode keymaps on the yazi buffer, so nvim
-- intercepts the chord before the yazi process ever sees it --
-- nothing is needed in ~/.config/yazi/keymap.toml. Chords match
-- the telescope/snacks picker convention (<c-v>/<c-x>/<c-t>).
open_file_in_vertical_split = "<c-v>",
open_file_in_horizontal_split = "<c-x>",
-- NOTE: the default <c-t> (open in tab) shadows the yazi-side
-- <C-t> "plugin tv" bind from keymap.toml while inside nvim;
-- set open_file_in_tab = false to let <C-t> reach yazi/tv instead
open_file_in_tab = "<c-t>",
-- ~/.config/yazi/keymap.toml binds <C-q> to quit inside yazi;
-- don't hijack it for the quickfix list (multi-select still goes
-- to the quickfix list via the default yazi_opened_multiple_files)
send_to_quickfix_list = false,
},
integrations = {
-- <c-y> copy-relative-path action inside snacks pickers too
picker_add_copy_relative_path_action = "snacks.picker",
},
},
init = function()
-- netrw is fully replaced by yazi (open_for_directories)
vim.g.loaded_netrwPlugin = 1
end,
},
-- neo-tree is fully replaced by yazi.nvim
{ "nvim-neo-tree/neo-tree.nvim", enabled = false },
}