From f22dcfe6134a5cf31f92e1dcd6538010da4ef4b1 Mon Sep 17 00:00:00 2001 From: Micah Halter Date: Fri, 26 Jan 2024 08:48:06 -0500 Subject: [PATCH] feat: clean up rooter and add toggle function --- README.md | 36 ++++++++++++++++++++++++++++-------- lua/astrocore/config.lua | 11 ----------- lua/astrocore/init.lua | 31 +++++++++++++++++-------------- lua/astrocore/rooter.lua | 39 +++++++++++++++++++++++---------------- lua/astrocore/toggles.lua | 12 ++++++++++++ 5 files changed, 80 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 6fa41a7..d3d4f96 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ AstroCore provides the core Lua API that powers [AstroNvim](https://github.com/A - Easy toggles of UI/UX elements and features - Universal interface for setting up git worktrees - Tab local buffer management for a clean `tabline` +- Project root detection with automatic `cd` features - Session management with [resession.nvim][resession] ## ⚡️ Requirements @@ -22,25 +23,25 @@ AstroCore provides the core Lua API that powers [AstroNvim](https://github.com/A Install the plugin with the lazy plugin manager: ```lua -{ +return { "AstroNvim/astrocore", dependencies = { "nvim-lua/plenary.nvim" }, lazy = false, -- disable lazy loading priority = 10000, -- load AstroCore first opts = { -- set configuration options as described below - } + }, } ``` > 💡 If you want to enable session management with [resession.nvim][resession], enable it in the setup: ```lua -require('resession').setup({ - extensions = { - astrocore = {} - } -}) +require("resession").setup { + extensions = { + astrocore = {}, + }, +} ``` ## ⚙️ Configuration @@ -49,7 +50,7 @@ require('resession').setup({ ```lua ---@type AstroCoreConfig -{ +local opts = { -- easily configure auto commands autocmds = { -- first key is the `augroup` (:h augroup) @@ -120,6 +121,25 @@ require('resession').setup({ git_worktrees = { { toplevel = vim.env.HOME, gitdir = vim.env.HOME .. "/.dotfiles" }, }, + -- Configure project root detection, check status with `:AstroRootInfo` + rooter = { + -- list of detectors in order of prevalence, elements can be: + -- "lsp" : lsp detection + -- string[] : a list of directory patterns to look for + -- fun(bufnr: integer): string|string[] : a function that takes a buffer number and outputs detected roots + detector = { "lsp", { ".git", "_darcs", ".hg", ".bzr", ".svn", "lua", "Makefile", "package.json" } }, + -- ignore things from root detection + ignore = { + servers = {}, -- list of language server names to ignore (Ex. { "efm" }) + dirs = {}, -- list of directory patterns (Ex. { "~/.cargo/*" }) + }, + -- whether or not to disable automatic working directory updating (update with `:AstroRoot`) + autochdir = true, + -- scope of working directory to change ("global"|"tab"|"win") + scope = "global", + -- whether or not to notify on every working directory change + notify = false, + }, -- Configuration table of session options for AstroNvim's session management powered by Resession sessions = { -- Configure auto saving diff --git a/lua/astrocore/config.lua b/lua/astrocore/config.lua index c393c22..dc41ac6 100644 --- a/lua/astrocore/config.lua +++ b/lua/astrocore/config.lua @@ -249,17 +249,6 @@ local M = { notifications = true, }, git_worktrees = nil, - -- enable by default once tested - -- rooter = { - -- detector = { "lsp", { ".git" } }, - -- ignore = { - -- dirs = {}, - -- servers = {}, - -- }, - -- scope = "global", - -- autochdir = true, - -- notify = false, - -- }, rooter = false, sessions = { autosave = { last = true, cwd = true }, diff --git a/lua/astrocore/init.lua b/lua/astrocore/init.lua index f7e8ade..3fd04c1 100644 --- a/lua/astrocore/init.lua +++ b/lua/astrocore/init.lua @@ -374,6 +374,7 @@ function M.setup(opts) end end + -- initialize rooter if M.config.rooter then local root_config = M.config.rooter --[[@as AstroCoreRooterOpts]] vim.api.nvim_create_user_command( @@ -388,26 +389,28 @@ function M.setup(opts) ) local group = vim.api.nvim_create_augroup("rooter", { clear = true }) -- clear the augroup no matter what - if root_config.autochdir then - vim.api.nvim_create_autocmd({ "VimEnter", "BufEnter" }, { + vim.api.nvim_create_autocmd({ "VimEnter", "BufEnter" }, { + nested = true, + group = group, + desc = "Root detection when entering a buffer", + callback = function(args) + if root_config.autochdir then require("astrocore.rooter").root(args.buf) end + end, + }) + if vim.tbl_contains(root_config.detector or {}, "lsp") then + vim.api.nvim_create_autocmd("LspAttach", { nested = true, group = group, - desc = "Root detection when entering a buffer", - callback = function(args) require("astrocore.rooter").root(args.buf) end, - }) - if vim.tbl_contains(root_config.detector or {}, "lsp") then - vim.api.nvim_create_autocmd("LspAttach", { - nested = true, - group = group, - desc = "Root detection on LSP attach", - callback = function(args) + desc = "Root detection on LSP attach", + callback = function(args) + if root_config.autochdir then local server = assert(vim.lsp.get_client_by_id(args.data.client_id)).name if not vim.tbl_contains(vim.tbl_get(root_config, "ignore", "servers") or {}, server) then require("astrocore.rooter").root(args.buf) end - end, - }) - end + end + end, + }) end end end diff --git a/lua/astrocore/rooter.lua b/lua/astrocore/rooter.lua index a54dbfc..ee5a4a8 100644 --- a/lua/astrocore/rooter.lua +++ b/lua/astrocore/rooter.lua @@ -2,6 +2,10 @@ --- ---Utilities necessary for automatic root detectoin --- +---This module is heavily inspired by LazyVim and project.nvim +---https://github.com/ahmedkhalf/project.nvim +---https://github.com/LazyVim/LazyVim/blob/98db7ec0d287adcd8eaf6a93c4a392f588b5615a/lua/lazyvim/util/root.lua +--- ---This module can be loaded with `local rooter = require "astrocore.rooter"` --- ---copyright 2023 @@ -11,6 +15,11 @@ local M = { detectors = {} } ---@type AstroCoreRooterOpts local config = require("astrocore").config.rooter +local vim_autochdir + +local notify = function(msg, level) + require("astrocore").notify(msg, level or vim.log.levels.INFO, { title = "AstroNvim Rooter" }) +end ---@class AstroCoreRooterRoot ---@field paths string[] @@ -119,13 +128,13 @@ function M.detect(bufnr, all) end --- Get information information about the current root ----@param silent integer? whether or not to notify with verbose details ----@return string the currently detected root -function M.info(silent) - local roots = M.detect(0, true) - if not silent then +function M.info() + local lines = {} + if vim_autochdir then + table.insert(lines, "Rooting disabled when `autochdir` is set") + else + local roots = M.detect(0, true) local first = true - local lines = {} for _, root in ipairs(roots) do for _, path in ipairs(root.paths) do local surround = first and "**" or "" @@ -154,9 +163,8 @@ function M.info(silent) if setting then table.insert(lines, key .. " = " .. vim.inspect(setting)) end end table.insert(lines, "```") - require("astrocore").notify(table.concat(lines, "\n"), vim.log.levels.INFO, { title = "AstroNvim Rooter" }) end - return roots[1] and roots[1].paths[1] or vim.loop.cwd() + notify(table.concat(lines, "\n")) end --- Set the current directory to a given root @@ -177,7 +185,7 @@ function M.set_pwd(root) vim.api.nvim_err_writeln(("Unable to parse scope: %s"):format(config.scope)) end - if config.notify then vim.notify("Set CWD to " .. path .. " using " .. vim.inspect(root.spec)) end + if config.notify then notify(("Set CWD to `%s`"):format(path)) end end return true end @@ -205,17 +213,16 @@ function M.exists(path) return vim.fn.empty(vim.fn.glob(path)) == 0 end function M.root(bufnr) -- add `autochdir` protection local autochdir = vim.opt.autochdir:get() - if not M.disabled and autochdir then - require("astrocore").notify("AstroNvim's rooter disabled, unset `autochdir` to re-enable", vim.log.levels.WARN) - M.disabled = true - elseif M.disabled and not autochdir then - M.disabled = false + if not vim_autochdir and autochdir then + notify("Rooting disabled, unset `autochdir` to re-enable", vim.log.levels.WARN) + vim_autochdir = true + elseif vim_autochdir and not autochdir then + vim_autochdir = false end - if M.disabled or vim.v.vim_did_enter == 0 then return end + if vim_autochdir or vim.v.vim_did_enter == 0 then return end if not bufnr or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end - local root = M.detect(bufnr)[1] if root then M.set_pwd(root) end end diff --git a/lua/astrocore/toggles.lua b/lua/astrocore/toggles.lua index 76511bc..69c8fd2 100644 --- a/lua/astrocore/toggles.lua +++ b/lua/astrocore/toggles.lua @@ -12,6 +12,18 @@ local M = {} local function bool2str(bool) return bool and "on" or "off" end local function ui_notify(silent, ...) return not silent and require("astrocore").notify(...) end +--- Toggle rooter autochdir +---@param silent? boolean if true then don't sent a notification +function M.autochdir(silent) + local root_config = require("astrocore").config.rooter + if not root_config then + ui_notify(silent, "Rooter not configured") + else + root_config.autochdir = not root_config.autochdir + ui_notify(silent, ("Rooter autochdir %s"):format(bool2str(root_config.autochdir))) + end +end + --- Toggle notifications for UI toggles ---@param silent? boolean if true then don't sent a notification function M.notifications(silent)