diff --git a/lua/plugins/native/treesitter.lua b/lua/plugins/native/treesitter.lua index 1ed09e2..734e096 100644 --- a/lua/plugins/native/treesitter.lua +++ b/lua/plugins/native/treesitter.lua @@ -1,16 +1,39 @@ local M = {} function M.setup() - local ok_configs, ts_configs = pcall(require, "nvim-treesitter.configs") - if not ok_configs then + local ok_ts, ts = pcall(require, "nvim-treesitter") + if not ok_ts then vim.schedule(function() - vim.notify("nvim-treesitter is not available yet. Run :lua vim.pack.update() and restart.", + vim.notify("nvim-treesitter is not ready yet. Wait for background plugin install and restart Neovim.", vim.log.levels.WARN) end) return end - ts_configs.setup({ + local move_config = { + goto_next_start = { + ["]f"] = "@function.outer", + ["]c"] = "@class.outer", + ["]a"] = "@parameter.inner", + }, + goto_next_end = { + ["]F"] = "@function.outer", + ["]C"] = "@class.outer", + ["]A"] = "@parameter.inner", + }, + goto_previous_start = { + ["[f"] = "@function.outer", + ["[c"] = "@class.outer", + ["[a"] = "@parameter.inner", + }, + goto_previous_end = { + ["[F"] = "@function.outer", + ["[C"] = "@class.outer", + ["[A"] = "@parameter.inner", + }, + } + + ts.setup({ ensure_installed = { "bash", "c", @@ -51,26 +74,10 @@ function M.setup() textobjects = { move = { enable = true, - goto_next_start = { - ["]f"] = "@function.outer", - ["]c"] = "@class.outer", - ["]a"] = "@parameter.inner", - }, - goto_next_end = { - ["]F"] = "@function.outer", - ["]C"] = "@class.outer", - ["]A"] = "@parameter.inner", - }, - goto_previous_start = { - ["[f"] = "@function.outer", - ["[c"] = "@class.outer", - ["[a"] = "@parameter.inner", - }, - goto_previous_end = { - ["[F"] = "@function.outer", - ["[C"] = "@class.outer", - ["[A"] = "@parameter.inner", - }, + goto_next_start = move_config.goto_next_start, + goto_next_end = move_config.goto_next_end, + goto_previous_start = move_config.goto_previous_start, + goto_previous_end = move_config.goto_previous_end, }, }, }) @@ -84,7 +91,7 @@ function M.setup() if name:find("goto") == 1 then move[name] = function(query, ...) if vim.wo.diff then - local config = ts_configs.get_module("textobjects.move")[name] + local config = move_config[name] for key, textobject in pairs(config or {}) do if query == textobject and key:find("[%]%[][cC]") then vim.cmd("normal! " .. key) diff --git a/lua/plugins/pack.lua b/lua/plugins/pack.lua index 3a4bdbe..50693d4 100644 --- a/lua/plugins/pack.lua +++ b/lua/plugins/pack.lua @@ -1,4 +1,5 @@ local M = {} +local async_install_started = false local function has_valid_head(path) if vim.fn.isdirectory(path .. "/.git") == 0 then @@ -31,6 +32,45 @@ local function to_src(value) return "https://github.com/" .. value end +local function plugin_name(spec) + if type(spec) == "table" and type(spec.name) == "string" and spec.name ~= "" then + return spec.name + end + + local src = type(spec) == "string" and spec or spec.src + local name = src:gsub("/$", ""):match("([^/]+)$") or src + return name:gsub("%.git$", "") +end + +local function plugin_installed(spec) + local root = vim.fn.stdpath("data") .. "/site/pack/core/opt" + local path = root .. "/" .. plugin_name(spec) + return vim.fn.isdirectory(path) == 1 +end + +local function install_missing_async(specs) + if async_install_started or #specs == 0 then + return + end + + async_install_started = true + + local specs_json = vim.json.encode(specs) + local lua_expr = string.format( + "local s=vim.json.decode(%q); vim.pack.add(s,{confirm=false,load=false})", + specs_json + ) + + vim.system({ + vim.v.progpath, + "--headless", + "-u", + "NONE", + "+lua " .. lua_expr, + "+qall", + }, { detach = true }) +end + function M.add(specs) local resolved = {} @@ -44,17 +84,42 @@ function M.add(specs) end end - local ok, err = pcall(vim.pack.add, resolved, { confirm = false, load = true }) + local installed = {} + local missing = {} + + for _, spec in ipairs(resolved) do + if plugin_installed(spec) then + table.insert(installed, spec) + else + table.insert(missing, spec) + end + end + + if #missing > 0 then + install_missing_async(missing) + vim.schedule(function() + vim.notify( + "Missing plugins detected. Started background install; restart Neovim when it finishes.", + vim.log.levels.WARN + ) + end) + end + + if #installed == 0 then + return false + end + + local ok, err = pcall(vim.pack.add, installed, { confirm = false, load = true }) if not ok and tostring(err):find("ambiguous argument 'HEAD'", 1, true) then prune_broken_pack_repos() vim.fn.delete(vim.fn.stdpath("config") .. "/nvim-pack-lock.json") - ok, err = pcall(vim.pack.add, resolved, { confirm = false, load = true }) + ok, err = pcall(vim.pack.add, installed, { confirm = false, load = true }) end if not ok then vim.schedule(function() - local msg = "vim.pack failed to install/load plugins. Check network and run :lua vim.pack.update()." + local msg = "vim.pack failed to load installed plugins." vim.notify(msg .. "\n" .. tostring(err), vim.log.levels.WARN) end) return false