From 467a27030e03757dbcd99ead6eb85d4ad6c4671c Mon Sep 17 00:00:00 2001 From: Micah Halter Date: Thu, 6 Jul 2023 15:28:35 -0400 Subject: [PATCH] v3.31.0 Nightly (#2091) * fix(utils): load treesitter when making notifications * fix(treesitter): ensure markdown treesitter parser * feat: add `vim.g.git_worktrees` to enable usage of detached git working trees (#2092) * feat(options): add setting to enable git integration for custom worktrees * fix(autocmds): add additional check for AstroGitFile to see if file is in custom worktree * refactor(autocmds): extract `in_worktree()` to custom utility function `find_worktree()` * feat(mappings): allow toggle lazygit to automatically load git worktrees if available * chore(mappings): cleanup redundant toggle lazygit mapping * refactor: clean up implementation of git worktrees * fix(ui): notifications appearing on top in unintended situations (#2093) * fix(ui): notifications appearing on top in unintended situations * fix(ui): increase notification zindex to 175 Co-authored-by: Micah Halter --------- Co-authored-by: Micah Halter * feat: include tables for all map modes in `mappings` and `lsp.mappings` * chore: use `vim.ui.open` if it's available * fix(utils): set cursor in a better position (#2094) * fix: disable `lua_ls` formatting with Neoconf * fix(lsp): hacky fix for neoconf lazy loading * fix(heirline): improve lualine integration with statusline * refactor: simplify notification formatting implementation * fix(utils): update `is_available` to use the correct lazy API * chore(snapshot): update lazy_snapshot --------- Co-authored-by: Josh <56745535+Subjective@users.noreply.github.com> Co-authored-by: Tiago Muniz de Araujo --- .neoconf.json | 20 +++++++++++++++++ lua/astronvim/autocmds.lua | 5 ++++- lua/astronvim/mappings.lua | 16 ++++++++++---- lua/astronvim/options.lua | 1 + lua/astronvim/utils/git.lua | 26 ++++++++++++++++++++++ lua/astronvim/utils/init.lua | 37 +++++++++++++++++--------------- lua/astronvim/utils/lsp.lua | 33 +++++++++++----------------- lua/lazy_snapshot.lua | 8 +++---- lua/plugins/configs/heirline.lua | 20 ++++++++--------- lua/plugins/git.lua | 1 + lua/plugins/lsp.lua | 2 ++ lua/plugins/neo-tree.lua | 5 ++++- lua/plugins/treesitter.lua | 1 + lua/plugins/ui.lua | 9 ++++++-- 14 files changed, 123 insertions(+), 61 deletions(-) create mode 100644 .neoconf.json diff --git a/.neoconf.json b/.neoconf.json new file mode 100644 index 00000000000..2d7a81f9669 --- /dev/null +++ b/.neoconf.json @@ -0,0 +1,20 @@ +{ + "neodev": { + "library": { + "enabled": true, + "plugins": true + } + }, + "neoconf": { + "plugins": { + "lua_ls": { + "enabled": true + } + } + }, + "lspconfig": { + "lua_ls": { + "Lua.format.enable": false + } + } +} diff --git a/lua/astronvim/autocmds.lua b/lua/astronvim/autocmds.lua index f3fcffff7a4..f324ad8c443 100644 --- a/lua/astronvim/autocmds.lua +++ b/lua/astronvim/autocmds.lua @@ -257,7 +257,10 @@ autocmd({ "BufReadPost", "BufNewFile", "BufWritePost" }, { callback = function(args) if not (vim.fn.expand "%" == "" or vim.api.nvim_get_option_value("buftype", { buf = args.buf }) == "nofile") then astroevent "File" - if utils.cmd({ "git", "-C", vim.fn.expand "%:p:h", "rev-parse" }, false) then + if + require("astronvim.utils.git").file_worktree() + or utils.cmd({ "git", "-C", vim.fn.expand "%:p:h", "rev-parse" }, false) + then astroevent "GitFile" vim.api.nvim_del_augroup_by_name "file_user_events" end diff --git a/lua/astronvim/mappings.lua b/lua/astronvim/mappings.lua index c5b0adc88a7..cf0d11acf6a 100644 --- a/lua/astronvim/mappings.lua +++ b/lua/astronvim/mappings.lua @@ -4,7 +4,7 @@ local get_icon = utils.get_icon local is_available = utils.is_available local ui = require "astronvim.utils.ui" -local maps = { i = {}, n = {}, v = {}, t = {} } +local maps = require("astronvim.utils").empty_map_table() local sections = { f = { desc = get_icon("Search", 1, true) .. "Find" }, @@ -26,11 +26,12 @@ maps.n["k"] = { "v:count == 0 ? 'gk' : 'k'", expr = true, desc = "Move cursor up maps.n["w"] = { "w", desc = "Save" } maps.n["q"] = { "confirm q", desc = "Quit" } maps.n["n"] = { "enew", desc = "New File" } -maps.n["gx"] = { utils.system_open, desc = "Open the file under cursor with system app" } maps.n[""] = { "w!", desc = "Force write" } maps.n[""] = { "q!", desc = "Force quit" } maps.n["|"] = { "vsplit", desc = "Vertical Split" } maps.n["\\"] = { "split", desc = "Horizontal Split" } +-- TODO: Remove when dropping support for p"] = sections.p @@ -308,8 +309,15 @@ if is_available "toggleterm.nvim" then maps.n["t"] = sections.t if vim.fn.executable "lazygit" == 1 then maps.n["g"] = sections.g - maps.n["gg"] = { function() utils.toggle_term_cmd "lazygit" end, desc = "ToggleTerm lazygit" } - maps.n["tl"] = { function() utils.toggle_term_cmd "lazygit" end, desc = "ToggleTerm lazygit" } + maps.n["gg"] = { + function() + local worktree = require("astronvim.utils.git").file_worktree() + local flags = worktree and (" --work-tree=%s --git-dir=%s"):format(worktree.toplevel, worktree.gitdir) or "" + utils.toggle_term_cmd("lazygit " .. flags) + end, + desc = "ToggleTerm lazygit", + } + maps.n["tl"] = maps.n["gg"] end if vim.fn.executable "node" == 1 then maps.n["tn"] = { function() utils.toggle_term_cmd "node" end, desc = "ToggleTerm node" } diff --git a/lua/astronvim/options.lua b/lua/astronvim/options.lua index 01a77164669..52f2c10982d 100644 --- a/lua/astronvim/options.lua +++ b/lua/astronvim/options.lua @@ -63,6 +63,7 @@ local options = astronvim.user_opts("options", { lsp_handlers_enabled = true, -- enable or disable default vim.lsp.handlers (hover and signatureHelp) semantic_tokens_enabled = true, -- enable or disable LSP semantic tokens on startup ui_notifications_enabled = true, -- disable notifications (TODO: rename to notifications_enabled in AstroNvim v4) + git_worktrees = nil, -- enable git integration for detached worktrees (specify a table where each entry is of the form { toplevel = vim.env.HOME, gitdir=vim.env.HOME .. "/.dotfiles" }) }, t = vim.t.bufs and vim.t.bufs or { bufs = vim.api.nvim_list_bufs() }, -- initialize buffers for the current tab }) diff --git a/lua/astronvim/utils/git.lua b/lua/astronvim/utils/git.lua index 82bb4d863e9..3f2a205c91e 100644 --- a/lua/astronvim/utils/git.lua +++ b/lua/astronvim/utils/git.lua @@ -18,6 +18,32 @@ function git.cmd(args, ...) return require("astronvim.utils").cmd(vim.list_extend({ "git", "-C", astronvim.install.home }, args), ...) end +--- Get the first worktree that a file belongs to +---@param file string? the file to check, defaults to the current file +---@param worktrees table[]? an array like table of worktrees with entries `toplevel` and `gitdir`, default retrieves from `vim.g.git_worktrees` +---@return table|nil # a table specifying the `toplevel` and `gitdir` of a worktree or nil if not found +function git.file_worktree(file, worktrees) + worktrees = worktrees or vim.g.git_worktrees + if not worktrees then return end + file = file or vim.fn.expand "%" + for _, worktree in ipairs(worktrees) do + if + require("astronvim.utils").cmd({ + "git", + "--work-tree", + worktree.toplevel, + "--git-dir", + worktree.gitdir, + "ls-files", + "--error-unmatch", + file, + }, false) + then + return worktree + end + end +end + --- Check if the AstroNvim is able to reach the `git` command ---@return boolean # The result of running `git --help` function git.available() return vim.fn.executable "git" == 1 end diff --git a/lua/astronvim/utils/init.lua b/lua/astronvim/utils/init.lua index dc18f4281e9..b1c405aa498 100644 --- a/lua/astronvim/utils/init.lua +++ b/lua/astronvim/utils/init.lua @@ -135,21 +135,7 @@ end ---@param type number|nil The type of the notification (:help vim.log.levels) ---@param opts? table The nvim-notify options to use (:help notify-options) function M.notify(msg, type, opts) - vim.schedule(function() - vim.notify( - msg, - type, - M.extend_tbl({ - title = "AstroNvim", - on_open = function(win) - vim.bo[vim.api.nvim_win_get_buf(win)].filetype = "markdown" - vim.wo[win].spell = false - vim.wo[win].conceallevel = 3 - vim.wo[win].concealcursor = "n" - end, - }, opts) - ) - end) + vim.schedule(function() vim.notify(msg, type, M.extend_tbl({ title = "AstroNvim" }, opts)) end) end --- Trigger an AstroNvim user event @@ -161,6 +147,8 @@ end --- Open a URL under the cursor with the current operating system ---@param path string The path of the file to open with the system opener function M.system_open(path) + -- TODO: REMOVE WHEN DROPPING NEOVIM <0.10 + if vim.ui.open then return vim.ui.open(path) end local cmd if vim.fn.has "win32" == 1 and vim.fn.executable "explorer" == 1 then cmd = { "cmd.exe", "/K", "explorer" } @@ -212,7 +200,7 @@ function M.alpha_button(sc, txt) position = "center", text = txt, shortcut = sc, - cursor = 5, + cursor = -2, width = 36, align_shortcut = "right", hl = "DashboardCenter", @@ -226,7 +214,7 @@ end ---@return boolean available # Whether the plugin is available function M.is_available(plugin) local lazy_config_avail, lazy_config = pcall(require, "lazy.core.config") - return lazy_config_avail and lazy_config.plugins[plugin] ~= nil + return lazy_config_avail and lazy_config.spec.plugins[plugin] ~= nil end --- Resolve the options table for a given plugin with lazy @@ -272,6 +260,21 @@ function M.which_key_register() end end +--- Get an empty table of mappings with a key for each map mode +---@return table # a table with entries for each map mode +function M.empty_map_table() + local maps = {} + for _, mode in ipairs { "", "n", "v", "x", "s", "o", "!", "i", "l", "c", "t" } do + maps[mode] = {} + end + if vim.fn.has "nvim-0.10.0" == 1 then + for _, abbr_mode in ipairs { "ia", "ca", "!a" } do + maps[abbr_mode] = {} + end + end + return maps +end + --- Table based API for setting keybindings ---@param map_table table A nested table where the first key is the vim mode, the second key is the key to map, and the value is the function to set the mapping to ---@param base? table A base set of options to set on every keybinding diff --git a/lua/astronvim/utils/lsp.lua b/lua/astronvim/utils/lsp.lua index 170659b1e6b..64910a99e9f 100644 --- a/lua/astronvim/utils/lsp.lua +++ b/lua/astronvim/utils/lsp.lua @@ -85,6 +85,12 @@ M.setup = function(server) end local opts = M.config(server) local setup_handler = setup_handlers[server] or setup_handlers[1] + + -- HACK: set up neoconf before setting up any language servers if it's not setup + if not package.loaded["neoconf"] and utils.is_available "neoconf.nvim" then + require("neoconf").setup(utils.plugin_opts "neoconf.nvim") + end + if not vim.tbl_contains(astronvim.lsp.skip_setup, server) and setup_handler then setup_handler(server, opts) end end @@ -128,27 +134,12 @@ end ---@param client table The LSP client details when attaching ---@param bufnr number The buffer that the LSP client is attaching to M.on_attach = function(client, bufnr) - local lsp_mappings = { - n = { - ["ld"] = { - function() vim.diagnostic.open_float() end, - desc = "Hover diagnostics", - }, - ["[d"] = { - function() vim.diagnostic.goto_prev() end, - desc = "Previous diagnostic", - }, - ["]d"] = { - function() vim.diagnostic.goto_next() end, - desc = "Next diagnostic", - }, - ["gl"] = { - function() vim.diagnostic.open_float() end, - desc = "Hover diagnostics", - }, - }, - v = {}, - } + local lsp_mappings = require("astronvim.utils").empty_map_table() + + lsp_mappings.n["ld"] = { function() vim.diagnostic.open_float() end, desc = "Hover diagnostics" } + lsp_mappings.n["[d"] = { function() vim.diagnostic.goto_prev() end, desc = "Previous diagnostic" } + lsp_mappings.n["]d"] = { function() vim.diagnostic.goto_next() end, desc = "Next diagnostic" } + lsp_mappings.n["gl"] = { function() vim.diagnostic.open_float() end, desc = "Hover diagnostics" } if is_available "telescope.nvim" then lsp_mappings.n["lD"] = diff --git a/lua/lazy_snapshot.lua b/lua/lazy_snapshot.lua index 54d515b7baf..e1ba3df9886 100644 --- a/lua/lazy_snapshot.lua +++ b/lua/lazy_snapshot.lua @@ -20,7 +20,7 @@ return { { "hrsh7th/nvim-cmp", commit = "2743dd989e9b932e1b4813a4927d7b84272a14e2", optional = true }, { "jay-babu/mason-null-ls.nvim", version = "^2", optional = true }, { "jay-babu/mason-nvim-dap.nvim", version = "^2", optional = true }, - { "jose-elias-alvarez/null-ls.nvim", commit = "07897774c3b2f14d71b2ca51f3014d1055da9657", optional = true }, + { "jose-elias-alvarez/null-ls.nvim", commit = "db09b6c691def0038c456551e4e2772186449f35", optional = true }, { "kevinhwang91/nvim-ufo", version = "^1", optional = true }, { "kevinhwang91/promise-async", version = "^1", optional = true }, { "lewis6991/gitsigns.nvim", version = "^0.6", optional = true }, @@ -28,17 +28,17 @@ return { { "max397574/better-escape.nvim", commit = "7031dc734add47bb71c010e0551829fa5799375f", optional = true }, { "mfussenegger/nvim-dap", version = "^0.6", optional = true }, { "mrjones2014/smart-splits.nvim", version = "^1", optional = true }, - { "neovim/nvim-lspconfig", commit = "2187f222c37cb5fd7cf96f242e5c8a4a340f2596", optional = true }, + { "neovim/nvim-lspconfig", commit = "a7ecaff3245ba4b9e5ed784ebefbedba54e7f0ad", optional = true }, { "numToStr/Comment.nvim", version = "^0.8", optional = true }, { "nvim-lua/plenary.nvim", version = "^0.1", optional = true }, { "nvim-neo-tree/neo-tree.nvim", version = "^2", optional = true }, { "nvim-telescope/telescope-fzf-native.nvim", commit = "9bc8237565ded606e6c366a71c64c0af25cd7a50", optional = true }, { "nvim-telescope/telescope.nvim", version = "^0.1", optional = true }, { "nvim-tree/nvim-web-devicons", commit = "9ab9b0b894b2388a9dbcdee5f00ce72e25d85bf9", optional = true }, - { "nvim-treesitter/nvim-treesitter", commit = "0b81ed9f18333949a74586a1ea0497ae4cbb7cd4", optional = true }, + { "nvim-treesitter/nvim-treesitter", commit = "e1ab5391e5c4820dd1ffc2566d29b01573ab52a9", optional = true }, { "nvim-treesitter/nvim-treesitter-textobjects", commit = "52f1f3280d9092bfaee5c45be5962fabee3d9654", optional = true }, { "onsails/lspkind.nvim", commit = "57610d5ab560c073c465d6faf0c19f200cb67e6e", optional = true }, - { "rafamadriz/friendly-snippets", commit = "17245edcd1195ad88d60ae13fb1e90d1df9b2fc9", optional = true }, + { "rafamadriz/friendly-snippets", commit = "96c02045323a9e0b8936fc4dce42dc249495c4f1", optional = true }, { "rcarriga/cmp-dap", commit = "d16f14a210cd28988b97ca8339d504533b7e09a4", optional = true }, { "rcarriga/nvim-dap-ui", version = "^3", optional = true }, { "rcarriga/nvim-notify", version = "^3", optional = true }, diff --git a/lua/plugins/configs/heirline.lua b/lua/plugins/configs/heirline.lua index 034d6257670..60d5e6abeb8 100644 --- a/lua/plugins/configs/heirline.lua +++ b/lua/plugins/configs/heirline.lua @@ -1,8 +1,9 @@ return function(_, opts) local heirline = require "heirline" - local hl = require "astronvim.utils.status.hl" local C = require("astronvim.utils.status.env").fallback_colors local get_hlgroup = require("astronvim.utils").get_hlgroup + local lualine_mode = require("astronvim.utils.status.hl").lualine_mode + local function resolve_lualine(orig, ...) return (not orig or orig == "NONE") and lualine_mode(...) or orig end local function setup_colors() local Normal = get_hlgroup("Normal", { fg = C.fg, bg = C.bg }) @@ -24,16 +25,13 @@ return function(_, opts) local DiagnosticWarn = get_hlgroup("DiagnosticWarn", { fg = C.orange, bg = C.dark_bg }) local DiagnosticInfo = get_hlgroup("DiagnosticInfo", { fg = C.white, bg = C.dark_bg }) local DiagnosticHint = get_hlgroup("DiagnosticHint", { fg = C.bright_yellow, bg = C.dark_bg }) - local HeirlineInactive = get_hlgroup("HeirlineInactive", { bg = nil }).bg - or hl.lualine_mode("inactive", C.dark_grey) - local HeirlineNormal = get_hlgroup("HeirlineNormal", { bg = nil }).bg or hl.lualine_mode("normal", C.blue) - local HeirlineInsert = get_hlgroup("HeirlineInsert", { bg = nil }).bg or hl.lualine_mode("insert", C.green) - local HeirlineVisual = get_hlgroup("HeirlineVisual", { bg = nil }).bg or hl.lualine_mode("visual", C.purple) - local HeirlineReplace = get_hlgroup("HeirlineReplace", { bg = nil }).bg or hl.lualine_mode("replace", C.bright_red) - local HeirlineCommand = get_hlgroup("HeirlineCommand", { bg = nil }).bg - or hl.lualine_mode("command", C.bright_yellow) - local HeirlineTerminal = get_hlgroup("HeirlineTerminal", { bg = nil }).bg - or hl.lualine_mode("insert", HeirlineInsert) + local HeirlineInactive = resolve_lualine(get_hlgroup("HeirlineInactive", { bg = nil }).bg, "inactive", C.dark_grey) + local HeirlineNormal = resolve_lualine(get_hlgroup("HeirlineNormal", { bg = nil }).bg, "normal", C.blue) + local HeirlineInsert = resolve_lualine(get_hlgroup("HeirlineInsert", { bg = nil }).bg, "insert", C.green) + local HeirlineVisual = resolve_lualine(get_hlgroup("HeirlineVisual", { bg = nil }).bg, "visual", C.purple) + local HeirlineReplace = resolve_lualine(get_hlgroup("HeirlineReplace", { bg = nil }).bg, "replace", C.bright_red) + local HeirlineCommand = resolve_lualine(get_hlgroup("HeirlineCommand", { bg = nil }).bg, "command", C.bright_yellow) + local HeirlineTerminal = resolve_lualine(get_hlgroup("HeirlineTerminal", { bg = nil }).bg, "insert", HeirlineInsert) local colors = astronvim.user_opts("heirline.colors", { close_fg = Error.fg, diff --git a/lua/plugins/git.lua b/lua/plugins/git.lua index f5fb15cb41f..48e099c5017 100644 --- a/lua/plugins/git.lua +++ b/lua/plugins/git.lua @@ -12,5 +12,6 @@ return { changedelete = { text = get_icon "GitSign" }, untracked = { text = get_icon "GitSign" }, }, + worktrees = vim.g.git_worktrees, }, } diff --git a/lua/plugins/lsp.lua b/lua/plugins/lsp.lua index 50056e13519..883df011583 100644 --- a/lua/plugins/lsp.lua +++ b/lua/plugins/lsp.lua @@ -37,6 +37,8 @@ return { end return { global_settings = global_settings and string.rep("../", depth):sub(1, -2) .. global_settings } end, + -- HACK: defer neoconf loading until after lspconfig is loaded but before servers are set up + config = function() pcall(require, "lspconfig") end, -- actual setup happens in astronvim.utils.lsp }, { "williamboman/mason-lspconfig.nvim", diff --git a/lua/plugins/neo-tree.lua b/lua/plugins/neo-tree.lua index 518badfd8d0..eba3b8c408f 100644 --- a/lua/plugins/neo-tree.lua +++ b/lua/plugins/neo-tree.lua @@ -45,7 +45,10 @@ return { }, }, commands = { - system_open = function(state) require("astronvim.utils").system_open(state.tree:get_node():get_id()) end, + system_open = function(state) + -- TODO: just use vim.ui.open when dropping support for Neovim <0.10 + (vim.ui.open or require("astronvim.utils").system_open)(state.tree:get_node():get_id()) + end, parent_or_close = function(state) local node = state.tree:get_node() if (node.type == "directory" or node:has_children()) and node:is_expanded() then diff --git a/lua/plugins/treesitter.lua b/lua/plugins/treesitter.lua index 70ce712e1a3..4f0eed40f94 100644 --- a/lua/plugins/treesitter.lua +++ b/lua/plugins/treesitter.lua @@ -26,6 +26,7 @@ return { return { autotag = { enable = true }, context_commentstring = { enable = true, enable_autocmd = false }, + ensure_installed = { "markdown" }, highlight = { enable = true, disable = function(_, bufnr) return vim.api.nvim_buf_line_count(bufnr) > 10000 end, diff --git a/lua/plugins/ui.lua b/lua/plugins/ui.lua index fbe2b25c124..ac60e5b2ea2 100644 --- a/lua/plugins/ui.lua +++ b/lua/plugins/ui.lua @@ -52,9 +52,14 @@ return { init = function() require("astronvim.utils").load_plugin_with_func("nvim-notify", vim, "notify") end, opts = { on_open = function(win) - vim.api.nvim_win_set_config(win, { zindex = 1000 }) - -- close notification immediately if notifications disabled + vim.api.nvim_win_set_config(win, { zindex = 175 }) if not vim.g.ui_notifications_enabled then vim.api.nvim_win_close(win, true) end + if require("astronvim.utils").is_available "nvim-treesitter" then + if not package.loaded["nvim-treesitter"] then require "nvim-treesitter" end + vim.wo[win].conceallevel = 3 + vim.bo[vim.api.nvim_win_get_buf(win)].filetype = "markdown" + vim.wo[win].spell = false + end end, }, config = require "plugins.configs.notify",