From 9a6bdfcf8c5cad15fb0f07139185cc137ead0391 Mon Sep 17 00:00:00 2001 From: Prad Nukala Date: Fri, 29 May 2026 18:35:10 -0400 Subject: [PATCH] feat(core): add astrocommunity configuration --- lua/community.lua | 36 +++ lua/config/ignore_patterns.lua | 259 +++++++++++++++++++ lua/config/terminals.lua | 98 +++++++ lua/lazy_setup.lua | 32 +++ lua/plugins/astrocore.lua | 456 +++++++++++++++++++++++++++++++++ lua/plugins/astrolsp.lua | 104 ++++++++ lua/plugins/astroui.lua | 15 ++ lua/plugins/claudecode.lua | 60 +++++ lua/plugins/conform.lua | 86 +++++++ lua/plugins/kitty.lua | 42 +++ lua/plugins/mason.lua | 28 ++ lua/plugins/neotree.lua | 341 ++++++++++++++++++++++++ lua/plugins/neovim.lua | 14 + lua/plugins/none-ls.lua | 24 ++ lua/plugins/treesitter.lua | 24 ++ lua/plugins/user.lua | 92 +++++++ lua/polish.lua | 47 ++++ 17 files changed, 1758 insertions(+) create mode 100644 lua/community.lua create mode 100644 lua/config/ignore_patterns.lua create mode 100644 lua/config/terminals.lua create mode 100644 lua/lazy_setup.lua create mode 100644 lua/plugins/astrocore.lua create mode 100644 lua/plugins/astrolsp.lua create mode 100644 lua/plugins/astroui.lua create mode 100644 lua/plugins/claudecode.lua create mode 100644 lua/plugins/conform.lua create mode 100644 lua/plugins/kitty.lua create mode 100644 lua/plugins/mason.lua create mode 100644 lua/plugins/neotree.lua create mode 100644 lua/plugins/neovim.lua create mode 100644 lua/plugins/none-ls.lua create mode 100644 lua/plugins/treesitter.lua create mode 100644 lua/plugins/user.lua create mode 100644 lua/polish.lua diff --git a/lua/community.lua b/lua/community.lua new file mode 100644 index 0000000..b3a3c6f --- /dev/null +++ b/lua/community.lua @@ -0,0 +1,36 @@ + +-- AstroCommunity: import any community modules here +-- We import this file in `lazy_setup.lua` before the `plugins/` folder. +-- This guarantees that the specs are processed before any user plugins. + +---@type LazySpec +return { + "AstroNvim/astrocommunity", + version = false, -- Use latest astrocommunity + { import = "astrocommunity.bars-and-lines.bufferline-nvim" }, + { import = "astrocommunity.editing-support.refactoring-nvim" }, + { import = "astrocommunity.editing-support.conform-nvim" }, + { import = "astrocommunity.editing-support.amp-nvim" }, + { import = "astrocommunity.diagnostics.trouble-nvim" }, + { import = "astrocommunity.git.codediff-nvim" }, + { import = "astrocommunity.git.octo-nvim" }, + { import = "astrocommunity.markdown-and-latex.render-markdown-nvim" }, + { import = "astrocommunity.pack.mdx" }, + { import = "astrocommunity.pack.biome" }, + { import = "astrocommunity.pack.go" }, + { import = "astrocommunity.pack.golangci-lint" }, + { import = "astrocommunity.pack.html-css" }, + { import = "astrocommunity.pack.json" }, + { import = "astrocommunity.pack.proto" }, + { import = "astrocommunity.pack.pkl" }, + { import = "astrocommunity.pack.rust" }, + { import = "astrocommunity.pack.yaml" }, + { import = "astrocommunity.pack.toml" }, + { import = "astrocommunity.pack.typescript" }, + { import = "astrocommunity.pack.tailwindcss" }, + { import = "astrocommunity.code-runner.overseer-nvim" }, + { import = "astrocommunity.completion.supermaven-nvim" }, + { import = "astrocommunity.lsp.dev-tools-nvim" }, + { import = "astrocommunity.lsp.nvim-lsp-file-operations" }, + { import = "astrocommunity.colorscheme.cyberdream-nvim" }, +} diff --git a/lua/config/ignore_patterns.lua b/lua/config/ignore_patterns.lua new file mode 100644 index 0000000..93dd266 --- /dev/null +++ b/lua/config/ignore_patterns.lua @@ -0,0 +1,259 @@ +--- Shared ignore patterns for file explorers and pickers +--- This module provides a centralized list of patterns to ignore across +--- neotree, telescope, snacks.picker, and other file browsing tools. +--- @module config.ignore_patterns + +local M = {} + +--- Core ignore patterns used across the configuration +--- These patterns use glob syntax (* for wildcards) +M.patterns = { + -- Build artifacts and generated files + "chain_*.json", + ".npmrc", + ".omc", + ".claude", + ".changeset", + ".codegraph", + ".gitignore", + "turbo.json", + "vite.config.ts", + "bunfig.toml", + "*.pb.go", + "*.pkl.go", + "*.pulsar.go", + "*.pb.gorm.go", + "*.pb.gw.go", + "*_templ.go", + "*_mock.go", + "*_integration.go", + "*_test.go", + "AGENTS.md", + "test", + "tests", + + -- Configuration files + ".editorconfig", + ".gitpod.*", + + + + -- Lock files and dependencies + "*.lock", + "*.lockb", + "*.sum", + "*.work.*", + "package-lock.json", + "pnpm-lock.yaml", + ".gitattributes", + ".oxlintrc.json", + "tsconfig*", + + -- Temporary and cache files + "*.tmp", + ".typecopy", + ".python-version", + ".prettierrc", + ".trunk", + ".config", + ".pkl-lsp", + ".tsbuildinfo", + ".wrangler", + ".parcel-cache", + ".conform*", + ".null-ls_*", + + -- Binary and media files + "*.wasm", + "*.png", + "*.jpg", + "*.icns", + "*.ico", + + -- Directories and special files + "contrib", + "interchaintest", + "PULL_REQUEST_TEMPLATE.md", + "Icon?", + "iCloud~", + "com~", +} + +--- Patterns that should never be shown in any file browser +M.never_show = { + -- Version control + ".git", + ".ai", + + -- Dependencies + "node_modules", + ".wrangler", + "CODEOWNERS", + ".golangci.yml", + + -- Build outputs + ".next", + ".parcel-cache", + + -- Task runners and tools + ".task", + ".devbox", + ".turbo", + ".jj", + ".spawn", + + -- IDE and editor + ".idea", + ".venv", + ".metadata", + ".dart_tool", + ".devcontainer", + + -- Build tools + ".gradle", + "gradle.bat", + "heighliner", + + -- Temporary + ".tmp", + "tmp", + + -- Logs + "sonr.log", + "junit.xml", + + -- macOS + ".DS_Store", + ".DocumentRevisions-V100", + ".Spotlight-V100", + ".TemporaryItems", + ".Trashes", + ".fseventsd", + ".timemachine", + + -- Templates + "DISCUSSION_TEMPLATE", + "ISSUE_TEMPLATE", + + -- License + "LICENSE", +} + +--- Patterns that should never be shown (pattern matching) +M.never_show_patterns = { + "*DS_Store", + ".obsidian", + ".pkl-lsp", + ".tsbuildinfo", + "package-lock.json", + ".prettierrc", + "node_modules", + ".DocumentRevisions-V100", + ".Spotlight-V100", + ".TemporaryItems", + ".Trashes", + ".fseventsd", + ".editorconfig", + "*.min.js", + "*.lock", + "*lock*", + "*.lockb", + "*.pulsar.go", + "*.pb.gorm.go", + "*.pb.gw.go", + "*_templ.go", + "*.tmp", + "*.work.*", + "*.sum", + ".parcel-cache", + "*.icns", + "*.ico", + "*.iml", + "Icon?", + "iCloud~", + "com~", + "*.icns", + ".conform*", + ".null-ls_*", +} + +--- Directories to ignore when filtering files +M.ignored_directories = { + "contracts", + "crypto", + "api", + "chains", + "test", + "examples", + "scripts", + "bridge", + "client", + "translations", + "env", + ".husky", +} + +--- Read additional ignore patterns from .rgignore file in git root +--- @return table patterns List of patterns from .rgignore +function M.read_rgignore() + local patterns = {} + local current_file = vim.fn.expand "%:p" + local current_dir = vim.fn.fnamemodify(current_file, ":h") + + if current_dir == "" then current_dir = vim.fn.getcwd() end + + local git_root = + vim.fn.systemlist("cd " .. vim.fn.shellescape(current_dir) .. " && git rev-parse --show-toplevel 2>/dev/null")[1] + + if git_root and git_root ~= "" and not git_root:match "^fatal:" then + local rgignore_path = git_root .. "/.rgignore" + local file = io.open(rgignore_path, "r") + + if file then + for line in file:lines() do + if line ~= "" and not line:match "^#" then + line = line:gsub("^%./", "") + table.insert(patterns, line) + end + end + file:close() + end + end + + return patterns +end + +--- Get all hide patterns including rgignore +--- @return table patterns Combined list of all patterns to hide +function M.get_all_patterns() + local rgignore_patterns = M.read_rgignore() + return vim.list_extend(vim.list_extend({}, M.patterns), rgignore_patterns) +end + +--- Create a file filter function for pickers +--- @return function filter Function that filters files based on ignore patterns +function M.create_picker_filter() + return function(item) + if not item or not item.file then return item end + + local file = item.file + local basename = vim.fn.fnamemodify(file, ":t") + local dir = vim.fn.fnamemodify(file, ":h:t") + + -- Check against all patterns + local all_patterns = M.get_all_patterns() + for _, pattern in ipairs(all_patterns) do + local lua_pattern = pattern:gsub("%.", "%%."):gsub("%*", ".*"):gsub("%?", ".") + if basename:match("^" .. lua_pattern .. "$") or file:match(lua_pattern) then return nil end + end + + -- Check ignored directories + for _, ignored in ipairs(M.ignored_directories) do + if dir == ignored or file:match("/" .. ignored .. "/") then return nil end + end + + return item + end +end + +return M diff --git a/lua/config/terminals.lua b/lua/config/terminals.lua new file mode 100644 index 0000000..0addeac --- /dev/null +++ b/lua/config/terminals.lua @@ -0,0 +1,98 @@ +--- Terminal configurations using toggleterm +--- This module provides terminal toggle functions for various CLI tools +--- @module config.terminals + +local M = {} + +--- Check if toggleterm is available +--- @return boolean available Whether toggleterm is loaded +local function is_toggleterm_available() + local ok, _ = pcall(require, "toggleterm.terminal") + return ok +end + +--- Initialize all terminal configurations +--- Only runs if toggleterm is available +function M.setup() + if not is_toggleterm_available() then + vim.notify("toggleterm not available, skipping terminal setup", vim.log.levels.WARN) + return + end + + local Terminal = require("toggleterm.terminal").Terminal + -- Scooter find and replace terminal + local smartCommit = Terminal:new { + cmd = "smartcommit", + hidden = true, + direction = "vertical", + close_on_exit = true, + on_open = function(term) + vim.cmd "startinsert!" + vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "close", { noremap = true, silent = true }) + end, + } + + -- Scooter find and replace terminal + local scooter = Terminal:new { + cmd = "scooter", + hidden = true, + direction = "vertical", + close_on_exit = true, + on_open = function(term) + vim.cmd "startinsert!" + vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "close", { noremap = true, silent = true }) + end, + } + + -- Mk (make) terminal + local mk = Terminal:new { + cmd = "task", + hidden = true, + direction = "horizontal", + on_open = function(term) + vim.cmd "startinsert!" + vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "close", { noremap = true, silent = true }) + end, + } + + -- Mk (make) terminal + local lazygit = Terminal:new { + cmd = "lazygit", + hidden = true, + direction = "float", + on_open = function(term) + vim.cmd "startinsert!" + vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "close", { noremap = true, silent = true }) + end, + } + -- Mk (make) terminal + local lazydocker = Terminal:new { + cmd = "lazydocker", + hidden = true, + direction = "float", + on_open = function(term) + vim.cmd "startinsert!" + vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "close", { noremap = true, silent = true }) + end, + } + + -- Scratch terminal + local scratch = Terminal:new { + cmd = "zsh", + hidden = true, + direction = "horizontal", + on_open = function(term) + vim.cmd "startinsert!" + vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "close", { noremap = true, silent = true }) + end, + } + -- Export toggle functions to module instead of global namespace + M.scooter_toggle = function() scooter:toggle() end + M.mk_toggle = function() mk:toggle() end + M.lazygit_toggle = function() lazygit:toggle() end + M.lazydocker_toggle = function() lazydocker:toggle() end + M.smartCommit_toggle = function() smartCommit:toggle() end + M.scratch_toggle = function() scratch:toggle() end +end + +return M diff --git a/lua/lazy_setup.lua b/lua/lazy_setup.lua new file mode 100644 index 0000000..8e1abfb --- /dev/null +++ b/lua/lazy_setup.lua @@ -0,0 +1,32 @@ +require("lazy").setup({ + { + "AstroNvim/AstroNvim", + version = "^6", -- Remove version tracking to elect for nightly AstroNvim + import = "astronvim.plugins", + opts = { -- AstroNvim options must be set here with the `import` key + mapleader = " ", -- This ensures the leader key must be configured before Lazy is set up + maplocalleader = ",", -- This ensures the localleader key must be configured before Lazy is set up + icons_enabled = true, -- Set to false to disable icons (if no Nerd Font is available) + pin_plugins = nil, -- Default will pin plugins when tracking `version` of AstroNvim, set to true/false to override + update_notifications = true, -- Enable/disable notification about running `:Lazy update` twice to update pinned plugins + }, + }, + { import = "community" }, + { import = "plugins" }, +} --[[@as LazySpec]], { + -- Configure any other `lazy.nvim` configuration options here + install = { colorscheme = { "astrotheme", "habamax" } }, + ui = { backdrop = 100 }, + performance = { + rtp = { + -- disable some rtp plugins, add more to your liking + disabled_plugins = { + "gzip", + "netrwPlugin", + "tarPlugin", + "tohtml", + "zipPlugin", + }, + }, + }, +} --[[@as LazyConfig]]) diff --git a/lua/plugins/astrocore.lua b/lua/plugins/astrocore.lua new file mode 100644 index 0000000..9cd958e --- /dev/null +++ b/lua/plugins/astrocore.lua @@ -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 terminals = require "config.terminals" + +terminals.setup() + +local file_filter = ignore_patterns.create_picker_filter() + +-- Open a snacks picker with trouble.nvim send-to-quickfix action bound to . +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 {}, { + [""] = { "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 = "win", + 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 = { + [""] = { "suspend", desc = "Suspend nvim (return with 'fg')" }, + ["Q"] = { "wqa", desc = "Save all buffers and quit Neovim" }, + [""] = { "wabd", 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"] = { "BufferLineCycleNext", desc = "Next buffer" }, + ["H"] = { "BufferLineCyclePrev", desc = "Previous buffer" }, + [""] = { "Neotree toggle reveal", desc = "Open Explorer (reveal current file)" }, + [""] = { + function() require("snacks").picker.smart() end, + desc = "Find files", + }, + ["b"] = { "BufferLinePick", desc = "Pick buffer" }, + ["f"] = { + function() require("snacks").picker.buffers() end, + desc = "Find buffers", + }, + [""] = { + 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", + }, + ["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", + }, + ["l"] = { + function() require("snacks").picker.lines() end, + desc = "Find in line", + }, + ["o"] = { "!gh repo view --web", desc = "Open Repo on Web" }, + [""] = { "w", desc = "Save buffer" }, + [""] = { "wbd", desc = "Save and close buffer" }, + [""] = { "tabnext", desc = "Next Tab" }, + [""] = { terminals.lazygit_toggle, desc = "Lazygit Toggle" }, + [""] = { "Octo issue list", desc = "List Issues" }, + [""] = { "Octo label", desc = "Manage Labels" }, + [""] = { "Octo pr list", desc = "List PRs" }, + ["s"] = { "Octo search", desc = "Octo Search" }, + [""] = { "!gh release list", desc = "List Releases" }, + ["d"] = { + function() require("snacks").picker.git_diff() end, + desc = "Search git diffs", + }, + [""] = { + 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" }, + ["d"] = { + function() require("snacks").picker.diagnostics() end, + desc = "Find diagnostics", + }, + ["l"] = { + function() require("snacks").picker.lines() end, + desc = "Find in line", + }, + ["t"] = { + function() require("snacks").picker.lines() end, + desc = "Find in line", + }, + ["w"] = { + function() require("snacks").picker.grep() end, + desc = "Find word", + }, + ["f"] = { + function() require("snacks").picker.git_files { transform = file_filter } end, + desc = "Find files", + }, + ["o"] = { + function() require("snacks").picker.recent() end, + desc = "Find recent files", + }, + ["p"] = { + function() require("snacks").picker.projects() end, + desc = "Find projects", + }, + ["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", + }, + ["p"] = { desc = "Find Package files" }, + ["m"] = { desc = "Find Module files" }, + ["g"] = { desc = "Find by Group" }, + ["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", + }, + ["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", + }, + ["gm"] = { + function() require("snacks").picker.files { cmd = "fd", args = { "Makefile" } } end, + desc = "Find Makefile files", + }, + ["gp"] = { + function() require("snacks").picker.files { cmd = "fd", args = { "package.json" } } end, + desc = "Find Package.json files", + }, + [""] = { + function() + if vim.b.toggle_number == 99 then + vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("", 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", + }, + [""] = { function() terminals.scratch_toggle() end, desc = "Open Scratch Terminal" }, + [""] = { "ClaudeCodeFocus", desc = "Toggle Claude Code" }, + [""] = { "OverseerRun", desc = "Run Overseer task" }, + ["d"] = { + function() with_trouble("diagnostics") end, + desc = "Search diagnostics ( sends to Trouble)", + }, + ["a"] = { + function() vim.lsp.buf.code_action() end, + desc = "Show code actions", + }, + ["s"] = { + function() with_trouble("lsp_symbols") end, + desc = "Search LSP symbols ( sends to Trouble)", + }, + ["S"] = { + function() with_trouble("lsp_workspace_symbols") end, + desc = "Search LSP workspace symbols ( sends to Trouble)", + }, + + ["u"] = { desc = "UI Toggles" }, + ["ud"] = { + function() require("snacks").toggle.diagnostics():toggle() end, + desc = "Toggle Diagnostics", + }, + ["un"] = { + function() require("snacks").toggle.line_number():toggle() end, + desc = "Toggle Line Numbers", + }, + ["ur"] = { + function() require("snacks").toggle.option("relativenumber"):toggle() end, + desc = "Toggle Relative Numbers", + }, + ["uw"] = { + function() require("snacks").toggle.option("wrap"):toggle() end, + desc = "Toggle Line Wrap", + }, + ["us"] = { + function() require("snacks").toggle.option("spell"):toggle() end, + desc = "Toggle Spelling", + }, + ["ui"] = { + function() require("snacks").toggle.inlay_hints():toggle() end, + desc = "Toggle Inlay Hints", + }, + ["ut"] = { + function() require("snacks").toggle.treesitter():toggle() end, + desc = "Toggle Treesitter", + }, + ["uc"] = { + function() require("snacks").toggle.option("conceallevel", { off = 0, on = 2 }):toggle() end, + desc = "Toggle Conceal", + }, + ["uI"] = { + function() require("snacks").toggle.indent():toggle() end, + desc = "Toggle Indent Guides", + }, + ["uz"] = { + function() require("snacks").toggle.zen():toggle() end, + desc = "Toggle Zen Mode", + }, + ["uZ"] = { + function() require("snacks").toggle.zoom():toggle() end, + desc = "Toggle Zoom", + }, + ["ua"] = { + function() require("snacks").toggle.animate():toggle() end, + desc = "Toggle Animations", + }, + ["uS"] = { + function() require("snacks").toggle.scroll():toggle() end, + desc = "Toggle Smooth Scroll", + }, + ["up"] = { + function() require("snacks").toggle.profiler():toggle() end, + desc = "Toggle Profiler", + }, + ["uh"] = { + function() require("snacks").toggle.profiler_highlights():toggle() end, + desc = "Toggle Profiler Highlights", + }, + ["ux"] = { + function() require("snacks").toggle.dim():toggle() end, + desc = "Toggle Dim Inactive", + }, + ["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 + ["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 = { + [""] = { "wa", desc = "Save buffer, and return to normal mode" }, + [""] = { "wabd", desc = "Save, close buffer, and return to normal mode" }, + [""] = { "wabd", desc = "Save, close buffer, and return to normal mode" }, + }, + v = { + [""] = { "Neotree toggle reveal", desc = "Open Explorer (reveal current file)" }, + [""] = { "wbd", desc = "Save and close buffer" }, + [""] = { "wbd", desc = "Save and close buffer" }, + [""] = { "ClaudeCodeSend", desc = "Send selection to Claude Code" }, + ["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 = { + [""] = { "ClaudeCodeFocus", desc = "Toggle Claude Code" }, + [""] = { "Neotree toggle reveal", desc = "Open Explorer (reveal current file)" }, + [""] = { function() vim.cmd 'normal! "+p' end, desc = "Paste from system clipboard" }, + ["f"] = { + function() require("snacks").picker.buffers() end, + desc = "Find buffers", + }, + [""] = { + function() + vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes([[]], true, false, true), "n", false) + vim.cmd "close" + end, + desc = "Exit terminal and close window", + }, + }, + }, + }, +} diff --git a/lua/plugins/astrolsp.lua b/lua/plugins/astrolsp.lua new file mode 100644 index 0000000..b8b121f --- /dev/null +++ b/lua/plugins/astrolsp.lua @@ -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", + }, + ["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, + }, +} diff --git a/lua/plugins/astroui.lua b/lua/plugins/astroui.lua new file mode 100644 index 0000000..0c49c1f --- /dev/null +++ b/lua/plugins/astroui.lua @@ -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", + }, +} diff --git a/lua/plugins/claudecode.lua b/lua/plugins/claudecode.lua new file mode 100644 index 0000000..22313e3 --- /dev/null +++ b/lua/plugins/claudecode.lua @@ -0,0 +1,60 @@ +-- Claude Code IDE integration via WebSocket MCP. +-- opens/focuses a near-fullscreen snacks float; the same key inside +-- the terminal hides it (toggle). Visual-mode sends the selection. +-- Neo-tree's is wired separately (see lua/plugins/neotree.lua). + +local toggle_key = "" + +---@type LazySpec +return { + "coder/claudecode.nvim", + dependencies = { "folke/snacks.nvim" }, + cmd = { + "ClaudeCode", + "ClaudeCodeFocus", + "ClaudeCodeSend", + "ClaudeCodeAdd", + "ClaudeCodeTreeAdd", + "ClaudeCodeSelectModel", + "ClaudeCodeDiffAccept", + "ClaudeCodeDiffDeny", + "ClaudeCodeStatus", + }, + keys = { + { toggle_key, "ClaudeCodeFocus", mode = { "n", "x" }, desc = "Toggle Claude Code" }, + { "am", "ClaudeCodeSelectModel", desc = "Select Claude model" }, + { "ar", "ClaudeCode --resume", desc = "Resume Claude" }, + { "aC", "ClaudeCode --continue", desc = "Continue Claude" }, + { "ab", "ClaudeCodeAdd %", desc = "Add current buffer to Claude" }, + { "ay", "ClaudeCodeDiffAccept", desc = "Accept Claude diff" }, + { "an", "ClaudeCodeDiffDeny", desc = "Deny Claude diff" }, + }, + opts = { + git_repo_cwd = true, + terminal = { + provider = "snacks", + ---@module "snacks" + ---@type snacks.win.Config|{} + snacks_win_opts = { + position = "float", + width = 0.95, + height = 0.95, + border = "rounded", + backdrop = 60, + keys = { + claude_hide = { + toggle_key, + function(self) self:hide() end, + mode = { "t", "n" }, + desc = "Hide Claude Code", + }, + }, + }, + }, + diff_opts = { + layout = "vertical", + open_in_new_tab = false, + }, + }, + config = true, +} diff --git a/lua/plugins/conform.lua b/lua/plugins/conform.lua new file mode 100644 index 0000000..f5c2fd5 --- /dev/null +++ b/lua/plugins/conform.lua @@ -0,0 +1,86 @@ +-- 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 "." prefix (LSP CodeActionKind is hierarchical). +local SAFE_KINDS = { + "source", + "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 + +local function apply_result(client, bufnr, result) + if not result then return end + for _, action in ipairs(result) do + 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 + +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, +} diff --git a/lua/plugins/kitty.lua b/lua/plugins/kitty.lua new file mode 100644 index 0000000..443b39d --- /dev/null +++ b/lua/plugins/kitty.lua @@ -0,0 +1,42 @@ +local function t_nav(fn) + return function() + vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes([[]], 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 `); 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 . Resize bindings () are left intact. + specs = { + { + "AstroNvim/astrocore", + opts = function(_, opts) + local m = opts.mappings.n + m[""] = false + m[""] = false + m[""] = false + m[""] = false + end, + }, + }, + keys = { + {"", function()require("kitty-navigator").navigateLeft()end, desc = "Move left a Split", mode = {"n"}}, + {"", function()require("kitty-navigator").navigateDown()end, desc = "Move down a Split", mode = {"n"}}, + {"", function()require("kitty-navigator").navigateUp()end, desc = "Move up a Split", mode = {"n"}}, + {"", function()require("kitty-navigator").navigateRight()end, desc = "Move right a Split", mode = {"n"}}, + {"", t_nav(function()require("kitty-navigator").navigateLeft()end), desc = "Move left a Split", mode = {"t"}}, + {"", t_nav(function()require("kitty-navigator").navigateDown()end), desc = "Move down a Split", mode = {"t"}}, + {"", t_nav(function()require("kitty-navigator").navigateUp()end), desc = "Move up a Split", mode = {"t"}}, + {"", t_nav(function()require("kitty-navigator").navigateRight()end), desc = "Move right a Split", mode = {"t"}}, + }, +} diff --git a/lua/plugins/mason.lua b/lua/plugins/mason.lua new file mode 100644 index 0000000..2d79b5f --- /dev/null +++ b/lua/plugins/mason.lua @@ -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", + }, + }, + }, +} diff --git a/lua/plugins/neotree.lua b/lua/plugins/neotree.lua new file mode 100644 index 0000000..86c2ee6 --- /dev/null +++ b/lua/plugins/neotree.lua @@ -0,0 +1,341 @@ +--- Neo-tree configuration with dynamic pattern filtering +--- @module plugins.neotree + +-- Import shared modules +local ignore_patterns = require "config.ignore_patterns" +local terminals = require "config.terminals" + +---@type LazySpec +return { + { + "neo-tree.nvim", + init = function() + vim.api.nvim_create_autocmd("DirChanged", { + group = vim.api.nvim_create_augroup("NeoTreeRefreshPatterns", { clear = true }), + callback = function() + local ok, manager = pcall(require, "neo-tree.sources.manager") + if ok then pcall(manager.refresh, "filesystem") end + end, + }) + end, + opts = function() + -- Get all hide patterns from shared module + local hide_patterns = ignore_patterns.get_all_patterns() + + return { + + popup_border_style = "rounded", + enable_git_status = true, + enable_diagnostics = true, + sort_case_insensitive = false, + auto_expand_width = true, + git_status_async = true, -- Asynchronous git status. Improves performance. + hide_root_node = true, -- Hide the root node. + retain_hidden_root_indent = true, -- IF the root node is hidden, keep the indentation anyhow. + use_libuv_file_watcher = false, + sort = { + sorter = "name", + }, + window = { + position = "left", + width = 34, + mappings = { + ["H"] = "navigate_up", + ["L"] = function(state) + require("neo-tree.sources.filesystem.commands").set_root(state) + -- Refresh patterns when changing root + vim.defer_fn(function() + local new_patterns = ignore_patterns.get_all_patterns() + require("neo-tree").config.filesystem.filtered_items.hide_by_pattern = new_patterns + require("neo-tree.sources.manager").refresh "filesystem" + end, 50) + end, + [""] = "toggle_hidden", + ["."] = "toggle_hidden", + ["/"] = "fuzzy_finder", + ["f"] = "filter_on_submit", + [""] = "clear_filter", + [""] = "open_and_close_neotree", + [""] = "open", + -- Claude Code: add file under cursor to context + [""] = function() vim.cmd "ClaudeCodeTreeAdd" end, + -- Git keybindings from astrocore + ["o"] = function() vim.cmd "!gh repo view --web" end, + ["h"] = function() + require("snacks").terminal("gh dash", { + hidden = true, + auto_close = false, + interactive = true, + }) + end, + ["g"] = function() + require("snacks").terminal("lazygit", { + hidden = true, + auto_close = true, + interactive = true, + }) + end, + ["d"] = function() require("snacks").picker.git_diff() end, + ["b"] = function() require("snacks").picker.git_branches() end, + -- Terminal keybindings from astrocore + ["m"] = terminals.mk_toggle, + ["l"] = function() + require("snacks").terminal("lazydocker", { + hidden = true, + auto_close = true, + start_in_insert = true, + interactive = true, + }) + end, + ["du"] = function() + require("snacks").terminal("devbox services up", { + hidden = true, + auto_close = false, + start_in_insert = true, + interactive = true, + }) + end, + ["dd"] = function() + require("snacks").terminal("devbox services down", { + hidden = true, + auto_close = false, + start_in_insert = true, + interactive = true, + }) + end, + ["da"] = function() + require("snacks").terminal("devbox services attach", { + hidden = true, + auto_close = false, + start_in_insert = true, + interactive = true, + }) + end, + ["."] = terminals.yazi_toggle, + ["t"] = function() require("snacks").terminal() end, + -- Find keybindings from astrocore + -- These Find keybindings are defined in astrocore.lua + -- NeoTree only needs the basic navigation and terminal bindings + -- Mappings for Mason and formatting + ["N"] = function(state) + local node = state.tree:get_node() + local path = node.type == "directory" and node.path or vim.fn.fnamemodify(node.path, ":h") + + -- Check if running on Arch Linux + local is_arch = vim.fn.filereadable "/etc/arch-release" == 1 + + if is_arch then + -- Use uwsm to launch alacritty with yazi on Arch Linux + vim.fn.jobstart( + string.format("uwsm app -- alacritty --working-directory %s -e yazi", vim.fn.shellescape(path)), + { + detach = true, + } + ) + else + -- Fallback to direct alacritty launch with yazi on other systems + vim.fn.jobstart(string.format("alacritty --working-directory %s -e yazi", vim.fn.shellescape(path)), { + detach = true, + }) + end + end, + }, + header = { + highlight = "NeoTreeHeader", + }, + }, + default_component_configs = { + container = { + enable_character_fade = true, + }, + indent = { + indent_size = 2, + padding = 1, -- extra padding on left hand side + -- indent guides + with_markers = true, + indent_marker = "│", + last_indent_marker = "└", + highlight = "NeoTreeIndentMarker", + -- expander config, needed for nesting files + expander_collapsed = "", + expander_expanded = "", + expander_highlight = "NeoTreeExpander", + }, + name = { + trailing_slash = false, -- append a trailing slash to folder names + use_git_status_colors = true, -- use git status colors instead of the default colors + highlight = "NeoTreeFileName", + }, + git_status = { + symbols = { + -- Change type + added = "", -- or "✚", but this is redundant info if you use git_status_colors on the name + modified = "", -- or "", but this is redundant info if you use git_status_colors on the name + deleted = "✖", -- this can only be used in the git_status source + renamed = "󰁕", -- this can only be used in the git_status source + -- Status type + untracked = "", + ignored = "", + unstaged = "󰄱", + staged = "", + conflict = "", + }, + }, + -- If you don't want to use these columns, you can set `enabled = false` for each of them individually + file_size = { + enabled = true, + width = 12, -- width of the column + required_width = 48, -- min width of window required to show this column + }, + type = { + enabled = true, + width = 10, -- width of the column + required_width = 122, -- min width of window required to show this column + }, + last_modified = { + enabled = true, + width = 20, -- width of the column + required_width = 88, -- min width of window required to show this column + }, + created = { + enabled = true, + width = 20, -- width of the column + required_width = 110, -- min width of window required to show this column + }, + symlink_target = { + enabled = false, + }, + }, + + buffers = { + follow_current_file = { + enabled = true, + }, + }, + + -- Filesystem specific settings + filesystem = { + commands = { + -- Refresh patterns when changing directories + refresh_patterns = function(state) + -- Re-read patterns when navigating + local new_patterns = ignore_patterns.get_all_patterns() + state.filtered_items.hide_by_pattern = new_patterns + require("neo-tree.sources.manager").refresh "filesystem" + end, + -- If item is a file it will close neotree after opening it. + open_and_close_neotree = function(state) + require("neo-tree.sources.filesystem.commands").open(state) + local tree = state.tree + local success, node = pcall(tree.get_node, tree) + if not success then return end + if node.type == "file" then require("neo-tree.command").execute { action = "close" } end + end, + + -- Custom command to open Mason + mason_open = function() vim.cmd "Mason" end, + + -- Custom command to format a file using the LSP + format_file = function(state) + local node = state.tree:get_node() + if node and node.type == "file" then + -- Format the file in a temporary buffer without opening it in a window + local bufnr = vim.api.nvim_create_buf(false, true) + vim.api.nvim_buf_set_name(bufnr, node.path) + vim.api.nvim_buf_load(bufnr) + vim.lsp.buf.format { bufnr = bufnr, async = false, timeout_ms = 5000 } + vim.api.nvim_buf_call(bufnr, function() vim.cmd "write" end) + vim.notify("Formatted " .. vim.fs.basename(node.path), vim.log.levels.INFO, { title = "Neo-tree" }) + else + vim.notify("Not a file", vim.log.levels.WARN, { title = "Neo-tree" }) + end + end, + }, + bind_to_cwd = true, + follow_current_file = { + enabled = true, + leave_dirs_open = false, + }, + filtered_items = { + force_visible_in_empty_folder = false, + group_empty = false, + show_hidden_count = false, + hide_dotfiles = false, + hide_gitignored = true, + hide_by_pattern = hide_patterns, + always_show = {}, + always_show_by_pattern = {}, + visible = function(item) + -- Hide all symlinks + if item.type == "link" then return false end + return true + end, + hide_by_name = { + -- "contracts", + -- "crypto", + -- "CONSTITUTION.md", + -- "CONTRIBUTING.md", + -- "api", + -- "turbo.json", + -- "OpenCode.md", + -- "AGENT.md", + -- "AGENTS.md", + -- "svgo.config.mjs", + -- ".prettierrc.cjs", + -- ".eslintrc.cjs", + -- "tsconfig.json", + -- "tsconfig.prod.json", + -- ".prettierignore", + -- "CONVENTIONS.md", + -- ".gitkeep", + -- ".source", + -- "settings.json", + -- ".gitignore", + -- "analysis_options.yaml", + -- "slumber.yml", + -- ".eslintignore", + -- "CONTRIBUTING.md", + -- "CHANGELOG.md", + -- "devbox.d", + -- "env", + -- ".husky", + -- "translations", + -- "LICENSE.md", + -- ".envrc", + -- "CLAUDE.md", + -- "chains", + -- "test", + -- ".golangci.yml", + -- "go.mod", + -- "pnpm-workspace.yaml", + -- "examples", + -- "bridge", + -- "client", + }, + never_show_by_pattern = ignore_patterns.never_show_patterns, + never_show = ignore_patterns.never_show, + }, + }, + diagnostics = { + enable = false, + icons = { + hint = "", + info = "", + warning = "", + error = "", + }, + }, + + source_selector = { + winbar = false, + statusline = false, + }, + + -- Main sources + sources = { + "filesystem", + }, + } + end, + }, +} diff --git a/lua/plugins/neovim.lua b/lua/plugins/neovim.lua new file mode 100644 index 0000000..a3dadcc --- /dev/null +++ b/lua/plugins/neovim.lua @@ -0,0 +1,14 @@ +-- neovim.lua — auto-generated by iNiR. Use 99-inir-user.lua for overrides. +return { + { + "yukazakiri/inir.nvim", + priority = 1000, + opts = {}, + }, + { + "LazyVim/LazyVim", + opts = { + colorscheme = "inir", + }, + }, +} diff --git a/lua/plugins/none-ls.lua b/lua/plugins/none-ls.lua new file mode 100644 index 0000000..2b0ed18 --- /dev/null +++ b/lua/plugins/none-ls.lua @@ -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, +} diff --git a/lua/plugins/treesitter.lua b/lua/plugins/treesitter.lua new file mode 100644 index 0000000..3a9afe9 --- /dev/null +++ b/lua/plugins/treesitter.lua @@ -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 + }, + }, + }, +} diff --git a/lua/plugins/user.lua b/lua/plugins/user.lua new file mode 100644 index 0000000..fc9aff0 --- /dev/null +++ b/lua/plugins/user.lua @@ -0,0 +1,92 @@ + +-- You can also add or configure plugins by creating files in this `plugins/` folder +-- PLEASE REMOVE THE EXAMPLES YOU HAVE NO INTEREST IN BEFORE ENABLING THIS FILE +-- Here are some examples: + +---@type LazySpec +return { +{ + "ankushbhagats/match.nvim", + config = true, +}, + -- == Examples of Adding Plugins == + + "andweeb/presence.nvim", + { + "ray-x/lsp_signature.nvim", + event = "BufRead", + config = function() require("lsp_signature").setup() end, + }, + + -- == Examples of Overriding Plugins == + + -- customize dashboard options + { + "folke/snacks.nvim", + opts = { + dashboard = { + preset = { + header = table.concat({ + " █████ ███████ ████████ ██████ ██████ ", + "██ ██ ██ ██ ██ ██ ██ ██", + "███████ ███████ ██ ██████ ██ ██", + "██ ██ ██ ██ ██ ██ ██ ██", + "██ ██ ███████ ██ ██ ██ ██████ ", + "", + "███  ██ ██  ██ ██ ███  ███", + "████  ██ ██  ██ ██ ████  ████", + "██ ██  ██ ██  ██ ██ ██ ████ ██", + "██  ██ ██  ██  ██  ██ ██  ██  ██", + "██   ████   ████   ██ ██      ██", + }, "\n"), + }, + }, + }, + }, + + -- You can disable default plugins as follows: + { "max397574/better-escape.nvim", enabled = false }, + + -- You can also easily customize additional setup of plugins that is outside of the plugin's setup call + { + "L3MON4D3/LuaSnip", + config = function(plugin, opts) + -- add more custom luasnip configuration such as filetype extend or custom snippets + local luasnip = require "luasnip" + luasnip.filetype_extend("javascript", { "javascriptreact" }) + + -- include the default astronvim config that calls the setup call + require "astronvim.plugins.configs.luasnip"(plugin, opts) + end, + }, + + { + "windwp/nvim-autopairs", + config = function(plugin, opts) + require "astronvim.plugins.configs.nvim-autopairs"(plugin, opts) -- include the default astronvim config that calls the setup call + -- add more custom autopairs configuration such as custom rules + local npairs = require "nvim-autopairs" + local Rule = require "nvim-autopairs.rule" + local cond = require "nvim-autopairs.conds" + npairs.add_rules( + { + Rule("$", "$", { "tex", "latex" }) + -- don't add a pair if the next character is % + :with_pair(cond.not_after_regex "%%") + -- don't add a pair if the previous character is xxx + :with_pair( + cond.not_before_regex("xxx", 3) + ) + -- don't move right when repeat character + :with_move(cond.none()) + -- don't delete if the next character is xx + :with_del(cond.not_after_regex "xx") + -- disable adding a newline when you press + :with_cr(cond.none()), + }, + -- disable for .vim files, but it work for another filetypes + Rule("a", "a", "-vim") + ) + end, + }, +} diff --git a/lua/polish.lua b/lua/polish.lua new file mode 100644 index 0000000..eb772c8 --- /dev/null +++ b/lua/polish.lua @@ -0,0 +1,47 @@ +-- if true then return end -- WARN: REMOVE THIS LINE TO ACTIVATE THIS FILE + +-- This will run last in the setup process. +-- This is just pure lua so anything that doesn't +-- fit in the normal config locations above can go here +-- +-- + + +local overseer = require "overseer" + +overseer.setup { + strategy = { + "toggleterm", + use_shell = false, + direction = "horizontal", + size = function() return math.floor(vim.o.lines * 0.2) end, + auto_scroll = true, + close_on_exit = false, + quit_on_exit = "success", + open_on_start = true, + hidden = true, + }, + -- Persistent tasks: keep completed runs around until the user disposes them. + component_aliases = { + default = { + "on_exit_set_status", + "on_complete_notify", + }, + }, +} + +local task_list = require "overseer.task_list" + +vim.api.nvim_create_user_command("OverseerRestartLast", function() + local tasks = overseer.list_tasks { + status = { overseer.STATUS.SUCCESS, overseer.STATUS.FAILURE, overseer.STATUS.CANCELED }, + sort = task_list.sort_finished_recently, + } + if vim.tbl_isempty(tasks) then + vim.notify("No completed tasks to restart", vim.log.levels.WARN) + return + end + overseer.run_action(tasks[1], "restart") +end, { desc = "Restart the most recently completed Overseer task" }) + +vim.cmd.cnoreabbrev "OS OverseerShell"