From fe5e7da79b52d4a53f786193ee2079f4a132cb56 Mon Sep 17 00:00:00 2001 From: Marc Jakobi Date: Wed, 3 Jul 2024 23:58:32 +0200 Subject: [PATCH] perf: don't write config at startup + more asynchronicity --- lua/rocks/config/internal.lua | 51 ++++++++++++++++----------- lua/rocks/loader.lua | 60 ++++++++++++++++++++------------ lua/rocks/luarocks.lua | 6 ++-- lua/rocks/operations/helpers.lua | 4 +-- plugin/rocks.lua | 2 +- spec/loader_spec.lua | 4 ++- spec/luarocks_config_spec.lua | 6 ++-- 7 files changed, 81 insertions(+), 52 deletions(-) diff --git a/lua/rocks/config/internal.lua b/lua/rocks/config/internal.lua index a33a7108..aa71ae16 100644 --- a/lua/rocks/config/internal.lua +++ b/lua/rocks/config/internal.lua @@ -117,8 +117,8 @@ local default_config = { vim.tbl_deep_extend("force", vim.empty_dict(), rocks_toml.rocks or {}, rocks_toml.plugins or {}) return config.apply_rock_spec_modifiers(user_rocks) end, - ---@type string - luarocks_config = nil, + ---@type fun():string + luarocks_config_path = nil, } ---@type RocksOpts @@ -156,38 +156,49 @@ end if type(opts.luarocks_config) == "string" then -- luarocks_config override if vim.uv.fs_stat(opts.luarocks_config) then + local luarocks_config_path = ("%s"):format(opts.luarocks_config) ---@diagnostic disable-next-line: inject-field - config.luarocks_config = ("%s"):format(opts.luarocks_config) + config.luarocks_config_path = function() + return luarocks_config_path + end else vim.notify("rocks.nvim: luarocks_config does not exist!", vim.log.levels.ERROR) opts.luarocks_config = nil end end if not opts.luarocks_config or type(opts.luarocks_config) == "table" then - local luarocks_config_path = vim.fs.joinpath(config.rocks_path, "luarocks-config.lua") - local default_luarocks_config = { - lua_version = "5.1", - rocks_trees = { - { - name = "rocks.nvim", - root = config.rocks_path, + local nio = require("nio") + local semaphore = nio.control.semaphore(1) + ---@diagnostic disable-next-line: inject-field + config.luarocks_config_path = nio.create(function() + semaphore.acquire() + local luarocks_config_path = vim.fs.joinpath(config.rocks_path, "luarocks-config.lua") + local default_luarocks_config = { + lua_version = "5.1", + rocks_trees = { + { + name = "rocks.nvim", + root = config.rocks_path, + }, }, - }, - } - local luarocks_config = vim.tbl_deep_extend("force", default_luarocks_config, opts.luarocks_config or {}) + } + local luarocks_config = vim.tbl_deep_extend("force", default_luarocks_config, opts.luarocks_config or {}) - ---@type string - local config_str = vim.iter(luarocks_config):fold("", function(acc, k, v) - return ([[ + ---@type string + local config_str = vim.iter(luarocks_config):fold("", function(acc, k, v) + return ([[ %s %s = %s ]]):format(acc, k, vim.inspect(v)) - end) + end) - fs.write_file(luarocks_config_path, "w+", config_str) + fs.write_file_await(luarocks_config_path, "w+", config_str) - ---@diagnostic disable-next-line: inject-field - config.luarocks_config = ("%s"):format(luarocks_config_path) + semaphore.release() + + ---@diagnostic disable-next-line: inject-field + return ("%s"):format(luarocks_config_path) + end) end return config diff --git a/lua/rocks/loader.lua b/lua/rocks/loader.lua index 0569a3f5..eaa313d6 100644 --- a/lua/rocks/loader.lua +++ b/lua/rocks/loader.lua @@ -2,43 +2,59 @@ local loader = {} local log = require("rocks.log") local config = require("rocks.config.internal") +local nio = require("nio") ---@return string | nil local function get_luarocks_lua_dir_from_luarocks() - local ok, so = pcall(vim.system, { config.luarocks_binary, "--lua-version=5.1", "which", "luarocks.loader" }) + local future = nio.control.future() + local ok = pcall( + vim.system, + { config.luarocks_binary, "--lua-version=5.1", "which", "luarocks.loader" }, + nil, + function(sc) + future.set(sc) + end + ) if not ok then log.error(("Could not invoke luarocks at %s"):format(config.luarocks_binary)) return end - local sc = so:wait() + ---@type vim.SystemCompleted + local sc = future.wait() local result = sc.stdout and sc.stdout:match(vim.fs.joinpath("(%S+)", "5.1", "luarocks", "loader.lua")) return result end ----@return boolean -function loader.enable() +---@type async fun():boolean +loader.enable = nio.create(function() log.trace("Enabling luarocks loader") + local luarocks_config_path = config.luarocks_config_path() local luarocks_lua_dir = config.luarocks_binary == config.default_luarocks_binary and vim.fs.joinpath(config.rocks_path, "share", "lua") or get_luarocks_lua_dir_from_luarocks() - if luarocks_lua_dir then - package.path = package.path - .. ";" - .. table.concat({ - vim.fs.joinpath(luarocks_lua_dir, "5.1", "?.lua"), - vim.fs.joinpath(luarocks_lua_dir, "5.1", "init.lua"), - }, ";") - vim.env.LUAROCKS_CONFIG = config.luarocks_config - local ok, err = pcall(require, "luarocks.loader") - if ok then - return true + local future = nio.control.future() + vim.schedule(function() + if luarocks_lua_dir then + package.path = package.path + .. ";" + .. table.concat({ + vim.fs.joinpath(luarocks_lua_dir, "5.1", "?.lua"), + vim.fs.joinpath(luarocks_lua_dir, "5.1", "init.lua"), + }, ";") + vim.env.LUAROCKS_CONFIG = luarocks_config_path + local ok, err = pcall(require, "luarocks.loader") + if ok then + future.set(true) + return + end + log.error(err or "Unknown error initializing luarocks loader") + vim.notify("Failed to initialize luarocks loader: " .. err, vim.log.levels.WARN, { + title = "rocks.nvim", + }) end - log.error(err or "Unknown error initializing luarocks loader") - vim.notify("Failed to initialize luarocks loader: " .. err, vim.log.levels.WARN, { - title = "rocks.nvim", - }) - end - return false -end + future.set(false) + end) + return future.wait() +end) return loader diff --git a/lua/rocks/luarocks.lua b/lua/rocks/luarocks.lua index ae5e258a..08b757e8 100644 --- a/lua/rocks/luarocks.lua +++ b/lua/rocks/luarocks.lua @@ -49,7 +49,7 @@ end --- asynchronously. Receives SystemCompleted object, see return of SystemObj:wait(). ---@param opts? LuarocksCliOpts ---@see vim.system -luarocks.cli = function(args, on_exit, opts) +luarocks.cli = nio.create(function(args, on_exit, opts) opts = opts or {} ---@cast opts LuarocksCliOpts opts.synchronized = opts.synchronized ~= nil and opts.synchronized or false @@ -72,7 +72,7 @@ luarocks.cli = function(args, on_exit, opts) semaphore.acquire() end opts.env = vim.tbl_deep_extend("force", opts.env or {}, { - LUAROCKS_CONFIG = config.luarocks_config, + LUAROCKS_CONFIG = config.luarocks_config_path(), TREE_SITTER_LANGUAGE_VERSION = tostring(vim.treesitter.language_version), LUA_PATH = ('"%s"'):format(package.path), LUA_CPATH = ('"%s"'):format(package.cpath), @@ -97,7 +97,7 @@ luarocks.cli = function(args, on_exit, opts) } on_exit_wrapped(sc) end -end +end, 3) ---@class LuarocksSearchOpts ---@field dev? boolean Include dev manifest? Default: false diff --git a/lua/rocks/operations/helpers.lua b/lua/rocks/operations/helpers.lua index 9aee3cfa..00d88003 100644 --- a/lua/rocks/operations/helpers.lua +++ b/lua/rocks/operations/helpers.lua @@ -30,7 +30,7 @@ local helpers = {} ---@param rock_spec RockSpec ---@param progress_handle? ProgressHandle ---@return nio.control.Future -helpers.install = function(rock_spec, progress_handle) +helpers.install = nio.create(function(rock_spec, progress_handle) cache.invalidate_removable_rocks() local name = rock_spec.name:lower() local version = rock_spec.version @@ -103,7 +103,7 @@ helpers.install = function(rock_spec, progress_handle) servers = servers, }) return future -end +end, 2) ---Removes a rock ---@param name string diff --git a/plugin/rocks.lua b/plugin/rocks.lua index c6702eb4..90157eb1 100644 --- a/plugin/rocks.lua +++ b/plugin/rocks.lua @@ -27,7 +27,7 @@ local config = require("rocks.config.internal") -- Initialize the luarocks loader if config.enable_luarocks_loader then - require("rocks.loader").enable() + nio.run(require("rocks.loader").enable) end -- Set up the Rocks user command diff --git a/spec/loader_spec.lua b/spec/loader_spec.lua index 296b865a..dcd1f1ff 100644 --- a/spec/loader_spec.lua +++ b/spec/loader_spec.lua @@ -1,10 +1,12 @@ +vim.env.PLENARY_TEST_TIMEOUT = 60000 vim.g.rocks_nvim = { luarocks_binary = "luarocks", } local loader = require("rocks.loader") +local nio = require("nio") describe("rocks.loader", function() - it("Can enable luarocks.loader", function() + nio.tests.it("Can enable luarocks.loader", function() assert.True(loader.enable()) end) end) diff --git a/spec/luarocks_config_spec.lua b/spec/luarocks_config_spec.lua index 8e2d22c9..fd60cf94 100644 --- a/spec/luarocks_config_spec.lua +++ b/spec/luarocks_config_spec.lua @@ -19,10 +19,10 @@ describe("luarocks config", function() } local config = require("rocks.config.internal") - nio.sleep(2000) - assert.is_not_nil(vim.uv.fs_stat(config.luarocks_config)) + local luarocks_config_path = config.luarocks_config_path() + assert.is_not_nil(vim.uv.fs_stat(luarocks_config_path)) local luarocks_config = {} - loadfile(config.luarocks_config, "t", luarocks_config)() + loadfile(luarocks_config_path, "t", luarocks_config)() assert.same({ lua_version = "5.1", external_deps_dirs = external_deps_dirs,