diff --git a/lua/lazyvim/plugins/coding.lua b/lua/lazyvim/plugins/coding.lua index cbf94e77..3141bddb 100644 --- a/lua/lazyvim/plugins/coding.lua +++ b/lua/lazyvim/plugins/coding.lua @@ -150,74 +150,27 @@ return { }, }, - -- Better text-objects + -- disable old installations of mini.ai. Optional so it doesn't appear under disabled plugins { "echasnovski/mini.ai", - -- keys = { - -- { "a", mode = { "x", "o" } }, - -- { "i", mode = { "x", "o" } }, - -- }, - event = "VeryLazy", - dependencies = { "nvim-treesitter-textobjects" }, - opts = function() - local ai = require("mini.ai") - return { - n_lines = 500, - custom_textobjects = { - o = ai.gen_spec.treesitter({ - a = { "@block.outer", "@conditional.outer", "@loop.outer" }, - i = { "@block.inner", "@conditional.inner", "@loop.inner" }, - }, {}), - f = ai.gen_spec.treesitter({ a = "@function.outer", i = "@function.inner" }, {}), - c = ai.gen_spec.treesitter({ a = "@class.outer", i = "@class.inner" }, {}), - }, - } - end, - config = function(_, opts) - require("mini.ai").setup(opts) - -- register all text objects with which-key - require("lazyvim.util").on_load("which-key.nvim", function() - ---@type table - local i = { - [" "] = "Whitespace", - ['"'] = 'Balanced "', - ["'"] = "Balanced '", - ["`"] = "Balanced `", - ["("] = "Balanced (", - [")"] = "Balanced ) including white-space", - [">"] = "Balanced > including white-space", - [""] = "Balanced <", - ["]"] = "Balanced ] including white-space", - ["["] = "Balanced [", - ["}"] = "Balanced } including white-space", - ["{"] = "Balanced {", - ["?"] = "User Prompt", - _ = "Underscore", - a = "Argument", - b = "Balanced ), ], }", - c = "Class", - f = "Function", - o = "Block, conditional, loop", - q = "Quote `, \", '", - t = "Tag", - } - local a = vim.deepcopy(i) - for k, v in pairs(a) do - a[k] = v:gsub(" including.*", "") + enabled = function() + vim.schedule(function() + local Config = require("lazy.core.config") + if Config.spec.disabled["mini.ai"] then + require("lazy.core.util").warn( + [[ `mini.ai` has been moved to extras: +The core config for nvim-treesitter now contains textobjects +for `select`, `move` and `swap`. +If you want to keep using mini.ai, you can add the mini-ai extra: +`lazyvim.plugins.extras.coding.mini-ai` +By doing so, your original mini.ai setup remains unchanged. +]], + { title = "LazyVim" } + ) end - - local ic = vim.deepcopy(i) - local ac = vim.deepcopy(a) - for key, name in pairs({ n = "Next", l = "Last" }) do - i[key] = vim.tbl_extend("force", { name = "Inside " .. name .. " textobject" }, ic) - a[key] = vim.tbl_extend("force", { name = "Around " .. name .. " textobject" }, ac) - end - require("which-key").register({ - mode = { "o", "x" }, - i = i, - a = a, - }) end) + return false end, + optional = true, }, } diff --git a/lua/lazyvim/plugins/extras/coding/mini-ai.lua b/lua/lazyvim/plugins/extras/coding/mini-ai.lua new file mode 100644 index 00000000..db0c9699 --- /dev/null +++ b/lua/lazyvim/plugins/extras/coding/mini-ai.lua @@ -0,0 +1,139 @@ +local load_textobjects = false + +---@param langs table +---@return table +local function dedup(langs) + -- TODO: move this utility function to a better location + ---@type table + local added = {} + return vim.tbl_filter(function(lang) + if added[lang] then + return false + end + added[lang] = true + return true + end, langs) +end + +return { + + { + "nvim-treesitter/nvim-treesitter", + dependencies = { + { + "nvim-treesitter/nvim-treesitter-textobjects", + init = function() + -- disable rtp plugin, as we only need its queries for mini.ai + -- In case other textobject modules are enabled, we will load them + -- once nvim-treesitter is loaded + require("lazy.core.loader").disable_rtp_plugin("nvim-treesitter-textobjects") + load_textobjects = true + end, + }, + }, + opts = function(_, opts) + -- override the default textobjects, set in plugins/treesitter.lua + -- when using this extra, the user is expected to add textobjects + -- on a need-to-have basis + opts.textobjects = nil + end, + ---@param opts TSConfig + config = function(_, opts) -- override config in plugins/treesitter.lua + if type(opts.ensure_installed) == "table" then + opts.ensure_installed = dedup(opts.ensure_installed) + end + require("nvim-treesitter.configs").setup(opts) + + if load_textobjects then + -- PERF: no need to load the plugin, if we only need its queries for mini.ai + if opts.textobjects then + for _, mod in ipairs({ "move", "select", "swap", "lsp_interop" }) do + if opts.textobjects[mod] and opts.textobjects[mod].enable then + local Loader = require("lazy.core.loader") + Loader.disabled_rtp_plugins["nvim-treesitter-textobjects"] = nil + local plugin = require("lazy.core.config").plugins["nvim-treesitter-textobjects"] + require("lazy.core.loader").source_runtime(plugin.dir, "plugin") + break + end + end + end + end + end, + }, + + -- Better text-objects + { + "echasnovski/mini.ai", + enabled = true, + -- keys = { + -- { "a", mode = { "x", "o" } }, + -- { "i", mode = { "x", "o" } }, + -- }, + event = "VeryLazy", + dependencies = { "nvim-treesitter-textobjects" }, + opts = function() + local ai = require("mini.ai") + return { + n_lines = 500, + custom_textobjects = { + + -- see: https://github.com/echasnovski/mini.nvim/issues/474 + t = false, -- for now, fallback to neovim's builtin tag. + + o = ai.gen_spec.treesitter({ + a = { "@block.outer", "@conditional.outer", "@loop.outer" }, + i = { "@block.inner", "@conditional.inner", "@loop.inner" }, + }, {}), + f = ai.gen_spec.treesitter({ a = "@function.outer", i = "@function.inner" }, {}), + c = ai.gen_spec.treesitter({ a = "@class.outer", i = "@class.inner" }, {}), + }, + } + end, + config = function(_, opts) + require("mini.ai").setup(opts) + -- register all text objects with which-key + require("lazyvim.util").on_load("which-key.nvim", function() + ---@type table + local i = { + [" "] = "Whitespace", + ['"'] = 'Balanced "', + ["'"] = "Balanced '", + ["`"] = "Balanced `", + ["("] = "Balanced (", + [")"] = "Balanced ) including white-space", + [">"] = "Balanced > including white-space", + [""] = "Balanced <", + ["]"] = "Balanced ] including white-space", + ["["] = "Balanced [", + ["}"] = "Balanced } including white-space", + ["{"] = "Balanced {", + ["?"] = "User Prompt", + _ = "Underscore", + a = "Argument", + b = "Balanced ), ], }", + c = "Class", + f = "Function", + o = "Block, conditional, loop", + q = "Quote `, \", '", + t = "Tag", + } + local a = vim.deepcopy(i) + for k, v in pairs(a) do + a[k] = v:gsub(" including.*", "") + end + + local ic = vim.deepcopy(i) + local ac = vim.deepcopy(a) + for key, name in pairs({ n = "Next", l = "Last" }) do + i[key] = vim.tbl_extend("force", { name = "Inside " .. name .. " textobject" }, ic) + a[key] = vim.tbl_extend("force", { name = "Around " .. name .. " textobject" }, ac) + end + require("which-key").register({ + mode = { "o", "x" }, + i = i, + a = a, + }) + end) + end, + }, +} diff --git a/lua/lazyvim/plugins/treesitter.lua b/lua/lazyvim/plugins/treesitter.lua index b84d01a7..fcb3ca43 100644 --- a/lua/lazyvim/plugins/treesitter.lua +++ b/lua/lazyvim/plugins/treesitter.lua @@ -1,4 +1,18 @@ -local load_textobjects = false +---@param langs table +---@return table +local function dedup(langs) + -- TODO: move this utility function to a better location + ---@type table + local added = {} + return vim.tbl_filter(function(lang) + if added[lang] then + return false + end + added[lang] = true + return true + end, langs) +end + return { -- Treesitter is a new parser generator tool that we can -- use in Neovim to power faster and more accurate @@ -8,18 +22,7 @@ return { version = false, -- last release is way too old and doesn't work on Windows build = ":TSUpdate", event = { "BufReadPost", "BufNewFile" }, - dependencies = { - { - "nvim-treesitter/nvim-treesitter-textobjects", - init = function() - -- disable rtp plugin, as we only need its queries for mini.ai - -- In case other textobject modules are enabled, we will load them - -- once nvim-treesitter is loaded - require("lazy.core.loader").disable_rtp_plugin("nvim-treesitter-textobjects") - load_textobjects = true - end, - }, - }, + dependencies = { "nvim-treesitter/nvim-treesitter-textobjects" }, cmd = { "TSUpdateSync" }, keys = { { "", desc = "Increment selection" }, @@ -59,36 +62,70 @@ return { node_decremental = "", }, }, + textobjects = { + select = { + enable = true, + lookahead = true, + keymaps = { + ["ak"] = { query = "@block.outer", desc = "around block" }, + ["ik"] = { query = "@block.inner", desc = "inside block" }, + ["ac"] = { query = "@class.outer", desc = "around class" }, + ["ic"] = { query = "@class.inner", desc = "inside class" }, + ["a?"] = { query = "@conditional.outer", desc = "around conditional" }, + ["i?"] = { query = "@conditional.inner", desc = "inside conditional" }, + ["af"] = { query = "@function.outer", desc = "around function " }, + ["if"] = { query = "@function.inner", desc = "inside function " }, + ["al"] = { query = "@loop.outer", desc = "around loop" }, + ["il"] = { query = "@loop.inner", desc = "inside loop" }, + ["aa"] = { query = "@parameter.outer", desc = "around argument" }, + ["ia"] = { query = "@parameter.inner", desc = "inside argument" }, + }, + }, + move = { + enable = true, + set_jumps = true, + goto_next_start = { + ["]k"] = { query = "@block.outer", desc = "Next block start" }, + ["]f"] = { query = "@function.outer", desc = "Next function start" }, + ["]a"] = { query = "@parameter.inner", desc = "Next argument start" }, + }, + goto_next_end = { + ["]K"] = { query = "@block.outer", desc = "Next block end" }, + ["]F"] = { query = "@function.outer", desc = "Next function end" }, + ["]A"] = { query = "@parameter.inner", desc = "Next argument end" }, + }, + goto_previous_start = { + ["[k"] = { query = "@block.outer", desc = "Previous block start" }, + ["[f"] = { query = "@function.outer", desc = "Previous function start" }, + ["[a"] = { query = "@parameter.inner", desc = "Previous argument start" }, + }, + goto_previous_end = { + ["[K"] = { query = "@block.outer", desc = "Previous block end" }, + ["[F"] = { query = "@function.outer", desc = "Previous function end" }, + ["[A"] = { query = "@parameter.inner", desc = "Previous argument end" }, + }, + }, + swap = { + enable = true, + swap_next = { + [">K"] = { query = "@block.outer", desc = "Swap next block" }, + [">F"] = { query = "@function.outer", desc = "Swap next function" }, + [">A"] = { query = "@parameter.inner", desc = "Swap next argument" }, + }, + swap_previous = { + [" - local added = {} - opts.ensure_installed = vim.tbl_filter(function(lang) - if added[lang] then - return false - end - added[lang] = true - return true - end, opts.ensure_installed) + opts.ensure_installed = dedup(opts.ensure_installed) end require("nvim-treesitter.configs").setup(opts) - - if load_textobjects then - -- PERF: no need to load the plugin, if we only need its queries for mini.ai - if opts.textobjects then - for _, mod in ipairs({ "move", "select", "swap", "lsp_interop" }) do - if opts.textobjects[mod] and opts.textobjects[mod].enable then - local Loader = require("lazy.core.loader") - Loader.disabled_rtp_plugins["nvim-treesitter-textobjects"] = nil - local plugin = require("lazy.core.config").plugins["nvim-treesitter-textobjects"] - require("lazy.core.loader").source_runtime(plugin.dir, "plugin") - break - end - end - end - end end, }, }