From ec61cbe07250ef15e9abd7afc9e45759aa868aee Mon Sep 17 00:00:00 2001 From: Prad Nukala Date: Fri, 19 Sep 2025 15:37:02 -0400 Subject: [PATCH] refactor: remove redundant buffer tracking mechanism --- lua/plugins/astrocore.lua | 133 +++---------- lua/plugins/neotree.lua | 396 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 420 insertions(+), 109 deletions(-) create mode 100644 lua/plugins/neotree.lua diff --git a/lua/plugins/astrocore.lua b/lua/plugins/astrocore.lua index e2a75ca..8547aff 100644 --- a/lua/plugins/astrocore.lua +++ b/lua/plugins/astrocore.lua @@ -1,8 +1,5 @@ local Terminal = require("toggleterm.terminal").Terminal --- Track closed buffers -local closed_buffers = {} - -- Shared ignore patterns from neotree configuration local ignore_patterns = { -- Hidden patterns @@ -207,7 +204,6 @@ return { "lsp", -- highest priority is getting workspace from running language servers { ".git", "_darcs", ".hg", ".bzr", ".svn" }, -- next check for a version controlled parent directory { - "go.work", "package.json", "lua", "Cargo.toml", @@ -223,7 +219,7 @@ return { -- automatically update working directory (update manually with `:AstroRoot`) autochdir = true, -- scope of working directory to change ("global"|"tab"|"win") - scope = "win", -- Changed from "win" to "global" to make directory changes apply globally + scope = "global", -- Changed from "win" to "global" to make directory changes apply globally -- show notification on every working directory change notify = false, }, @@ -238,7 +234,7 @@ return { -- Diagnostics configuration (for vim.diagnostics.config({...})) when diagnostics are on diagnostics = { - virtual_text = false, + virtual_text = true, underline = true, }, -- vim options can be configured here @@ -262,33 +258,12 @@ return { -- first key is the mode n = { -- navigate buffer tabs - [""] = { - function() - -- Save the buffer path before closing - local bufname = vim.api.nvim_buf_get_name(0) - if bufname ~= "" then - table.insert(closed_buffers, bufname) - -- Keep only the last 10 closed buffers - if #closed_buffers > 10 then table.remove(closed_buffers, 1) end - end - vim.cmd "wa" - vim.cmd "bd" - end, - desc = "Save and close buffer", - }, + [""] = { "wabd", desc = "Save and close buffer" }, -- Added C-x to save and close buffer ["F"] = { "za", desc = "Toggle fold under cursor" }, ["L"] = { "BufferLineCycleNext", desc = "Next buffer" }, ["H"] = { "BufferLineCyclePrev", desc = "Previous buffer" }, - [""] = { - function() require("snacks").explorer.reveal() end, - desc = "Reveal file in Explorer", - }, + [""] = { "Neotree toggle", desc = "Open Explorer" }, [""] = { "OverseerRun", desc = "Run Overseer" }, - [""] = { "b#", desc = "Return to last buffer" }, - ["e"] = { - function() require("snacks").explorer.reveal() end, - desc = "Reveal file in Explorer", - }, [""] = { function() require("snacks").picker.smart() end, desc = "Find files", @@ -316,18 +291,6 @@ return { end, desc = "Toggle all buffer groups", }, - ["z"] = { - function() - if #closed_buffers > 0 then - local last_closed = table.remove(closed_buffers) - vim.cmd("e " .. vim.fn.fnameescape(last_closed)) - vim.notify("Reopened: " .. vim.fn.fnamemodify(last_closed, ":t")) - else - vim.notify("No recently closed buffer found", vim.log.levels.WARN) - end - end, - desc = "Reopen last closed buffer", - }, -- Quick group toggles ["l"] = { function() require("snacks").picker.lines() end, @@ -425,10 +388,6 @@ return { function() require("snacks").picker.diagnostics() end, desc = "Find diagnostics", }, - ["l"] = { - function() require("snacks").picker.lines() end, - desc = "Find diagnostics", - }, ["f"] = { function() require("snacks").picker.git_files { transform = file_filter } end, desc = "Find files", @@ -459,27 +418,25 @@ return { }, ["go"] = { "ObsidianSearch", desc = "Find in Obsidian" }, ["p"] = { desc = "Find Package files" }, - ["P"] = { + ["pc"] = { function() require("snacks").picker.files { - dirs = { "/home/prad/code/github.com/sonr-io/sonr/proto" }, - ft = { "proto" }, + dirs = { "/home/prad/code/github.com/sonr-io/sonr/packages/cli" }, + exclude = { "packages/cli/dist" }, + ft = { "ts", "tsx", "js" }, } end, - desc = "Find Proto files", + desc = "Find @sonr.io/cli files", }, - ["W"] = { + ["pe"] = { function() require("snacks").picker.files { - dirs = { - "/home/prad/code/github.com/sonr-io/sonr/packages", - "/home/prad/code/github.com/sonr-io/sonr/web", - }, - exclude = { "packages/**/dist", "web/**/dist" }, - ft = { "ts", "tsx", "js", "html", "css", "json", "yaml" }, + dirs = { "/home/prad/code/github.com/sonr-io/sonr/packages/es" }, + exclude = { "packages/es/dist" }, + ft = { "ts", "tsx", "js" }, } end, - desc = "Find Web Dev files", + desc = "Find @sonr.io/es files", }, ["pp"] = { function() @@ -620,37 +577,29 @@ return { end, desc = "Find dotfiles", }, - ["c"] = { + ["c."] = { function() require("snacks").picker.files { - dirs = { "/home/prad/.local/share/chezmoi/dot_config" }, + dirs = { "/home/prad/.local/share/chezmoi" }, } end, desc = "Find chezmoi config files", }, - ["e"] = { + ["cn"] = { function() require("snacks").picker.files { - dirs = { "/home/prad/.local/share/chezmoi/extensions" }, + dirs = { "/home/prad/code/github.com/prnk28/nvim" }, } end, - desc = "Find chezmoi extension files", + desc = "Find nvim files", }, - ["l"] = { + ["cs"] = { function() require("snacks").picker.files { - dirs = { "/home/prad/.local/share/chezmoi/dot_local" }, + dirs = { "/home/prad/.local/share/chezmoi/dot_local/share/services" }, } end, - desc = "Find chezmoi local files", - }, - ["n"] = { - function() - require("snacks").picker.files { - dirs = { "/home/prad/.local/share/chezmoi/dot_config/nvim" }, - } - end, - desc = "Find chezmoi neovim files", + desc = "Find Service files", }, ["a"] = { function() vim.lsp.buf.code_action() end, desc = "LSP Code Action" }, ["h"] = { function() vim.lsp.buf.hover() end, desc = "LSP Hover" }, @@ -674,46 +623,12 @@ return { [""] = { "wabd", desc = "Save, close buffer, and return to normal mode" }, -- Added C-x for insert mode }, v = { - [""] = { - function() - -- Toggle explorer using the proper Snacks.explorer API - local snacks = require "snacks" - -- Check if there's an active explorer picker - local pickers = snacks.picker.get { source = "explorer" } - if #pickers > 0 then - -- Close the explorer - for _, picker in ipairs(pickers) do - picker:close() - end - else - -- Open the explorer - snacks.explorer() - end - end, - desc = "Toggle Explorer", - }, + [""] = { "Neotree toggle", desc = "Open Explorer" }, [""] = { "wbd", desc = "Save and close buffer" }, -- Modified to save and close buffer [""] = { "wbd", desc = "Save and close buffer" }, -- Added C-x for visual mode }, t = { - [""] = { - function() - -- Toggle explorer using the proper Snacks.explorer API - local snacks = require "snacks" - -- Check if there's an active explorer picker - local pickers = snacks.picker.get { source = "explorer" } - if #pickers > 0 then - -- Close the explorer - for _, picker in ipairs(pickers) do - picker:close() - end - else - -- Open the explorer - snacks.explorer() - end - end, - desc = "Toggle Explorer", - }, + [""] = { "Neotree toggle", desc = "Open Explorer" }, ["f"] = { function() require("snacks").picker.buffers() end, desc = "Find buffers", diff --git a/lua/plugins/neotree.lua b/lua/plugins/neotree.lua new file mode 100644 index 0000000..202e44e --- /dev/null +++ b/lua/plugins/neotree.lua @@ -0,0 +1,396 @@ +-- Function to read patterns from .rgignore file +local function read_rgignore_patterns() + local patterns = {} + local git_root = vim.fn.systemlist("git rev-parse --show-toplevel")[1] + + if git_root and git_root ~= "" then + local rgignore_path = git_root .. "/.rgignore" + local file = io.open(rgignore_path, "r") + + if file then + for line in file:lines() do + -- Skip comments and empty lines + if line ~= "" and not line:match "^#" then + -- Convert ripgrep patterns to neo-tree patterns + -- Remove leading ./ if present + line = line:gsub("^%./", "") + -- Add the pattern + table.insert(patterns, line) + end + end + file:close() + end + end + + return patterns +end + +return { + { + "neo-tree.nvim", + opts = function() + -- Get patterns from .rgignore + local rgignore_patterns = read_rgignore_patterns() + + -- Default patterns + local default_patterns = { + "chain_*.json", + "Library", + ".typecopy", + ".python-version", + "*.pb.go", + "*config.*.js", + "*config.js", + "deps.mjs", + ".parcelrc", + "worker-configuration.d.ts", + "wrangler.jsonc", + "*.pkl.go", + ".trunk", + ".config", + ".cz.toml", + "*_mock.go", + } + + -- Merge patterns + local hide_patterns = vim.list_extend(vim.list_extend({}, default_patterns), rgignore_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"] = "set_root", + [""] = "toggle_hidden", + ["."] = "toggle_hidden", + ["/"] = "fuzzy_finder", + ["f"] = "filter_on_submit", + [""] = "clear_filter", + [""] = "open_and_close_neotree", + [""] = "open", + -- 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"] = function() _G.Mk_toggle() end, + ["j"] = function() _G.Lazyjournal_toggle() end, + ["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, + ["."] = function() _G.Yazi_toggle() end, + ["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 + }, + 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 = { + -- 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, + 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 = { + "*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", + ".aider.tags.cache.v4", + "*.iml", + "Icon?", + "iCloud~", + "com~", + "*.icns", + ".conform*", + ".null-ls_*", + }, + never_show = { + ".git", + "pnpm-lock.yaml", + ".next", + ".task", + ".devbox", + ".dart_tool", + ".idea", + ".metadata", + ".venv", + ".gradle", + "gradle.bat", + ".aider.chat.history.md", + ".aider.input.history", + ".aider.tags.cache.v3", + ".devcontainer", + "heighliner", + ".tmp", + "go.work.sum", + ".DS_Store", + ".git", + "LICENSE", + "tmp", + "sonr.log", + "DISCUSSION_TEMPLATE", + "ISSUE_TEMPLATE", + ".devbox", + ".timemachine", + "junit.xml", + ".jj", + ".spawn", + ".turbo", + }, + }, + }, + diagnostics = { + enable = false, + icons = { + hint = "", + info = "", + warning = "", + error = "", + }, + }, + + source_selector = { + winbar = false, + statusline = false, + }, + + -- Main sources + sources = { + "filesystem", + }, + } + end, + }, +}