diff options
28 files changed, 350 insertions, 213 deletions
| @@ -39,7 +39,7 @@ bash <(curl -s https://raw.githubusercontent.com/lunarvim/lunarvim/master/utils/  To run the install script without any interaction you can pass the `-y` flag to automatically install all dependencies and have no prompts. This is particularly useful in automated installations. -The same way, you can use `--no-install-dependencies` to skip the dependency installation. +In the same way, you can use `--no-install-dependencies` to skip the dependency installation.  ### Windows (Powershell 7+): @@ -51,7 +51,7 @@ Invoke-WebRequest https://raw.githubusercontent.com/LunarVim/LunarVim/master/uti  ## Automatic LSP support -By default, most supported language servers will get automatically installed once you open the supported file-type, e.g, opening a Python file for the first time will install `Pyright` and configure it automatically for you. +By default, most supported language servers will get automatically installed once you open the supported file type, e.g, opening a Python file for the first time will install `Pyright` and configure it automatically for you.  ## Configuration file @@ -99,7 +99,7 @@ formatters.setup {    { command = "black" },    {      command = "prettier", -    ---@usage specify which filetypes to enable. By default a providers will attach to all the filetypes it supports. +    ---@usage specify which filetypes to enable. By default, providers will attach to all the filetypes it supports.      filetypes = { "typescript", "typescriptreact" },    },  } @@ -109,7 +109,7 @@ local linters = require "lvim.lsp.null-ls.linters"  linters.setup {    {      command = "eslint_d", -    ---@usage specify which filetypes to enable. By default a providers will attach to all the filetypes it supports. +    ---@usage specify which filetypes to enable. By default, providers will attach to all the filetypes it supports.      filetypes = { "javascript", "javascriptreact" },    },  } diff --git a/lua/lvim/config/init.lua b/lua/lvim/config/init.lua index 4343ace9..c6765f56 100644 --- a/lua/lvim/config/init.lua +++ b/lua/lvim/config/init.lua @@ -99,6 +99,13 @@ local function handle_deprecated_settings()        "Use vim.api.nvim_create_autocmd instead or check LunarVim#2592 to learn about the new syntax"      )    end + +  if lvim.lsp.automatic_servers_installation then +    deprecation_notice( +      "lvim.lsp.automatic_servers_installation", +      "Use `lvim.lsp.installer.setup.automatic_installation` instead" +    ) +  end  end  --- Override the configuration with a user provided one diff --git a/lua/lvim/core/autopairs.lua b/lua/lvim/core/autopairs.lua index 4d9f33f4..469a38a4 100644 --- a/lua/lvim/core/autopairs.lua +++ b/lua/lvim/core/autopairs.lua @@ -79,6 +79,10 @@ M.setup = function()    if lvim.builtin.autopairs.on_config_done then      lvim.builtin.autopairs.on_config_done(autopairs)    end +  pcall(function() +    local cmp_autopairs = require "nvim-autopairs.completion.cmp" +    require("cmp").event:on("confirm_done", cmp_autopairs.on_confirm_done()) +  end)  end  return M diff --git a/lua/lvim/core/bufferline.lua b/lua/lvim/core/bufferline.lua index 28e0f06d..7e8f1376 100644 --- a/lua/lvim/core/bufferline.lua +++ b/lua/lvim/core/bufferline.lua @@ -45,10 +45,10 @@ M.config = function()      },      highlights = {        background = { -        gui = "italic", +        italic = true,        },        buffer_selected = { -        gui = "bold", +        bold = true,        },      },      options = { diff --git a/lua/lvim/core/builtins/init.lua b/lua/lvim/core/builtins/init.lua index e219d45e..5cad2a00 100644 --- a/lua/lvim/core/builtins/init.lua +++ b/lua/lvim/core/builtins/init.lua @@ -16,6 +16,7 @@ local builtins = {    "lvim.core.notify",    "lvim.core.lualine",    "lvim.core.alpha", +  "lvim.core.mason",  }  function M.config(config) diff --git a/lua/lvim/core/cmp.lua b/lua/lvim/core/cmp.lua index 942a72f6..10cf56be 100644 --- a/lua/lvim/core/cmp.lua +++ b/lua/lvim/core/cmp.lua @@ -1,24 +1,23 @@  local M = {}  M.methods = {} ----checks if the character preceding the cursor is a space character ----@return boolean true if it is a space character, false otherwise -local check_backspace = function() -  local col = vim.fn.col "." - 1 -  return col == 0 or vim.fn.getline("."):sub(col, col):match "%s" +local has_words_before = function() +  local line, col = unpack(vim.api.nvim_win_get_cursor(0)) +  return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match "%s" == nil  end -M.methods.check_backspace = check_backspace +M.methods.has_words_before = has_words_before -local function T(str) +---@deprecated use M.methods.has_words_before instead +M.methods.check_backspace = function() +  return not has_words_before() +end + +local T = function(str)    return vim.api.nvim_replace_termcodes(str, true, true, true)  end ----wraps vim.fn.feedkeys while replacing key codes with escape codes ----Ex: feedkeys("<CR>", "n") becomes feedkeys("^M", "n") ----@param key string ----@param mode string  local function feedkeys(key, mode) -  vim.fn.feedkeys(T(key), mode) +  vim.api.nvim_feedkeys(T(key), mode, true)  end  M.methods.feedkeys = feedkeys @@ -28,39 +27,21 @@ M.methods.feedkeys = feedkeys  local function jumpable(dir)    local luasnip_ok, luasnip = pcall(require, "luasnip")    if not luasnip_ok then -    return +    return false    end    local win_get_cursor = vim.api.nvim_win_get_cursor    local get_current_buf = vim.api.nvim_get_current_buf -  local function inside_snippet() -    -- for outdated versions of luasnip -    if not luasnip.session.current_nodes then -      return false -    end - -    local node = luasnip.session.current_nodes[get_current_buf()] -    if not node then -      return false -    end - -    local snip_begin_pos, snip_end_pos = node.parent.snippet.mark:pos_begin_end() -    local pos = win_get_cursor(0) -    pos[1] = pos[1] - 1 -- LuaSnip is 0-based not 1-based like nvim for rows -    return pos[1] >= snip_begin_pos[1] and pos[1] <= snip_end_pos[1] -  end -    ---sets the current buffer's luasnip to the one nearest the cursor    ---@return boolean true if a node is found, false otherwise    local function seek_luasnip_cursor_node() +    -- TODO(kylo252): upstream this      -- for outdated versions of luasnip      if not luasnip.session.current_nodes then        return false      end -    local pos = win_get_cursor(0) -    pos[1] = pos[1] - 1      local node = luasnip.session.current_nodes[get_current_buf()]      if not node then        return false @@ -69,6 +50,9 @@ local function jumpable(dir)      local snippet = node.parent.snippet      local exit_node = snippet.insert_nodes[0] +    local pos = win_get_cursor(0) +    pos[1] = pos[1] - 1 +      -- exit early if we're past the exit node      if exit_node then        local exit_pos_end = exit_node.mark:pos_end() @@ -124,9 +108,9 @@ local function jumpable(dir)    end    if dir == -1 then -    return inside_snippet() and luasnip.jumpable(-1) +    return luasnip.in_snippet() and luasnip.jumpable(-1)    else -    return inside_snippet() and seek_luasnip_cursor_node() and luasnip.jumpable() +    return luasnip.in_snippet() and seek_luasnip_cursor_node() and luasnip.jumpable(1)    end  end  M.methods.jumpable = jumpable @@ -241,48 +225,61 @@ M.config = function()      mapping = cmp.mapping.preset.insert {        ["<C-k>"] = cmp.mapping.select_prev_item(),        ["<C-j>"] = cmp.mapping.select_next_item(), +      ["<Down>"] = cmp.mapping(cmp.mapping.select_next_item { behavior = cmp.SelectBehavior.Select }, { "i" }), +      ["<Up>"] = cmp.mapping(cmp.mapping.select_prev_item { behavior = cmp.SelectBehavior.Select }, { "i" }),        ["<C-d>"] = cmp.mapping.scroll_docs(-4),        ["<C-f>"] = cmp.mapping.scroll_docs(4), +      ["<C-y>"] = cmp.mapping { +        i = cmp.mapping.confirm { behavior = cmp.ConfirmBehavior.Replace, select = false }, +        c = function(fallback) +          if cmp.visible() then +            cmp.confirm { behavior = cmp.ConfirmBehavior.Replace, select = false } +          else +            fallback() +          end +        end, +      },        ["<Tab>"] = cmp.mapping(function(fallback)          if cmp.visible() then            cmp.select_next_item() -        elseif luasnip.expandable() then -          luasnip.expand() -        elseif jumpable() then +        elseif luasnip.expand_or_locally_jumpable() then +          luasnip.expand_or_jump() +        elseif jumpable(1) then            luasnip.jump(1) -        elseif check_backspace() then -          fallback() +        elseif has_words_before() then +          cmp.complete()          else            fallback()          end -      end, { -        "i", -        "s", -      }), +      end, { "i", "s" }),        ["<S-Tab>"] = cmp.mapping(function(fallback)          if cmp.visible() then            cmp.select_prev_item() -        elseif jumpable(-1) then +        elseif luasnip.jumpable(-1) then            luasnip.jump(-1)          else            fallback()          end -      end, { -        "i", -        "s", -      }), - +      end, { "i", "s" }),        ["<C-Space>"] = cmp.mapping.complete(),        ["<C-e>"] = cmp.mapping.abort(),        ["<CR>"] = cmp.mapping(function(fallback) -        if cmp.visible() and cmp.confirm(lvim.builtin.cmp.confirm_opts) then -          if jumpable() then +        if cmp.visible() then +          local confirm_opts = lvim.builtin.cmp.confirm_opts +          local is_insert_mode = function() +            return vim.api.nvim_get_mode().mode:sub(1, 1) == "i" +          end +          if is_insert_mode() then -- prevent overwriting brackets +            confirm_opts.behavior = cmp.ConfirmBehavior.Insert +          end +          cmp.confirm(confirm_opts) +          if jumpable(1) then              luasnip.jump(1)            end            return          end -        if jumpable() then +        if jumpable(1) then            if not luasnip.jump(1) then              fallback()            end diff --git a/lua/lvim/core/comment.lua b/lua/lvim/core/comment.lua index 86a2091a..d07739c6 100644 --- a/lua/lvim/core/comment.lua +++ b/lua/lvim/core/comment.lua @@ -3,8 +3,24 @@ local M = {}  function M.config()    local pre_hook = nil    if lvim.builtin.treesitter.context_commentstring.enable then -    pre_hook = function(_ctx) -      return require("ts_context_commentstring.internal").calculate_commentstring() +    pre_hook = function(ctx) +      local U = require "Comment.utils" + +      -- Determine whether to use linewise or blockwise commentstring +      local type = ctx.ctype == U.ctype.linewise and "__default" or "__multiline" + +      -- Determine the location where to calculate commentstring from +      local location = nil +      if ctx.ctype == U.ctype.blockwise then +        location = require("ts_context_commentstring.utils").get_cursor_location() +      elseif ctx.cmotion == U.cmotion.v or ctx.cmotion == U.cmotion.V then +        location = require("ts_context_commentstring.utils").get_visual_start_location() +      end + +      return require("ts_context_commentstring.internal").calculate_commentstring { +        key = type, +        location = location, +      }      end    end    lvim.builtin.comment = { diff --git a/lua/lvim/core/info.lua b/lua/lvim/core/info.lua index ac7d690a..da9ddbe6 100644 --- a/lua/lvim/core/info.lua +++ b/lua/lvim/core/info.lua @@ -111,9 +111,9 @@ local function make_auto_lsp_info(ft)      return info_lines    end -  local available = lsp_utils.get_supported_servers_per_filetype(ft) +  local supported = lsp_utils.get_supported_servers(ft)    local skipped = vim.tbl_filter(function(name) -    return vim.tbl_contains(available, name) +    return vim.tbl_contains(supported, name)    end, skipped_servers)    if #skipped == 0 then diff --git a/lua/lvim/core/lualine/components.lua b/lua/lvim/core/lualine/components.lua index 49a8ff81..5095cfb4 100644 --- a/lua/lvim/core/lualine/components.lua +++ b/lua/lvim/core/lualine/components.lua @@ -70,13 +70,13 @@ return {    },    treesitter = {      function() -      local b = vim.api.nvim_get_current_buf() -      if next(vim.treesitter.highlighter.active[b]) then -        return "" -      end -      return "" +      return "" +    end, +    color = function() +      local buf = vim.api.nvim_get_current_buf() +      local ts = vim.treesitter.highlighter.active[buf] +      return { fg = ts and not vim.tbl_isempty(ts) and colors.green or colors.red }      end, -    color = { fg = colors.green },      cond = conditions.hide_in_width,    },    lsp = { diff --git a/lua/lvim/core/mason.lua b/lua/lvim/core/mason.lua new file mode 100644 index 00000000..39be4f42 --- /dev/null +++ b/lua/lvim/core/mason.lua @@ -0,0 +1,41 @@ +local M = {} + +function M.config() +  lvim.builtin.mason = { +    ui = { +      keymaps = { +        toggle_package_expand = "<CR>", +        install_package = "i", +        update_package = "u", +        check_package_version = "c", +        update_all_packages = "U", +        check_outdated_packages = "C", +        uninstall_package = "X", +        cancel_installation = "<C-c>", +        apply_language_filter = "<C-f>", +      }, +    }, +    log_level = vim.log.levels.INFO, +    max_concurrent_installers = 4, + +    github = { +      -- The template URL to use when downloading assets from GitHub. +      -- The placeholders are the following (in order): +      -- 1. The repository (e.g. "rust-lang/rust-analyzer") +      -- 2. The release version (e.g. "v0.3.0") +      -- 3. The asset name (e.g. "rust-analyzer-v0.3.0-x86_64-unknown-linux-gnu.tar.gz") +      download_url_template = "https://github.com/%s/releases/download/%s/%s", +    }, +  } +end + +function M.setup() +  local status_ok, mason = pcall(require, "mason") +  if not status_ok then +    return +  end + +  mason.setup(lvim.builtin.mason) +end + +return M diff --git a/lua/lvim/core/which-key.lua b/lua/lvim/core/which-key.lua index 3015781b..2301943f 100644 --- a/lua/lvim/core/which-key.lua +++ b/lua/lvim/core/which-key.lua @@ -1,5 +1,4 @@  local M = {} -  M.config = function()    lvim.builtin.which_key = {      ---@usage disable which-key completely [not recommended] @@ -77,13 +76,13 @@ M.config = function()      -- NOTE: Prefer using : over <cmd> as the latter avoids going back in normal-mode.      -- see https://neovim.io/doc/user/map.html#:map-cmd      vmappings = { -      ["/"] = { "<ESC><CMD>lua require('Comment.api').toggle_linewise_op(vim.fn.visualmode())<CR>", "Comment" }, +      ["/"] = { "<Plug>(comment_toggle_linewise_visual)", "Comment toggle linewise (visual)" },      },      mappings = {        [";"] = { "<cmd>Alpha<CR>", "Dashboard" },        ["w"] = { "<cmd>w!<CR>", "Save" },        ["q"] = { "<cmd>lua require('lvim.utils.functions').smart_quit()<CR>", "Quit" }, -      ["/"] = { "<cmd>lua require('Comment.api').toggle_current_linewise()<CR>", "Comment" }, +      ["/"] = { "<Plug>(comment_toggle_linewise_current)", "Comment toggle current line" },        ["c"] = { "<cmd>BufferKill<CR>", "Close Buffer" },        ["f"] = { require("lvim.core.telescope.custom-finders").find_project_files, "Find File" },        ["h"] = { "<cmd>nohlsearch<CR>", "No Highlight" }, @@ -92,6 +91,7 @@ M.config = function()          j = { "<cmd>BufferLinePick<cr>", "Jump" },          f = { "<cmd>Telescope buffers<cr>", "Find" },          b = { "<cmd>BufferLineCyclePrev<cr>", "Previous" }, +        n = { "<cmd>BufferLineCycleNext<cr>", "Next" },          -- w = { "<cmd>BufferWipeout<cr>", "Wipeout" }, -- TODO: implement this for bufferline          e = {            "<cmd>BufferLinePickClose<cr>", @@ -160,7 +160,7 @@ M.config = function()          w = { "<cmd>Telescope diagnostics<cr>", "Diagnostics" },          f = { require("lvim.lsp.utils").format, "Format" },          i = { "<cmd>LspInfo<cr>", "Info" }, -        I = { "<cmd>LspInstallInfo<cr>", "Installer Info" }, +        I = { "<cmd>Mason<cr>", "Mason Info" },          j = {            vim.diagnostic.goto_next,            "Next Diagnostic", @@ -252,7 +252,7 @@ M.config = function()          k = { "<cmd>Telescope keymaps<cr>", "Keymaps" },          C = { "<cmd>Telescope commands<cr>", "Commands" },          p = { -          "<cmd>lua require('telescope.builtin.internal').colorscheme({enable_preview = true})<cr>", +          "<cmd>lua require('telescope.builtin').colorscheme({enable_preview = true})<cr>",            "Colorscheme with Preview",          },        }, diff --git a/lua/lvim/keymappings.lua b/lua/lvim/keymappings.lua index 137f1cc0..82113398 100644 --- a/lua/lvim/keymappings.lua +++ b/lua/lvim/keymappings.lua @@ -61,10 +61,6 @@ local defaults = {      ["<C-Left>"] = ":vertical resize -2<CR>",      ["<C-Right>"] = ":vertical resize +2<CR>", -    -- Tab switch buffer -    ["<S-l>"] = ":BufferLineCycleNext<CR>", -    ["<S-h>"] = ":BufferLineCyclePrev<CR>", -      -- Move current line / block with Alt-j/k a la vscode.      ["<A-j>"] = ":m .+1<CR>==",      ["<A-k>"] = ":m .-2<CR>==", diff --git a/lua/lvim/lsp/config.lua b/lua/lvim/lsp/config.lua index e3cd503b..2cd1bc6e 100644 --- a/lua/lvim/lsp/config.lua +++ b/lua/lvim/lsp/config.lua @@ -30,7 +30,6 @@ local skipped_servers = {    "sqlls",    "sqls",    "stylelint_lsp", -  "tailwindcss",    "tflint",    "svlangserver",    "verible", @@ -88,7 +87,6 @@ return {    },    on_attach_callback = nil,    on_init_callback = nil, -  automatic_servers_installation = true,    automatic_configuration = {      ---@usage list of servers that the automatic installer will skip      skipped_servers = skipped_servers, @@ -131,12 +129,8 @@ return {    installer = {      setup = {        ensure_installed = {}, -      ui = { -        icons = { -          server_installed = "✓", -          server_pending = "", -          server_uninstalled = "✗", -        }, +      automatic_installation = { +        exclude = {},        },      },    }, @@ -153,6 +147,8 @@ return {      setup = {},      config = {},    }, -  ---@deprecated use automatic_configuration.skipped_servers instead +  ---@deprecated use lvim.lsp.automatic_configuration.skipped_servers instead    override = {}, +  ---@deprecated use lvim.lsp.installer.setup.automatic_installation instead +  automatic_servers_installation = nil,  } diff --git a/lua/lvim/lsp/init.lua b/lua/lvim/lsp/init.lua index 53b4f248..0b361972 100644 --- a/lua/lvim/lsp/init.lua +++ b/lua/lvim/lsp/init.lua @@ -110,7 +110,10 @@ function M.setup()    end)    pcall(function() -    require("nvim-lsp-installer").setup(lvim.lsp.installer.setup) +    require("mason-lspconfig").setup(lvim.lsp.installer.setup) +    local util = require "lspconfig.util" +    -- automatic_installation is handled by lsp-manager +    util.on_setup = nil    end)    require("lvim.lsp.null-ls").setup() diff --git a/lua/lvim/lsp/manager.lua b/lua/lvim/lsp/manager.lua index 00643815..1323ace7 100644 --- a/lua/lvim/lsp/manager.lua +++ b/lua/lvim/lsp/manager.lua @@ -1,7 +1,30 @@  local M = {}  local Log = require "lvim.core.log" +local fmt = string.format  local lvim_lsp_utils = require "lvim.lsp.utils" +local is_windows = vim.loop.os_uname().version:match "Windows" + +local function resolve_mason_config(server_name) +  local found, mason_config = pcall(require, "mason-lspconfig.server_configurations." .. server_name) +  if not found then +    Log:debug(fmt("mason configuration not found for %s", server_name)) +    return {} +  end +  local server_mapping = require "mason-lspconfig.mappings.server" +  local path = require "mason-core.path" +  local pkg_name = server_mapping.lspconfig_to_package[server_name] +  local install_dir = path.package_prefix(pkg_name) +  local conf = mason_config(install_dir) +  if is_windows and conf.cmd and conf.cmd[1] then +    local exepath = vim.fn.exepath(conf.cmd[1]) +    if exepath ~= "" then +      conf.cmd[1] = exepath +    end +  end +  Log:debug(fmt("resolved mason configuration for %s, got %s", server_name, vim.inspect(conf))) +  return conf or {} +end  ---Resolve the configuration for a server by merging with the default config  ---@param server_name string @@ -65,35 +88,45 @@ function M.setup(server_name, user_config)      return    end -  local servers = require "nvim-lsp-installer.servers" -  local server_available, server = servers.get_server(server_name) +  local server_mapping = require "mason-lspconfig.mappings.server" +  local registry = require "mason-registry" -  if not server_available then +  local pkg_name = server_mapping.lspconfig_to_package[server_name] +  if not pkg_name then      local config = resolve_config(server_name, user_config)      launch_server(server_name, config)      return    end -  local install_in_progress = false +  local should_auto_install = function(name) +    local installer_settings = lvim.lsp.installer.setup +    return installer_settings.automatic_installation +      and not vim.tbl_contains(installer_settings.automatic_installation.exclude, name) +  end -  if not server:is_installed() then -    if lvim.lsp.automatic_servers_installation then +  if not registry.is_installed(pkg_name) then +    if should_auto_install(server_name) then        Log:debug "Automatic server installation detected" -      server:install() -      install_in_progress = true +      vim.notify_once(string.format("Installation in progress for [%s]", server_name), vim.log.levels.INFO) +      local pkg = registry.get_package(pkg_name) +      pkg:install():once("closed", function() +        if pkg:is_installed() then +          vim.schedule(function() +            vim.notify_once(string.format("Installation complete for [%s]", server_name), vim.log.levels.INFO) +            -- mason config is only available once the server has been installed +            local config = resolve_config(server_name, resolve_mason_config(server_name), user_config) +            launch_server(server_name, config) +          end) +        end +      end) +      return      else -      Log:debug(server.name .. " is not managed by the automatic installer") +      Log:debug(server_name .. " is not managed by the automatic installer")      end    end -  server:on_ready(function() -    if install_in_progress then -      vim.notify(string.format("Installation complete for [%s] server", server.name), vim.log.levels.INFO) -    end -    install_in_progress = false -    local config = resolve_config(server_name, server:get_default_options(), user_config) -    launch_server(server_name, config) -  end) +  local config = resolve_config(server_name, resolve_mason_config(server_name), user_config) +  launch_server(server_name, config)  end  return M diff --git a/lua/lvim/lsp/null-ls/linters.lua b/lua/lvim/lsp/null-ls/linters.lua index 07c8094b..ba7670d3 100644 --- a/lua/lvim/lsp/null-ls/linters.lua +++ b/lua/lvim/lsp/null-ls/linters.lua @@ -6,9 +6,19 @@ local null_ls = require "null-ls"  local services = require "lvim.lsp.null-ls.services"  local method = null_ls.methods.DIAGNOSTICS +local alternative_methods = { +  null_ls.methods.DIAGNOSTICS, +  null_ls.methods.DIAGNOSTICS_ON_OPEN, +  null_ls.methods.DIAGNOSTICS_ON_SAVE, +} +  function M.list_registered(filetype)    local registered_providers = services.list_registered_providers_names(filetype) -  return registered_providers[method] or {} +  local providers_for_methods = vim.tbl_flatten(vim.tbl_map(function(m) +    return registered_providers[m] or {} +  end, alternative_methods)) + +  return providers_for_methods  end  function M.list_supported(filetype) diff --git a/lua/lvim/lsp/providers/tailwindcss.lua b/lua/lvim/lsp/providers/tailwindcss.lua new file mode 100644 index 00000000..063cf89f --- /dev/null +++ b/lua/lvim/lsp/providers/tailwindcss.lua @@ -0,0 +1,8 @@ +local opts = { +  root_dir = function(fname) +    local util = require "lspconfig/util" +    return util.root_pattern("tailwind.config.js", "tailwind.config.cjs", "tailwind.js", "tailwind.cjs")(fname) +  end, +} + +return opts diff --git a/lua/lvim/lsp/templates.lua b/lua/lvim/lsp/templates.lua index 578362a7..dc2e5b11 100644 --- a/lua/lvim/lsp/templates.lua +++ b/lua/lvim/lsp/templates.lua @@ -56,21 +56,12 @@ end  ---The files are generated to a runtimepath: "$LUNARVIM_RUNTIME_DIR/site/after/ftplugin/template.lua"  ---@param servers_names? table list of servers to be enabled. Will add all by default  function M.generate_templates(servers_names) -  servers_names = servers_names or {} +  servers_names = servers_names or lvim_lsp_utils.get_supported_servers()    Log:debug "Templates installation in progress"    M.remove_template_files() -  if vim.tbl_isempty(servers_names) then -    local available_servers = require("nvim-lsp-installer.servers").get_available_servers() - -    for _, server in pairs(available_servers) do -      table.insert(servers_names, server.name) -      table.sort(servers_names) -    end -  end -    -- create the directory if it didn't exist    if not utils.is_directory(lvim.lsp.templates_dir) then      vim.fn.mkdir(ftplugin_dir, "p") diff --git a/lua/lvim/lsp/utils.lua b/lua/lvim/lsp/utils.lua index fa1ac6d9..b92ef11c 100644 --- a/lua/lvim/lsp/utils.lua +++ b/lua/lvim/lsp/utils.lua @@ -51,37 +51,34 @@ end  ---Get supported filetypes per server  ---@param server_name string can be any server supported by nvim-lsp-installer ----@return table supported filestypes as a list of strings +---@return string[] supported filestypes as a list of strings  function M.get_supported_filetypes(server_name) -  local status_ok, lsp_installer_servers = pcall(require, "nvim-lsp-installer.servers") +  local status_ok, config = pcall(require, ("lspconfig.server_configurations.%s"):format(server_name))    if not status_ok then      return {}    end -  local server_available, requested_server = lsp_installer_servers.get_server(server_name) -  if not server_available then -    return {} -  end - -  return requested_server:get_supported_filetypes() +  return config.default_config.filetypes or {}  end  ---Get supported servers per filetype ----@param filetype string ----@return table list of names of supported servers -function M.get_supported_servers_per_filetype(filetype) -  local filetype_server_map = require "nvim-lsp-installer._generated.filetype_map" -  return filetype_server_map[filetype] +---@param filter { filetype: string | string[] }?: (optional) Used to filter the list of server names. +---@return string[] list of names of supported servers +function M.get_supported_servers(filter) +  local _, supported_servers = pcall(function() +    return require("mason-lspconfig").get_available_servers(filter) +  end) +  return supported_servers or {}  end  ---Get all supported filetypes by nvim-lsp-installer ----@return table supported filestypes as a list of strings +---@return string[] supported filestypes as a list of strings  function M.get_all_supported_filetypes() -  local status_ok, lsp_installer_filetypes = pcall(require, "nvim-lsp-installer._generated.filetype_map") +  local status_ok, filetype_server_map = pcall(require, "mason-lspconfig.mappings.filetype")    if not status_ok then      return {}    end -  return vim.tbl_keys(lsp_installer_filetypes or {}) +  return vim.tbl_keys(filetype_server_map or {})  end  function M.setup_document_highlight(client, bufnr) diff --git a/lua/lvim/plugins.lua b/lua/lvim/plugins.lua index fec91bc9..24f71204 100644 --- a/lua/lvim/plugins.lua +++ b/lua/lvim/plugins.lua @@ -7,8 +7,12 @@ local core_plugins = {      "jose-elias-alvarez/null-ls.nvim",    },    { "antoinemadec/FixCursorHold.nvim" }, -- Needed while issue https://github.com/neovim/neovim/issues/12587 is still open +  { "williamboman/mason-lspconfig.nvim" },    { -    "williamboman/nvim-lsp-installer", +    "williamboman/mason.nvim", +    config = function() +      require("lvim.core.mason").setup() +    end,    },    {      "lunarvim/onedarker.nvim", diff --git a/snapshots/default.json b/snapshots/default.json index 564e26b3..84990838 100644 --- a/snapshots/default.json +++ b/snapshots/default.json @@ -1,78 +1,81 @@  {    "Comment.nvim": { -    "commit": "2e0572c" +    "commit": "80e7746"    },    "FixCursorHold.nvim": {      "commit": "5aa5ff1"    },    "LuaSnip": { -    "commit": "be3083b" +    "commit": "9f454cc"    },    "alpha-nvim": { -    "commit": "14974c3" +    "commit": "f457f7f"    },    "bufferline.nvim": { -    "commit": "d7b775a" +    "commit": "13a532e"    },    "cmp-buffer": { -    "commit": "62fc67a" +    "commit": "3022dbc"    },    "cmp-nvim-lsp": {      "commit": "affe808"    },    "cmp-path": { -    "commit": "981baf9" +    "commit": "447c87c"    },    "cmp_luasnip": {      "commit": "a9de941"    },    "dap-buddy.nvim": { -    "commit": "bbda2b0" +    "commit": "3679132"    },    "friendly-snippets": { -    "commit": "40c306b" +    "commit": "e5a16f9"    },    "gitsigns.nvim": { -    "commit": "bb6c3bf" +    "commit": "1e107c9"    },    "lua-dev.nvim": {      "commit": "54149d1"    },    "lualine.nvim": { -    "commit": "8d956c1" +    "commit": "3cf4540" +  }, +  "mason-lspconfig.nvim": { +    "commit": "74c45b3" +  }, +  "mason.nvim": { +    "commit": "9249238"    },    "nlsp-settings.nvim": { -    "commit": "6c4e1a4" +    "commit": "1ffdeff"    },    "null-ls.nvim": { -    "commit": "9c396ab" +    "commit": "753ad51"    },    "nvim-autopairs": { -    "commit": "972a797" +    "commit": "0a18e10"    },    "nvim-cmp": { -    "commit": "c4dcb12" +    "commit": "058100d"    },    "nvim-dap": { -    "commit": "c0f43f4" -  }, -  "nvim-lsp-installer": { -    "commit": "45571e1" +    "commit": "57003a0"    },    "nvim-lspconfig": { -    "commit": "3479473" +    "commit": "636ce36"    },    "nvim-notify": { -    "commit": "74ba257" +    "commit": "cf5dc4f"    },    "nvim-tree.lua": { -    "commit": "08ab346" +    "commit": "4a725c0"    },    "nvim-treesitter": { -    "commit": "07b7221" +    "commit": "f3c53d2"    },    "nvim-ts-context-commentstring": { -    "commit": "8834375" +    "commit": "4d3a68c"    },    "nvim-web-devicons": {      "commit": "2d02a56" @@ -81,31 +84,31 @@      "commit": "b00dd21"    },    "packer.nvim": { -    "commit": "494fd59" +    "commit": "3a9f980"    },    "plenary.nvim": { -    "commit": "986ad71" +    "commit": "a3dafaa"    },    "popup.nvim": {      "commit": "b7404d3"    },    "project.nvim": { -    "commit": "541115e" +    "commit": "090bb11"    },    "schemastore.nvim": { -    "commit": "fbc7c71" +    "commit": "8f3a6e8"    },    "structlog.nvim": {      "commit": "232a8e2"    },    "telescope-fzf-native.nvim": { -    "commit": "6a33ece" +    "commit": "6791f74"    },    "telescope.nvim": { -    "commit": "273ccff" +    "commit": "8dce937"    },    "toggleterm.nvim": { -    "commit": "9db6f98" +    "commit": "f494c61"    },    "which-key.nvim": {      "commit": "f03a259" diff --git a/tests/minimal_lsp.lua b/tests/minimal_lsp.lua index a610fd7f..09224f94 100644 --- a/tests/minimal_lsp.lua +++ b/tests/minimal_lsp.lua @@ -16,7 +16,7 @@ local package_root = join_paths(temp_dir, "nvim", "site", "pack")  local install_path = join_paths(package_root, "packer", "start", "packer.nvim")  local compile_path = join_paths(install_path, "plugin", "packer_compiled.lua") --- Choose whether to use the executable that's managed by lsp-installer +-- Choose whether to use the executable that's managed by mason  local use_lsp_installer = true  local function load_plugins() @@ -24,7 +24,8 @@ local function load_plugins()      {        "wbthomason/packer.nvim",        "neovim/nvim-lspconfig", -      { "williamboman/nvim-lsp-installer", disable = not use_lsp_installer }, +      "williamboman/mason-lspconfig.nvim", +      "williamboman/mason.nvim",      },      config = {        package_root = package_root, @@ -44,9 +45,6 @@ _G.load_config = function()    require("vim.lsp.log").set_format_func(vim.inspect)    local nvim_lsp = require "lspconfig"    local on_attach = function(_, bufnr) -    local function buf_set_keymap(...) -      vim.api.nvim_buf_set_keymap(bufnr, ...) -    end      local function buf_set_option(...)        vim.api.nvim_buf_set_option(bufnr, ...)      end @@ -54,24 +52,26 @@ _G.load_config = function()      buf_set_option("omnifunc", "v:lua.vim.lsp.omnifunc")      -- Mappings. -    local opts = { noremap = true, silent = true } -    buf_set_keymap("n", "gD", "<Cmd>lua vim.lsp.buf.declaration()<CR>", opts) -    buf_set_keymap("n", "gd", "<Cmd>lua vim.lsp.buf.definition()<CR>", opts) -    buf_set_keymap("n", "K", "<Cmd>lua vim.lsp.buf.hover()<CR>", opts) -    buf_set_keymap("n", "gi", "<cmd>lua vim.lsp.buf.implementation()<CR>", opts) -    buf_set_keymap("n", "<C-k>", "<cmd>lua vim.lsp.buf.signature_help()<CR>", opts) -    buf_set_keymap("n", "<space>wa", "<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>", opts) -    buf_set_keymap("n", "<space>wr", "<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>", opts) -    buf_set_keymap("n", "<space>wl", "<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>", opts) -    buf_set_keymap("n", "<space>lD", "<cmd>lua vim.lsp.buf.type_definition()<CR>", opts) -    buf_set_keymap("n", "<space>lr", "<cmd>lua vim.lsp.buf.rename()<CR>", opts) -    buf_set_keymap("n", "gr", "<cmd>lua vim.lsp.buf.references()<CR>", opts) -    buf_set_keymap("n", "gl", "<cmd>lua vim.diagnostic.open_float(0,{scope='line'})<CR>", opts) -    buf_set_keymap("n", "<space>lk", "<cmd>lua vim.diagnostic.goto_prev()<CR>", opts) -    buf_set_keymap("n", "<space>lj", "<cmd>lua vim.diagnostic.goto_next()<CR>", opts) -    buf_set_keymap("n", "<space>lq", "<cmd>lua vim.diagnostic.setloclist()<CR>", opts) -    buf_set_keymap("n", "<space>li", "<cmd>LspInfo<CR>", opts) -    buf_set_keymap("n", "<space>lI", "<cmd>LspInstallInfo<CR>", opts) +    local opts = { buffer = bufnr, noremap = true, silent = true } +    vim.keymap.set("n", "gD", vim.lsp.buf.declaration, opts) +    vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts) +    vim.keymap.set("n", "K", vim.lsp.buf.hover, opts) +    vim.keymap.set("n", "gi", vim.lsp.buf.implementation, opts) +    vim.keymap.set("n", "<C-k>", vim.lsp.buf.signature_help, opts) +    vim.keymap.set("n", "<space>wa", vim.lsp.buf.add_workspace_folder, opts) +    vim.keymap.set("n", "<space>wr", vim.lsp.buf.remove_workspace_folder, opts) +    vim.keymap.set("n", "<space>wl", function() +      print(vim.inspect(vim.lsp.buf.list_workspace_folders())) +    end, opts) +    vim.keymap.set("n", "<space>lD", vim.lsp.buf.type_definition, opts) +    vim.keymap.set("n", "<space>lr", vim.lsp.buf.rename, opts) +    vim.keymap.set("n", "gr", vim.lsp.buf.references, opts) +    vim.keymap.set("n", "gl", vim.diagnostic.open_float, opts) +    vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, opts) +    vim.keymap.set("n", "]d", vim.diagnostic.goto_next, opts) +    vim.keymap.set("n", "<space>q", vim.diagnostic.setloclist, opts) +    vim.keymap.set("n", "<space>li", "<cmd>LspInfo<CR>", opts) +    vim.keymap.set("n", "<space>lI", "<cmd>MasonCR>", opts)    end    -- Add the server that troubles you here, e.g. "clangd", "pyright", "tsserver" @@ -81,15 +81,6 @@ _G.load_config = function()      on_attach = on_attach,    } -  if use_lsp_installer then -    local server_available, server = require("nvim-lsp-installer.servers").get_server(name) -    if not server_available then -      server:install() -    end -    local default_opts = server:get_default_options() -    setup_opts = vim.tbl_deep_extend("force", setup_opts, default_opts) -  end -    if not name then      print "You have not defined a server name, please edit minimal_init.lua"    end @@ -99,6 +90,10 @@ _G.load_config = function()    end    nvim_lsp[name].setup(setup_opts) +  if use_lsp_installer then +    require("mason-lspconfig").setup { automatic_installation = true } +  end +    print [[You can find your log at $HOME/.cache/nvim/lsp.log. Please paste in a github issue under a details tag as described in the issue template.]]  end diff --git a/tests/specs/lsp_spec.lua b/tests/specs/lsp_spec.lua index 7d9a3386..01e5e1d3 100644 --- a/tests/specs/lsp_spec.lua +++ b/tests/specs/lsp_spec.lua @@ -53,10 +53,14 @@ a.describe("lsp workflow", function()    a.it("should only include one server per generated template", function()      require("lvim.lsp").setup() +    local allowed_dupes = { "tailwindcss" }      for _, file in ipairs(vim.fn.glob(lvim.lsp.templates_dir .. "/*.lua", 1, 1)) do        local content = {}        for entry in io.lines(file) do -        table.insert(content, entry) +        local server_name = entry:match [[.*setup%("(.*)"%)]] +        if not vim.tbl_contains(allowed_dupes, server_name) then +          table.insert(content, server_name) +        end        end        local err_msg = ""        if #content > 1 then diff --git a/utils/ci/generate_new_lockfile.lua b/utils/ci/generate_new_lockfile.lua index fd10775c..8eef5184 100644 --- a/utils/ci/generate_new_lockfile.lua +++ b/utils/ci/generate_new_lockfile.lua @@ -70,6 +70,7 @@ local function write_lockfile(verbose)        name = name,        url = url,        commit = commit, +      branch = plugin.branch or "HEAD",      })    end @@ -90,7 +91,7 @@ local function write_lockfile(verbose)        }      end -    local handle = call_proc("git", { args = { "ls-remote", entry.url, "HEAD" } }, on_done) +    local handle = call_proc("git", { args = { "ls-remote", entry.url, entry.branch } }, on_done)      assert(handle)      table.insert(active_jobs, handle)    end diff --git a/utils/installer/config.example.lua b/utils/installer/config.example.lua index 036b8ec2..65662794 100644 --- a/utils/installer/config.example.lua +++ b/utils/installer/config.example.lua @@ -19,6 +19,8 @@ lvim.colorscheme = "onedarker"  lvim.leader = "space"  -- add your own keymapping  lvim.keys.normal_mode["<C-s>"] = ":w<cr>" +-- lvim.keys.normal_mode["<S-l>"] = ":BufferLineCycleNext<CR>" +-- lvim.keys.normal_mode["<S-h>"] = ":BufferLineCyclePrev<CR>"  -- unmap a default keymapping  -- vim.keymap.del("n", "<C-Up>")  -- override a default keymapping @@ -51,7 +53,7 @@ lvim.keys.normal_mode["<C-s>"] = ":w<cr>"  --   d = { "<cmd>Trouble document_diagnostics<cr>", "Diagnostics" },  --   q = { "<cmd>Trouble quickfix<cr>", "QuickFix" },  --   l = { "<cmd>Trouble loclist<cr>", "LocationList" }, ---   w = { "<cmd>Trouble workspace_diagnostics<cr>", "Wordspace Diagnostics" }, +--   w = { "<cmd>Trouble workspace_diagnostics<cr>", "Workspace Diagnostics" },  -- }  -- TODO: User Config for predefined plugins @@ -99,7 +101,7 @@ lvim.builtin.treesitter.highlight.enabled = true  -- }  -- ---@usage disable automatic installation of servers --- lvim.lsp.automatic_servers_installation = false +-- lvim.lsp.installer.setup.automatic_installation = false  -- ---configure a server manually. !!Requires `:LvimCacheReset` to take effect!!  -- ---see the full default list `:lua print(vim.inspect(lvim.lsp.automatic_configuration.skipped_servers))` diff --git a/utils/installer/config_win.example.lua b/utils/installer/config_win.example.lua index cb110664..6e9a1ba0 100644 --- a/utils/installer/config_win.example.lua +++ b/utils/installer/config_win.example.lua @@ -36,6 +36,8 @@ lvim.colorscheme = "onedarker"  lvim.leader = "space"  -- add your own keymapping  lvim.keys.normal_mode["<C-s>"] = ":w<cr>" +-- lvim.keys.normal_mode["<S-l>"] = ":BufferLineCycleNext<CR>" +-- lvim.keys.normal_mode["<S-h>"] = ":BufferLineCyclePrev<CR>"  -- unmap a default keymapping  -- vim.keymap.del("n", "<C-Up>")  -- override a default keymapping @@ -79,14 +81,14 @@ lvim.builtin.terminal.active = false  -- lvim.builtin.terminal.shell = "pwsh.exe -NoLogo"  -- nvim-tree has some performance issues on windows, see kyazdani42/nvim-tree.lua#549 -lvim.builtin.nvimtree.setup.diagnostics.enable = false -lvim.builtin.nvimtree.setup.filters.custom = false -lvim.builtin.nvimtree.setup.git.enable = false -lvim.builtin.nvimtree.setup.update_cwd = false -lvim.builtin.nvimtree.setup.update_focused_file.update_cwd = false +lvim.builtin.nvimtree.setup.diagnostics.enable = nil +lvim.builtin.nvimtree.setup.filters.custom = nil +lvim.builtin.nvimtree.setup.git.enable = nil +lvim.builtin.nvimtree.setup.update_cwd = nil +lvim.builtin.nvimtree.setup.update_focused_file.update_cwd = nil  lvim.builtin.nvimtree.setup.view.side = "left" -lvim.builtin.nvimtree.setup.renderer.highlight_git = false -lvim.builtin.nvimtree.setup.renderer.icons.show.git = false +lvim.builtin.nvimtree.setup.renderer.highlight_git = nil +lvim.builtin.nvimtree.setup.renderer.icons.show.git = nil  -- if you don't want all the parsers change this to a table of the ones you want  lvim.builtin.treesitter.ensure_installed = { @@ -114,7 +116,7 @@ lvim.builtin.treesitter.highlight.enabled = true  -- }  -- ---@usage disable automatic installation of servers --- lvim.lsp.automatic_servers_installation = false +-- lvim.lsp.installer.setup.automatic_installation = false  -- ---configure a server manually. !!Requires `:LvimCacheReset` to take effect!!  -- ---see the full default list `:lua print(vim.inspect(lvim.lsp.automatic_configuration.skipped_servers))` diff --git a/utils/installer/install.ps1 b/utils/installer/install.ps1 index dcfa47f4..320e377c 100644 --- a/utils/installer/install.ps1 +++ b/utils/installer/install.ps1 @@ -264,6 +264,13 @@ function create_alias {          return      } +    try { +        Get-Content $PROFILE -ErrorAction Stop +    } +    catch { +        New-Item -Path $PROFILE -ItemType "file" -Force +    } +      Add-Content -Path $PROFILE -Value $("`r`nSet-Alias lvim $lvim_bin")      Write-Host 'To use the new alias in this window reload your profile with: `. $PROFILE`' -ForegroundColor Green diff --git a/utils/installer/install.sh b/utils/installer/install.sh index dc342d12..620d46f5 100755 --- a/utils/installer/install.sh +++ b/utils/installer/install.sh @@ -26,6 +26,7 @@ declare ARGS_LOCAL=0  declare ARGS_OVERWRITE=0  declare ARGS_INSTALL_DEPENDENCIES=1  declare INTERACTIVE_MODE=1 +declare ADDITIONAL_WARNINGS=""  declare -a __lvim_dirs=(    "$LUNARVIM_CONFIG_DIR" @@ -148,6 +149,7 @@ function main() {    setup_lvim +  msg "$ADDITIONAL_WARNINGS"    msg "Thank you for installing LunarVim!!"    echo "You can start it by running: $INSTALL_PREFIX/bin/lvim"    echo "Do not forget to use a font with glyphs (icons) support [https://github.com/ryanoasis/nerd-fonts]" @@ -226,7 +228,25 @@ function validate_lunarvim_files() {    fi  } +function validate_install_prefix() { +  local prefix="$1" +  case $PATH in +    *"$prefix/bin"*) +      return +      ;; +  esac +  local profile="$HOME/.profile" +  test -z "$ZSH_VERSION" && profile="$HOME/.zshenv" +  ADDITIONAL_WARNINGS="[WARN] the folder $prefix/bin is not on PATH, consider adding 'export PATH=$prefix/bin:\$PATH' to your $profile" + +  # avoid problems when calling any verify_* function +  export PATH="$prefix/bin:$PATH" +} +  function check_system_deps() { + +  validate_install_prefix "$INSTALL_PREFIX" +    if ! command -v git &>/dev/null; then      print_missing_dep_msg "git"      exit 1 @@ -279,7 +299,6 @@ function __validate_node_installation() {    fi    if [ ! -d "$manager_home" ] || [ ! -w "$manager_home" ]; then -    echo "[ERROR] Unable to install using [$pkg_manager] without administrative privileges."      return 1    fi @@ -294,21 +313,21 @@ function install_nodejs_deps() {        return      fi    done -  print_missing_dep_msg "${pkg_managers[@]}" -  exit 1 +  echo "[WARN]: skipping installing optional nodejs dependencies due to insufficient permissions." +  echo "check how to solve it: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally"  }  function install_python_deps() {    echo "Verifying that pip is available.." -  if ! python3 -m ensurepip &>/dev/null; then +  if ! python3 -m ensurepip >/dev/null; then      if ! python3 -m pip --version &>/dev/null; then -      print_missing_dep_msg "pip" -      exit 1 +      echo "[WARN]: skipping installing optional python dependencies" +      return 1      fi    fi    echo "Installing with pip.."    for dep in "${__pip_deps[@]}"; do -    python3 -m pip install --user "$dep" +    python3 -m pip install --user "$dep" || return 1    done    echo "All Python dependencies are successfully installed"  } | 
