فهرست منبع

feat(lsp): handle user configuration in setup() (#1707)

kylo252 3 سال پیش
والد
کامیت
c0e3c8d43a
7فایلهای تغییر یافته به همراه102 افزوده شده و 69 حذف شده
  1. 23 26
      lua/bootstrap.lua
  2. 2 2
      lua/core/commands.lua
  3. 1 0
      lua/lsp/init.lua
  4. 42 39
      lua/lsp/manager.lua
  5. 1 1
      lua/lsp/templates.lua
  6. 33 0
      lua/utils/hooks.lua
  7. 0 1
      tests/lsp_spec.lua

+ 23 - 26
lua/bootstrap.lua

@@ -1,6 +1,7 @@
 local M = {}
 
-local in_headless = #vim.api.nvim_list_uis() == 0
+package.loaded["utils.hooks"] = nil
+local _, hooks = pcall(require, "utils.hooks")
 
 ---Join path segments that were passed as input
 ---@return string
@@ -42,12 +43,23 @@ function _G.get_cache_dir()
   return lvim_cache_dir
 end
 
+---Get the full path to the currently installed lunarvim repo
+---@return string
+local function get_install_path()
+  local lvim_runtime_dir = os.getenv "LUNARVIM_RUNTIME_DIR"
+  if not lvim_runtime_dir then
+    -- when nvim is used directly
+    return vim.fn.stdpath "config"
+  end
+  return join_paths(lvim_runtime_dir, "lvim")
+end
+
 ---Get currently installed version of LunarVim
 ---@param type string can be "short"
 ---@return string
 function _G.get_version(type)
   type = type or ""
-  local lvim_full_ver = vim.fn.system("git -C " .. get_runtime_dir() .. "/lvim describe --tags")
+  local lvim_full_ver = vim.fn.system("git -C " .. get_install_path() .. " describe --tags")
 
   if string.match(lvim_full_ver, "%d") == nil then
     return nil
@@ -65,7 +77,7 @@ function M:init()
   self.runtime_dir = get_runtime_dir()
   self.config_dir = get_config_dir()
   self.cache_path = get_cache_dir()
-  self.repo_dir = join_paths(self.runtime_dir, "lvim")
+  self.install_path = get_install_path()
 
   self.pack_dir = join_paths(self.runtime_dir, "site", "pack")
   self.packer_install_dir = join_paths(self.runtime_dir, "site", "pack", "packer", "start", "packer.nvim")
@@ -113,23 +125,15 @@ end
 ---Update LunarVim
 ---pulls the latest changes from github and, resets the startup cache
 function M:update()
+  hooks.run_pre_update()
   M:update_repo()
-  M:reset_cache()
-  require("lsp.templates").generate_templates()
-  if not in_headless then
-    vim.schedule(function()
-      require("packer").install()
-      -- TODO: add a changelog
-      vim.notify("Update complete", vim.log.levels.INFO)
-    end)
-  end
+  hooks.run_post_update()
 end
 
 local function git_cmd(subcmd)
   local Job = require "plenary.job"
   local Log = require "core.log"
-  local repo_dir = join_paths(get_runtime_dir(), "lvim")
-  local args = { "-C", repo_dir }
+  local args = { "-C", get_install_path() }
   vim.list_extend(args, subcmd)
 
   local stderr = {}
@@ -137,7 +141,7 @@ local function git_cmd(subcmd)
     :new({
       command = "git",
       args = args,
-      cwd = repo_dir,
+      cwd = get_install_path(),
       on_stderr = function(_, data)
         table.insert(stderr, data)
       end,
@@ -167,7 +171,8 @@ function M:update_repo()
 
   local ret = git_cmd(sub_commands.fetch)
   if ret ~= 0 then
-    error "Update failed! Check the log for further information"
+    Log:error "Update failed! Check the log for further information"
+    return
   end
 
   ret = git_cmd(sub_commands.diff)
@@ -180,17 +185,9 @@ function M:update_repo()
   ret = git_cmd(sub_commands.merge)
 
   if ret ~= 0 then
-    error "Error: unable to guarantee data integrity while updating your branch"
-    error "Please pull the changes manually instead."
+    Log:error "Update failed! Please pull the changes manually instead."
+    return
   end
 end
 
----Reset any startup cache files used by Packer and Impatient
----Tip: Useful for clearing any outdated settings
-function M:reset_cache()
-  _G.__luacache.clear_cache()
-  _G.__luacache.save_cache()
-  require("plugin-loader"):cache_reset()
-end
-
 return M

+ 2 - 2
lua/core/commands.lua

@@ -11,8 +11,8 @@ M.defaults = {
   endfunction
   ]],
   -- :LvimInfo
-  [[command! LvimInfo lua require('core.info').toggle_popup(vim.bo.filetype)]],
-  [[ command! LvimCacheReset lua require('bootstrap').reset_cache() ]],
+  [[ command! LvimInfo lua require('core.info').toggle_popup(vim.bo.filetype) ]],
+  [[ command! LvimCacheReset lua require('utils.hooks').reset_cache() ]],
   [[ command! LvimUpdate lua require('bootstrap').update() ]],
 }
 

+ 1 - 0
lua/lsp/init.lua

@@ -149,6 +149,7 @@ function M.setup()
   for _, sign in ipairs(lvim.lsp.diagnostics.signs.values) do
     vim.fn.sign_define(sign.name, { texthl = sign.name, text = sign.text, numhl = sign.name })
   end
+
   require("lsp.handlers").setup()
 
   if not utils.is_directory(lvim.lsp.templates_dir) then

+ 42 - 39
lua/lsp/manager.lua

@@ -24,59 +24,62 @@ local function is_overridden(server)
   end
 end
 
-function M.setup_server(server_name)
-  vim.validate {
-    name = { server_name, "string" },
-  }
-
-  if lsp_utils.is_client_active(server_name) or is_overridden(server_name) then
-    return
-  end
-
-  local lsp_installer_servers = require "nvim-lsp-installer.servers"
-  local server_available, requested_server = lsp_installer_servers.get_server(server_name)
-  if server_available then
-    if not requested_server:is_installed() then
-      Log:debug(string.format("[%s] is not installed", server_name))
-      if lvim.lsp.automatic_servers_installation then
-        Log:debug(string.format("Installing [%s]", server_name))
-        requested_server:install()
-      else
-        return
-      end
-    end
-  end
-
-  local default_config = {
+---Resolve the configuration for a server based on both common and user configuration
+---@param name string
+---@param user_config table [optional]
+---@return table
+local function resolve_config(name, user_config)
+  local config = {
     on_attach = require("lsp").common_on_attach,
     on_init = require("lsp").common_on_init,
     capabilities = require("lsp").common_capabilities(),
   }
 
-  local status_ok, custom_config = pcall(require, "lsp/providers/" .. requested_server.name)
+  local status_ok, custom_config = pcall(require, "lsp/providers/" .. name)
   if status_ok then
-    local new_config = vim.tbl_deep_extend("force", default_config, custom_config)
-    Log:debug("Using custom configuration for requested server: " .. requested_server.name)
-    requested_server:setup(new_config)
-  else
-    Log:debug("Using the default configuration for requested server: " .. requested_server.name)
-    requested_server:setup(default_config)
+    Log:debug("Using custom configuration for requested server: " .. name)
+    config = vim.tbl_deep_extend("force", config, custom_config)
   end
+
+  if user_config then
+    config = vim.tbl_deep_extend("force", config, user_config)
+  end
+
+  return config
 end
 
-function M.setup(servers)
-  local status_ok, _ = pcall(require, "nvim-lsp-installer")
-  if not status_ok then
+---Setup a language server by providing a name
+---@param server_name string name of the language server
+---@param user_config table [optional] when available it will take predence over any default configurations
+function M.setup(server_name, user_config)
+  vim.validate { name = { server_name, "string" } }
+
+  if lsp_utils.is_client_active(server_name) or is_overridden(server_name) then
     return
   end
 
-  --- allow using a single value
-  if type(servers) == "string" then
-    servers = { servers }
+  local config = resolve_config(server_name, user_config)
+  local server_available, requested_server = require("nvim-lsp-installer.servers").get_server(server_name)
+
+  local function ensure_installed(server)
+    if server:is_installed() then
+      return true
+    end
+    if not lvim.lsp.automatic_servers_installation then
+      Log:debug(server.name .. " is not managed by the automatic installer")
+      return false
+    end
+    Log:debug(string.format("Installing [%s]", server.name))
+    server:install()
+    vim.schedule(function()
+      vim.cmd [[LspStart]]
+    end)
   end
 
-  for _, server in ipairs(servers) do
-    M.setup_server(server)
+  if server_available and ensure_installed(requested_server) then
+    requested_server:setup(config)
+  else
+    require("lspconfig")[server_name].setup(config)
   end
 end
 

+ 1 - 1
lua/lsp/templates.lua

@@ -23,7 +23,7 @@ function M.is_ignored(server_name, filetypes)
   filetypes = filetypes or get_supported_filetypes(server_name)
 
   if vim.tbl_contains(filetypes, "javascript") then
-    if server_name == "tsserver" or server_name == "tailwindcss" then
+    if server_name == "tsserver" then
       return false
     else
       return true

+ 33 - 0
lua/utils/hooks.lua

@@ -0,0 +1,33 @@
+local M = {}
+
+local Log = require "core.log"
+local in_headless = #vim.api.nvim_list_uis() == 0
+
+function M.run_pre_update()
+  Log:debug "Starting pre-update hook"
+end
+
+---Reset any startup cache files used by Packer and Impatient
+---Tip: Useful for clearing any outdated settings
+function M.reset_cache()
+  _G.__luacache.clear_cache()
+  require("plugin-loader"):cache_reset()
+end
+
+function M.run_post_update()
+  M.reset_cache()
+  Log:debug "Starting post-update hook"
+  package.loaded["lsp.templates"] = nil
+  require("lsp.templates").generate_templates()
+
+  if not in_headless then
+    vim.schedule(function()
+      require("packer").install()
+      -- TODO: add a changelog
+      vim.notify("Update complete", vim.log.levels.INFO)
+      vim.cmd "LspStart"
+    end)
+  end
+end
+
+return M

+ 0 - 1
tests/lsp_spec.lua

@@ -79,7 +79,6 @@ a.describe("lsp workflow", function()
     local ts_template = utils.join_paths(lvim.lsp.templates_dir, "typescript.lua")
 
     assert.True(utils.file_contains(ts_template, "tsserver"))
-    assert.True(utils.file_contains(ts_template, "tailwindcss"))
     assert.False(utils.file_contains(ts_template, test_server.name))
   end)