diff options
31 files changed, 374 insertions, 246 deletions
diff --git a/lua/lvim/bootstrap.lua b/lua/lvim/bootstrap.lua index ac6475c7..a3114a1e 100644 --- a/lua/lvim/bootstrap.lua +++ b/lua/lvim/bootstrap.lua @@ -70,14 +70,11 @@ function M:init(base_dir) self.packer_install_dir = join_paths(self.runtime_dir, "site", "pack", "packer", "start", "packer.nvim") self.packer_cache_path = join_paths(self.config_dir, "plugin", "packer_compiled.lua") - ---@meta overridden to use LUNARVIM_x_DIR instead, since a lot of plugins call this function interally + ---@meta overridden to use LUNARVIM_CACHE_DIR instead, since a lot of plugins call this function interally + ---NOTE: changes to "data" are currently unstable, see #2507 vim.fn.stdpath = function(what) if what == "cache" then return _G.get_cache_dir() - elseif what == "data" then - return _G.get_runtime_dir() - elseif what == "config" then - return _G.get_config_dir() end return vim.call("stdpath", what) end diff --git a/lua/lvim/config/defaults.lua b/lua/lvim/config/defaults.lua index fe2780eb..7bccc895 100644 --- a/lua/lvim/config/defaults.lua +++ b/lua/lvim/config/defaults.lua @@ -7,9 +7,13 @@ return { pattern = "*", ---@usage timeout number timeout in ms for the format request (Default: 1000) timeout = 1000, + ---@usage filter func to select client + filter = require("lvim.lsp.handlers").format_filter, }, keys = {}, + use_icons = true, + builtin = {}, plugins = { diff --git a/lua/lvim/core/autocmds.lua b/lua/lvim/core/autocmds.lua index e10a42db..17c9bc22 100644 --- a/lua/lvim/core/autocmds.lua +++ b/lua/lvim/core/autocmds.lua @@ -70,79 +70,44 @@ local get_format_on_save_opts = function() } end -function M.enable_format_on_save(opts) - local fmd_cmd = string.format(":silent lua vim.lsp.buf.formatting_sync({}, %s)", opts.timeout) - M.define_augroups { - format_on_save = { { "BufWritePre", opts.pattern, fmd_cmd } }, - } +function M.enable_format_on_save() + local opts = get_format_on_save_opts() + vim.api.nvim_create_augroup("lsp_format_on_save", {}) + vim.api.nvim_create_autocmd("BufWritePre", { + group = "lsp_format_on_save", + pattern = opts.pattern, + callback = function() + vim.lsp.buf.format { timeout_ms = opts.timeout, filter = opts.filter } + end, + }) Log:debug "enabled format-on-save" end function M.disable_format_on_save() - M.disable_augroup "format_on_save" + pcall(vim.api.nvim_del_augroup_by_name, "lsp_format_on_save") Log:debug "disabled format-on-save" end function M.configure_format_on_save() if lvim.format_on_save then - local opts = get_format_on_save_opts() - M.enable_format_on_save(opts) + M.enable_format_on_save() else M.disable_format_on_save() end end function M.toggle_format_on_save() - if vim.fn.exists "#format_on_save#BufWritePre" == 0 then - local opts = get_format_on_save_opts() - M.enable_format_on_save(opts) + local status, _ = pcall(vim.api.nvim_get_autocmds, { + group = "lsp_format_on_save", + event = "BufWritePre", + }) + if not status then + M.enable_format_on_save() else M.disable_format_on_save() end end -function M.enable_lsp_document_highlight(client_id) - M.define_augroups({ - lsp_document_highlight = { - { - "CursorHold", - "<buffer>", - string.format("lua require('lvim.lsp.utils').conditional_document_highlight(%d)", client_id), - }, - { - "CursorMoved", - "<buffer>", - "lua vim.lsp.buf.clear_references()", - }, - }, - }, true) -end - -function M.disable_lsp_document_highlight() - M.disable_augroup "lsp_document_highlight" -end - -function M.enable_code_lens_refresh() - M.define_augroups({ - lsp_code_lens_refresh = { - { - "InsertLeave ", - "<buffer>", - "lua vim.lsp.codelens.refresh()", - }, - { - "InsertLeave ", - "<buffer>", - "lua vim.lsp.codelens.display()", - }, - }, - }, true) -end - -function M.disable_code_lens_refresh() - M.disable_augroup "lsp_code_lens_refresh" -end - function M.enable_transparent_mode() vim.cmd "au ColorScheme * hi Normal ctermbg=none guibg=none" vim.cmd "au ColorScheme * hi SignColumn ctermbg=none guibg=none" @@ -170,7 +135,6 @@ end --- Create autocommand groups based on the passed definitions ---@param definitions table contains trigger, pattern and text. The key will be used as a group name ----@param buffer boolean indicate if the augroup should be local to the buffer function M.define_augroups(definitions, buffer) for group_name, definition in pairs(definitions) do vim.cmd("augroup " .. group_name) diff --git a/lua/lvim/core/bufferline.lua b/lua/lvim/core/bufferline.lua index d16c3d79..cb322032 100644 --- a/lua/lvim/core/bufferline.lua +++ b/lua/lvim/core/bufferline.lua @@ -4,9 +4,12 @@ local function is_ft(b, ft) return vim.bo[b].filetype == ft end -local function diagnostics_indicator(_, _, diagnostics) +local function diagnostics_indicator(num, _, diagnostics, _) local result = {} local symbols = { error = "", warning = "", info = "" } + if not lvim.use_icons then + return "(" .. num .. ")" + end for name, count in pairs(diagnostics) do if symbols[name] and count > 0 then table.insert(result, symbols[name] .. " " .. count) @@ -112,8 +115,8 @@ M.config = function() padding = 1, }, }, - show_buffer_icons = true, -- disable filetype icons for buffers - show_buffer_close_icons = true, + show_buffer_icons = lvim.use_icons, -- disable filetype icons for buffers + show_buffer_close_icons = lvim.use_icons, show_close_icon = false, show_tab_indicators = true, persist_buffer_sort = true, -- whether or not custom sorted buffers should persist diff --git a/lua/lvim/core/cmp.lua b/lua/lvim/core/cmp.lua index 4eff9883..baf6279b 100644 --- a/lua/lvim/core/cmp.lua +++ b/lua/lvim/core/cmp.lua @@ -207,6 +207,7 @@ M.config = function() vsnip = "(Snippet)", luasnip = "(Snippet)", buffer = "(Buffer)", + tmux = "(TMUX)", }, duplicates = { buffer = 1, @@ -220,7 +221,9 @@ M.config = function() if max_width ~= 0 and #vim_item.abbr > max_width then vim_item.abbr = string.sub(vim_item.abbr, 1, max_width - 1) .. "…" end - vim_item.kind = lvim.builtin.cmp.formatting.kind_icons[vim_item.kind] + if lvim.use_icons then + vim_item.kind = lvim.builtin.cmp.formatting.kind_icons[vim_item.kind] + end vim_item.menu = lvim.builtin.cmp.formatting.source_names[entry.source.name] vim_item.dup = lvim.builtin.cmp.formatting.duplicates[entry.source.name] or lvim.builtin.cmp.formatting.duplicates_default @@ -247,6 +250,7 @@ M.config = function() { name = "emoji" }, { name = "treesitter" }, { name = "crates" }, + { name = "tmux" }, }, mapping = cmp.mapping.preset.insert { ["<C-k>"] = cmp.mapping.select_prev_item(), diff --git a/lua/lvim/core/dap.lua b/lua/lvim/core/dap.lua index d9b59641..8f7eb294 100644 --- a/lua/lvim/core/dap.lua +++ b/lua/lvim/core/dap.lua @@ -28,9 +28,11 @@ end M.setup = function() local dap = require "dap" - vim.fn.sign_define("DapBreakpoint", lvim.builtin.dap.breakpoint) - vim.fn.sign_define("DapBreakpointRejected", lvim.builtin.dap.breakpoint_rejected) - vim.fn.sign_define("DapStopped", lvim.builtin.dap.stopped) + if lvim.use_icons then + vim.fn.sign_define("DapBreakpoint", lvim.builtin.dap.breakpoint) + vim.fn.sign_define("DapBreakpointRejected", lvim.builtin.dap.breakpoint_rejected) + vim.fn.sign_define("DapStopped", lvim.builtin.dap.stopped) + end dap.defaults.fallback.terminal_win_cmd = "50vsplit new" diff --git a/lua/lvim/core/gitsigns.lua b/lua/lvim/core/gitsigns.lua index c000cfda..0365fc69 100644 --- a/lua/lvim/core/gitsigns.lua +++ b/lua/lvim/core/gitsigns.lua @@ -73,6 +73,7 @@ M.config = function() sign_priority = 6, update_debounce = 200, status_formatter = nil, -- Use default + yadm = { enable = false }, }, } end diff --git a/lua/lvim/core/info.lua b/lua/lvim/core/info.lua index 00a7e85a..ac7d690a 100644 --- a/lua/lvim/core/info.lua +++ b/lua/lvim/core/info.lua @@ -69,6 +69,7 @@ end local function tbl_set_highlight(terms, highlight_group) for _, v in pairs(terms) do vim.cmd('let m=matchadd("' .. highlight_group .. '", "' .. v .. "[ ,│']\")") + vim.cmd('let m=matchadd("' .. highlight_group .. '", ", ' .. v .. '")') end end diff --git a/lua/lvim/core/lualine/styles.lua b/lua/lvim/core/lualine/styles.lua index 45c6c639..8991d9d9 100644 --- a/lua/lvim/core/lualine/styles.lua +++ b/lua/lvim/core/lualine/styles.lua @@ -11,7 +11,7 @@ styles.none = { style = "none", options = { theme = "auto", - icons_enabled = true, + icons_enabled = lvim.use_icons, component_separators = { left = "", right = "" }, section_separators = { left = "", right = "" }, disabled_filetypes = {}, @@ -40,7 +40,7 @@ styles.default = { style = "default", options = { theme = "auto", - icons_enabled = true, + icons_enabled = lvim.use_icons, component_separators = { left = "", right = "" }, section_separators = { left = "", right = "" }, disabled_filetypes = {}, @@ -69,7 +69,7 @@ styles.lvim = { style = "lvim", options = { theme = "auto", - icons_enabled = true, + icons_enabled = lvim.use_icons, component_separators = { left = "", right = "" }, section_separators = { left = "", right = "" }, disabled_filetypes = { "alpha", "NvimTree", "Outline" }, diff --git a/lua/lvim/core/notify.lua b/lua/lvim/core/notify.lua index cb62778f..2db4c4d5 100644 --- a/lua/lvim/core/notify.lua +++ b/lua/lvim/core/notify.lua @@ -39,6 +39,15 @@ local defaults = { } function M.config() + if not lvim.use_icons then + defaults.opts.icons = { + ERROR = "[ERROR]", + WARN = "[WARNING]", + INFO = "[INFo]", + DEBUG = "[DEBUG]", + TRACE = "[TRACE]", + } + end lvim.builtin.notify = vim.tbl_deep_extend("force", defaults, lvim.builtin.notify or {}) end diff --git a/lua/lvim/core/nvimtree.lua b/lua/lvim/core/nvimtree.lua index 385708ed..e4d28220 100644 --- a/lua/lvim/core/nvimtree.lua +++ b/lua/lvim/core/nvimtree.lua @@ -2,6 +2,7 @@ local M = {} local Log = require "lvim.core.log" function M.config() + local vim_show_icons = lvim.use_icons and 1 or 0 lvim.builtin.nvimtree = { active = true, on_config_done = nil, @@ -9,6 +10,8 @@ function M.config() disable_netrw = true, hijack_netrw = true, open_on_setup = false, + open_on_setup_file = false, + sort_by = "name", ignore_buffer_on_setup = false, ignore_ft_on_setup = { "startify", @@ -21,16 +24,12 @@ function M.config() enable = true, auto_open = true, }, - update_to_buf_dir = { - enable = true, - auto_open = true, - }, - auto_close = false, open_on_tab = false, hijack_cursor = false, update_cwd = false, diagnostics = { - enable = true, + enable = lvim.use_icons, + show_on_dirs = false, icons = { hint = "", info = "", @@ -57,7 +56,7 @@ function M.config() height = 30, hide_root_folder = false, side = "left", - auto_resize = false, + preserve_window_proportions = false, mappings = { custom_only = false, list = {}, @@ -66,34 +65,66 @@ function M.config() relativenumber = false, signcolumn = "yes", }, + renderer = { + indent_markers = { + enable = false, + icons = { + corner = "└ ", + edge = "│ ", + none = " ", + }, + }, + icons = { + webdev_colors = lvim.use_icons, + }, + }, filters = { dotfiles = false, custom = { "node_modules", "\\.cache" }, + exclude = {}, }, trash = { cmd = "trash", require_confirm = true, }, + log = { + enable = false, + truncate = false, + types = { + all = false, + config = false, + copy_paste = false, + diagnostics = false, + git = false, + profile = false, + }, + }, actions = { + use_system_clipboard = true, change_dir = { + enable = true, global = false, + restrict_above_cwd = false, }, open_file = { - resize_window = true, quit_on_open = false, - }, - window_picker = { - enable = false, - chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", - exclude = {}, + resize_window = false, + window_picker = { + enable = true, + chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", + exclude = { + filetype = { "notify", "packer", "qf", "diff", "fugitive", "fugitiveblame" }, + buftype = { "nofile", "terminal", "help" }, + }, + }, }, }, }, show_icons = { - git = 1, - folders = 1, - files = 1, - folder_arrows = 1, + git = vim_show_icons, + folders = vim_show_icons, + files = vim_show_icons, + folder_arrows = vim_show_icons, }, git_hl = 1, root_folder_modifier = ":t", diff --git a/lua/lvim/core/telescope.lua b/lua/lvim/core/telescope.lua index a4df4b3f..5b55bdc3 100644 --- a/lua/lvim/core/telescope.lua +++ b/lua/lvim/core/telescope.lua @@ -91,24 +91,6 @@ function M.config() }) end -function M.code_actions() - local opts = { - winblend = 15, - layout_config = { - prompt_position = "top", - width = 80, - height = 12, - }, - borderchars = lvim.builtin.telescope.defaults.borderchars, - border = {}, - previewer = false, - shorten_path = false, - } - local builtin = require "telescope.builtin" - local themes = require "telescope.themes" - builtin.lsp_code_actions(themes.get_dropdown(opts)) -end - function M.setup() local previewers = require "telescope.previewers" local sorters = require "telescope.sorters" diff --git a/lua/lvim/core/terminal.lua b/lua/lvim/core/terminal.lua index 69492a57..6c190dd5 100644 --- a/lua/lvim/core/terminal.lua +++ b/lua/lvim/core/terminal.lua @@ -108,6 +108,7 @@ M.toggle_log_view = function(logfile) if vim.fn.executable(log_viewer) ~= 1 then log_viewer = "less +F" end + Log:debug("attempting to open: " .. logfile) log_viewer = log_viewer .. " " .. logfile local term_opts = vim.tbl_deep_extend("force", lvim.builtin.terminal, { cmd = log_viewer, diff --git a/lua/lvim/core/which-key.lua b/lua/lvim/core/which-key.lua index 52b7a9ab..3c3cc66b 100644 --- a/lua/lvim/core/which-key.lua +++ b/lua/lvim/core/which-key.lua @@ -15,7 +15,7 @@ M.config = function() operators = false, -- adds help for operators like d, y, ... motions = false, -- adds help for motions text_objects = false, -- help for text objects triggered after entering an operator - windows = true, -- default bindings on <c-w> + windows = false, -- default bindings on <c-w> nav = true, -- misc bindings to work with windows z = true, -- bindings for folds, spelling and others prefixed with z g = true, -- bindings for prefixed with g @@ -27,19 +27,35 @@ M.config = function() separator = "➜", -- symbol used between a key and it's label group = "+", -- symbol prepended to a group }, + popup_mappings = { + scroll_down = "<c-d>", -- binding to scroll down inside the popup + scroll_up = "<c-u>", -- binding to scroll up inside the popup + }, window = { border = "single", -- none, single, double, shadow position = "bottom", -- bottom, top margin = { 1, 0, 1, 0 }, -- extra window margin [top, right, bottom, left] padding = { 2, 2, 2, 2 }, -- extra window padding [top, right, bottom, left] + winblend = 0, }, layout = { height = { min = 4, max = 25 }, -- min and max height of the columns width = { min = 20, max = 50 }, -- min and max width of the columns spacing = 3, -- spacing between columns + align = "left", -- align columns left, center or right }, hidden = { "<silent>", "<cmd>", "<Cmd>", "<CR>", "call", "lua", "^:", "^ " }, -- hide mapping boilerplate + ignore_missing = false, -- enable this to hide mappings for which you didn't specify a label show_help = true, -- show help message on the command line when the popup is visible + triggers = "auto", -- automatically setup triggers + -- triggers = {"<leader>"} -- or specify a list manually + triggers_blacklist = { + -- list of mode / prefixes that should never be hooked by WhichKey + -- this is mostly relevant for key maps that start with a native binding + -- most people should not need to change this + i = { "j", "k" }, + v = { "j", "k" }, + }, }, opts = { @@ -137,32 +153,31 @@ M.config = function() "Git Diff", }, }, - l = { name = "LSP", - a = { "<cmd>lua require('lvim.core.telescope').code_actions()<cr>", "Code Action" }, + a = { "<cmd>lua vim.lsp.buf.code_action()<cr>", "Code Action" }, d = { "<cmd>Telescope diagnostics bufnr=0 theme=get_ivy<cr>", "Buffer Diagnostics" }, w = { "<cmd>Telescope diagnostics<cr>", "Diagnostics" }, - f = { "<cmd>lua vim.lsp.buf.formatting()<cr>", "Format" }, + f = { require("lvim.lsp.utils").format, "Format" }, i = { "<cmd>LspInfo<cr>", "Info" }, I = { "<cmd>LspInstallInfo<cr>", "Installer Info" }, j = { - "<cmd>lua vim.diagnostic.goto_next()<cr>", + vim.diagnostic.goto_next, "Next Diagnostic", }, k = { - "<cmd>lua vim.diagnostic.goto_prev()<cr>", + vim.diagnostic.goto_prev, "Prev Diagnostic", }, - l = { "<cmd>lua vim.lsp.codelens.run()<cr>", "CodeLens Action" }, + l = { vim.lsp.codelens.run, "CodeLens Action" }, p = { name = "Peek", d = { "<cmd>lua require('lvim.lsp.peek').Peek('definition')<cr>", "Definition" }, t = { "<cmd>lua require('lvim.lsp.peek').Peek('typeDefinition')<cr>", "Type Definition" }, i = { "<cmd>lua require('lvim.lsp.peek').Peek('implementation')<cr>", "Implementation" }, }, - q = { "<cmd>lua vim.diagnostic.setloclist()<cr>", "Quickfix" }, - r = { "<cmd>lua vim.lsp.buf.rename()<cr>", "Rename" }, + q = { vim.diagnostic.setloclist, "Quickfix" }, + r = { vim.lsp.buf.rename, "Rename" }, s = { "<cmd>Telescope lsp_document_symbols<cr>", "Document Symbols" }, S = { "<cmd>Telescope lsp_dynamic_workspace_symbols<cr>", @@ -214,10 +229,10 @@ M.config = function() }, N = { "<cmd>edit $NVIM_LOG_FILE<cr>", "Open the Neovim logfile" }, p = { - "<cmd>lua require('lvim.core.terminal').toggle_log_view('packer.nvim')<cr>", + "<cmd>lua require('lvim.core.terminal').toggle_log_view(get_cache_dir() .. '/packer.nvim.log')<cr>", "view packer log", }, - P = { "<cmd>exe 'edit '.stdpath('cache').'/packer.nvim.log'<cr>", "Open the Packer logfile" }, + P = { "<cmd>edit $LUNARVIM_CACHE_DIR/packer.nvim.log<cr>", "Open the Packer logfile" }, }, r = { "<cmd>LvimReload<cr>", "Reload LunarVim's configuration" }, u = { "<cmd>LvimUpdate<cr>", "Update LunarVim" }, diff --git a/lua/lvim/impatient/profile.lua b/lua/lvim/impatient/profile.lua index 3676c298..0ab04d65 100644 --- a/lua/lvim/impatient/profile.lua +++ b/lua/lvim/impatient/profile.lua @@ -5,6 +5,8 @@ local api, uv = vim.api, vim.loop local std_data = vim.fn.stdpath "data" local std_config = vim.fn.stdpath "config" local vimruntime = os.getenv "VIMRUNTIME" +local lvim_runtime = get_runtime_dir() +local lvim_config = get_config_dir() local function load_buffer(title, lines) local bufnr = api.nvim_create_buf(false, false) @@ -25,6 +27,8 @@ local function mod_path(path) path = path:gsub(std_data .. "/", "<STD_DATA>/") path = path:gsub(std_config .. "/", "<STD_CONFIG>/") path = path:gsub(vimruntime .. "/", "<VIMRUNTIME>/") + path = path:gsub(lvim_runtime .. "/", "<LVIM_RUNTIME>/") + path = path:gsub(lvim_config .. "/", "<LVIM_CONFIG>/") return path end diff --git a/lua/lvim/lsp/config.lua b/lua/lvim/lsp/config.lua index eada4ce7..a0e22107 100644 --- a/lua/lvim/lsp/config.lua +++ b/lua/lvim/lsp/config.lua @@ -94,15 +94,24 @@ return { }, buffer_mappings = { normal_mode = { - ["K"] = { "<cmd>lua vim.lsp.buf.hover()<CR>", "Show hover" }, - ["gd"] = { "<cmd>lua vim.lsp.buf.definition()<CR>", "Goto Definition" }, - ["gD"] = { "<cmd>lua vim.lsp.buf.declaration()<CR>", "Goto declaration" }, - ["gr"] = { "<cmd>lua vim.lsp.buf.references()<CR>", "Goto references" }, - ["gI"] = { "<cmd>lua vim.lsp.buf.implementation()<CR>", "Goto Implementation" }, - ["gs"] = { "<cmd>lua vim.lsp.buf.signature_help()<CR>", "show signature help" }, - ["gp"] = { "<cmd>lua require'lvim.lsp.peek'.Peek('definition')<CR>", "Peek definition" }, + ["K"] = { vim.lsp.buf.hover, "Show hover" }, + ["gd"] = { vim.lsp.buf.definition, "Goto Definition" }, + ["gD"] = { vim.lsp.buf.declaration, "Goto declaration" }, + ["gr"] = { vim.lsp.buf.references, "Goto references" }, + ["gI"] = { vim.lsp.buf.implementation, "Goto Implementation" }, + ["gs"] = { vim.lsp.buf.signature_help, "show signature help" }, + ["gp"] = { + function() + require("lvim.lsp.peek").Peek "definition" + end, + "Peek definition", + }, ["gl"] = { - "<cmd>lua require'lvim.lsp.handlers'.show_line_diagnostics()<CR>", + function() + local config = lvim.lsp.diagnostics.float + config.scope = "line" + vim.diagnostic.open_float(0, config) + end, "Show line diagnostics", }, }, diff --git a/lua/lvim/lsp/handlers.lua b/lua/lvim/lsp/handlers.lua index 5da0b21e..84f2ba5f 100644 --- a/lua/lvim/lsp/handlers.lua +++ b/lua/lvim/lsp/handlers.lua @@ -16,10 +16,4 @@ function M.setup() vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, lvim.lsp.float) end -function M.show_line_diagnostics() - local config = lvim.lsp.diagnostics.float - config.scope = "line" - return vim.diagnostic.open_float(0, config) -end - return M diff --git a/lua/lvim/lsp/init.lua b/lua/lvim/lsp/init.lua index a02ca426..13fafae0 100644 --- a/lua/lvim/lsp/init.lua +++ b/lua/lvim/lsp/init.lua @@ -3,23 +3,6 @@ local Log = require "lvim.core.log" local utils = require "lvim.utils" local autocmds = require "lvim.core.autocmds" -local function lsp_highlight_document(client) - if lvim.lsp.document_highlight == false then - return -- we don't need further - end - autocmds.enable_lsp_document_highlight(client.id) -end - -local function lsp_code_lens_refresh(client) - if lvim.lsp.code_lens_refresh == false then - return - end - - if client.resolved_capabilities.code_lens then - autocmds.enable_code_lens_refresh() - end -end - local function add_lsp_buffer_keybindings(bufnr) local mappings = { normal_mode = "n", @@ -65,28 +48,12 @@ function M.common_capabilities() return capabilities end -local function select_default_formater(client) - if client.name == "null-ls" or not client.resolved_capabilities.document_formatting then - return - end - Log:debug("Checking for formatter overriding for " .. client.name) - local formatters = require "lvim.lsp.null-ls.formatters" - local client_filetypes = client.config.filetypes or {} - for _, filetype in ipairs(client_filetypes) do - if #vim.tbl_keys(formatters.list_registered(filetype)) > 0 then - Log:debug("Formatter overriding detected. Disabling formatting capabilities for " .. client.name) - client.resolved_capabilities.document_formatting = false - client.resolved_capabilities.document_range_formatting = false - end - end -end - function M.common_on_exit(_, _) if lvim.lsp.document_highlight then - autocmds.disable_lsp_document_highlight() + pcall(vim.api.nvim_del_augroup_by_name, "lsp_document_highlight") end if lvim.lsp.code_lens_refresh then - autocmds.disable_code_lens_refresh() + pcall(vim.api.nvim_del_augroup_by_name, "lsp_code_lens_refresh") end end @@ -96,7 +63,6 @@ function M.common_on_init(client, bufnr) Log:debug "Called lsp.on_init_callback" return end - select_default_formater(client) end function M.common_on_attach(client, bufnr) @@ -104,8 +70,13 @@ function M.common_on_attach(client, bufnr) lvim.lsp.on_attach_callback(client, bufnr) Log:debug "Called lsp.on_attach_callback" end - lsp_highlight_document(client) - lsp_code_lens_refresh(client) + local lu = require "lvim.lsp.utils" + if lvim.lsp.document_highlight then + lu.setup_document_highlight(client, bufnr) + end + if lvim.lsp.code_lens_refresh == false then + lu.setup_codelens_refresh(client, bufnr) + end add_lsp_buffer_keybindings(bufnr) end @@ -134,8 +105,10 @@ function M.setup() return end - 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 }) + if lvim.use_icons then + 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 end require("lvim.lsp.handlers").setup() @@ -149,7 +122,7 @@ function M.setup() append_default_schemas = true, } - require("nvim-lsp-installer").settings { + require("nvim-lsp-installer").setup { -- use the default nvim_data_dir, since the server binaries are independent install_root_dir = utils.join_paths(vim.call("stdpath", "data"), "lsp_servers"), } diff --git a/lua/lvim/lsp/manager.lua b/lua/lvim/lsp/manager.lua index 09369d48..2f24298d 100644 --- a/lua/lvim/lsp/manager.lua +++ b/lua/lvim/lsp/manager.lua @@ -16,29 +16,27 @@ function M.init_defaults(languages) end end ----Resolve the configuration for a server based on both common and user configuration ----@param name string ----@param user_config table [optional] +---Resolve the configuration for a server by merging with the default config +---@param server_name string +---@vararg any config table [optional] ---@return table -local function resolve_config(name, user_config) - local config = { +local function resolve_config(server_name, ...) + local defaults = { on_attach = require("lvim.lsp").common_on_attach, on_init = require("lvim.lsp").common_on_init, on_exit = require("lvim.lsp").common_on_exit, capabilities = require("lvim.lsp").common_capabilities(), } - local has_custom_provider, custom_config = pcall(require, "lvim/lsp/providers/" .. name) + local has_custom_provider, custom_config = pcall(require, "lvim/lsp/providers/" .. server_name) if has_custom_provider then - Log:debug("Using custom configuration for requested server: " .. name) - config = vim.tbl_deep_extend("force", config, custom_config) + Log:debug("Using custom configuration for requested server: " .. server_name) + defaults = vim.tbl_deep_extend("force", defaults, custom_config) end - if user_config then - config = vim.tbl_deep_extend("force", config, user_config) - end + defaults = vim.tbl_deep_extend("force", defaults, ...) - return config + return defaults end -- manually start the server and don't wait for the usual filetype trigger from lspconfig @@ -62,47 +60,52 @@ local function client_is_configured(server_name, ft) return false end +local function launch_server(server_name, config) + pcall(function() + require("lspconfig")[server_name].setup(config) + buf_try_add(server_name) + end) +end + ---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 +---@param user_config table? when available it will take predence over any default configurations function M.setup(server_name, user_config) vim.validate { name = { server_name, "string" } } + user_config = user_config or {} if lvim_lsp_utils.is_client_active(server_name) or client_is_configured(server_name) then return end - local config = resolve_config(server_name, user_config) - local servers = require "nvim-lsp-installer.servers" - local server_available, requested_server = servers.get_server(server_name) + local server_available, server = servers.get_server(server_name) if not server_available then - pcall(function() - require("lspconfig")[server_name].setup(config) - buf_try_add(server_name) - end) + local config = resolve_config(server_name, user_config) + launch_server(server_name, config) return end - local install_notification = false + local install_in_progress = false - if not requested_server:is_installed() then + if not server:is_installed() then if lvim.lsp.automatic_servers_installation then Log:debug "Automatic server installation detected" - requested_server:install() - install_notification = true + server:install() + install_in_progress = true else - Log:debug(requested_server.name .. " is not managed by the automatic installer") + Log:debug(server.name .. " is not managed by the automatic installer") end end - requested_server:on_ready(function() - if install_notification then - vim.notify(string.format("Installation complete for [%s] server", requested_server.name), vim.log.levels.INFO) + 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_notification = false - requested_server:setup(config) + install_in_progress = false + local config = resolve_config(server_name, server:get_default_options(), user_config) + launch_server(server_name, config) end) end diff --git a/lua/lvim/lsp/null-ls/init.lua b/lua/lvim/lsp/null-ls/init.lua index 68e20c98..51a200f4 100644 --- a/lua/lvim/lsp/null-ls/init.lua +++ b/lua/lvim/lsp/null-ls/init.lua @@ -2,7 +2,7 @@ local M = {} local Log = require "lvim.core.log" -function M:setup() +function M.setup() local status_ok, null_ls = pcall(require, "null-ls") if not status_ok then Log:error "Missing null-ls dependency" diff --git a/lua/lvim/lsp/templates.lua b/lua/lvim/lsp/templates.lua index 38e68fb6..09f82430 100644 --- a/lua/lvim/lsp/templates.lua +++ b/lua/lvim/lsp/templates.lua @@ -46,7 +46,7 @@ end ---Generates ftplugin files based on a list of server_names ---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 +---@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 {} diff --git a/lua/lvim/lsp/utils.lua b/lua/lvim/lsp/utils.lua index ebc682e5..c976ff72 100644 --- a/lua/lvim/lsp/utils.lua +++ b/lua/lvim/lsp/utils.lua @@ -40,7 +40,7 @@ function M.get_client_capabilities(client_id) end local enabled_caps = {} - for capability, status in pairs(client.resolved_capabilities) do + for capability, status in pairs(client.server_capabilities or client.resolved_capabilities) do if status == true then table.insert(enabled_caps, capability) end @@ -84,14 +84,116 @@ function M.get_all_supported_filetypes() return vim.tbl_keys(lsp_installer_filetypes or {}) end -function M.conditional_document_highlight(id) - local client_ok, method_supported = pcall(function() - return vim.lsp.get_client_by_id(id).resolved_capabilities.document_highlight +function M.setup_document_highlight(client, bufnr) + local status_ok, highlight_supported = pcall(function() + return client.supports_method "textDocument/documentHighlight" end) - if not client_ok or not method_supported then + if not status_ok or not highlight_supported then return end - vim.lsp.buf.document_highlight() + local augroup_exist, _ = pcall(vim.api.nvim_get_autocmds, { + group = "lsp_document_highlight", + }) + if not augroup_exist then + vim.api.nvim_create_augroup("lsp_document_highlight", {}) + end + vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI" }, { + group = "lsp_document_highlight", + buffer = bufnr, + callback = vim.lsp.buf.document_highlight, + }) + vim.api.nvim_create_autocmd("CursorMoved", { + group = "lsp_document_highlight", + buffer = bufnr, + callback = vim.lsp.buf.clear_references, + }) +end + +function M.setup_codelens_refresh(client, bufnr) + local status_ok, codelens_supported = pcall(function() + return client.supports_method "textDocument/codeLens" + end) + if not status_ok or not codelens_supported then + return + end + local augroup_exist, _ = pcall(vim.api.nvim_get_autocmds, { + group = "lsp_code_lens_refresh", + }) + if not augroup_exist then + vim.api.nvim_create_augroup("lsp_code_lens_refresh", {}) + end + vim.api.nvim_create_autocmd("InsertLeave", { + group = "lsp_code_lens_refresh", + buffer = bufnr, + callback = vim.lsp.codelens.refresh, + }) + vim.api.nvim_create_autocmd("InsertLeave", { + group = "lsp_code_lens_refresh", + buffer = bufnr, + callback = vim.lsp.codelens.display, + }) +end + +---filter passed to vim.lsp.buf.format +---gives higher priority to null-ls +---@param clients table clients attached to a buffer +---@return table chosen clients +function M.format_filter(clients) + return vim.tbl_filter(function(client) + local status_ok, formatting_supported = pcall(function() + return client.supports_method "textDocument/formatting" + end) + -- give higher prio to null-ls + if status_ok and formatting_supported and client.name == "null-ls" then + return "null-ls" + else + return status_ok and formatting_supported and client.name + end + end, clients) +end + +---Provide vim.lsp.buf.format for nvim <0.8 +---@param opts table +function M.format(opts) + opts = opts or { filter = M.format_filter } + + if vim.lsp.buf.format then + vim.lsp.buf.format(opts) + end + + local bufnr = opts.bufnr or vim.api.nvim_get_current_buf() + local clients = vim.lsp.buf_get_clients(bufnr) + + if opts.filter then + clients = opts.filter(clients) + elseif opts.id then + clients = vim.tbl_filter(function(client) + return client.id == opts.id + end, clients) + elseif opts.name then + clients = vim.tbl_filter(function(client) + return client.name == opts.name + end, clients) + end + + clients = vim.tbl_filter(function(client) + return client.supports_method "textDocument/formatting" + end, clients) + + if #clients == 0 then + vim.notify "[LSP] Format request failed, no matching language servers." + end + + local timeout_ms = opts.timeout_ms or 1000 + for _, client in pairs(clients) do + local params = vim.lsp.util.make_formatting_params(opts.formatting_options) + local result, err = client.request_sync("textDocument/formatting", params, timeout_ms, bufnr) + if result and result.result then + vim.lsp.util.apply_text_edits(result.result, bufnr, client.offset_encoding) + elseif err then + vim.notify(string.format("[LSP][%s] %s", client.name, err), vim.log.levels.WARN) + end + end end return M diff --git a/lua/lvim/plugin-loader.lua b/lua/lvim/plugin-loader.lua index e42be52e..aa275da2 100644 --- a/lua/lvim/plugin-loader.lua +++ b/lua/lvim/plugin-loader.lua @@ -35,7 +35,7 @@ function plugin_loader.init(opts) init_opts.display = nil end - if vim.fn.empty(vim.fn.glob(install_path)) > 0 then + if not utils.is_directory(install_path) then vim.fn.system { "git", "clone", "--depth", "1", "https://github.com/wbthomason/packer.nvim", install_path } vim.cmd "packadd packer.nvim" -- IMPORTANT: we only set this the very first time to avoid constantly triggering the rollback function @@ -86,7 +86,7 @@ function plugin_loader.reload(configurations) end plugin_loader.load(configurations) - pcall_packer_command "sync" + plugin_loader.ensure_plugins() end function plugin_loader.load(configurations) @@ -140,8 +140,27 @@ function plugin_loader.sync_core_plugins() -- problem: rollback() will get stuck if a plugin directory doesn't exist -- solution: call sync() beforehand -- see https://github.com/wbthomason/packer.nvim/issues/862 - vim.cmd [[autocmd User PackerComplete ++once lua require("lvim.plugin-loader").load_snapshot() ]] + vim.api.nvim_create_autocmd("User", { + pattern = "PackerComplete", + once = true, + callback = function() + require("lvim.plugin-loader").load_snapshot(default_snapshot) + end, + }) pcall_packer_command "sync" end +function plugin_loader.ensure_plugins() + vim.api.nvim_create_autocmd("User", { + pattern = "PackerComplete", + once = true, + callback = function() + Log:debug "calling packer.clean()" + pcall_packer_command "clean" + end, + }) + Log:debug "calling packer.install()" + pcall_packer_command "install" +end + return plugin_loader diff --git a/lua/lvim/plugins.lua b/lua/lvim/plugins.lua index 1b885a09..c39311ed 100644 --- a/lua/lvim/plugins.lua +++ b/lua/lvim/plugins.lua @@ -97,7 +97,8 @@ local core_plugins = { "hrsh7th/cmp-path", }, { - "folke/lua-dev.nvim", + -- NOTE: Temporary fix till folke comes back + "max397574/lua-dev.nvim", module = "lua-dev", }, @@ -147,7 +148,7 @@ local core_plugins = { -- Whichkey { - "folke/which-key.nvim", + "max397574/which-key.nvim", config = function() require("lvim.core.which-key").setup() end, @@ -175,7 +176,10 @@ local core_plugins = { }, -- Icons - { "kyazdani42/nvim-web-devicons" }, + { + "kyazdani42/nvim-web-devicons", + disable = not lvim.use_icons, + }, -- Status Line and Bufferline { diff --git a/lua/lvim/utils/hooks.lua b/lua/lvim/utils/hooks.lua index a6b63c96..f15f6729 100644 --- a/lua/lvim/utils/hooks.lua +++ b/lua/lvim/utils/hooks.lua @@ -13,7 +13,7 @@ end function M.run_on_packer_complete() Log:debug "Packer operation complete" - vim.cmd [[doautocmd User PackerComplete]] + vim.api.nvim_exec_autocmds("User", { pattern = "PackerComplete" }) vim.g.colors_name = lvim.colorscheme pcall(vim.cmd, "colorscheme " .. lvim.colorscheme) diff --git a/snapshots/default.json b/snapshots/default.json index 445a0b53..582b93ca 100644 --- a/snapshots/default.json +++ b/snapshots/default.json @@ -1,6 +1,6 @@ { "Comment.nvim": { - "commit": "8f37791" + "commit": "cb0de89" }, "DAPInstall.nvim": { "commit": "bbda2b0" @@ -9,73 +9,73 @@ "commit": "1bfb32e" }, "LuaSnip": { - "commit": "6b67cb1" + "commit": "1dbafec" }, "alpha-nvim": { - "commit": "6655228" + "commit": "4781fcf" }, "bufferline.nvim": { - "commit": "f02e19b" + "commit": "2d5266d" }, "cmp-buffer": { "commit": "d66c4c2" }, "cmp-nvim-lsp": { - "commit": "ebdfc20" + "commit": "e6b5feb" }, "cmp-path": { "commit": "466b6b8" }, "cmp_luasnip": { - "commit": "b108297" + "commit": "a9de941" }, "friendly-snippets": { - "commit": "5fd8b92" + "commit": "6e0881a" }, "gitsigns.nvim": { - "commit": "f83a2e1" + "commit": "61c8398" }, "lua-dev.nvim": { - "commit": "a0ee777" + "commit": "54149d1" }, "lualine.nvim": { - "commit": "18a07f7" + "commit": "45d07fc" }, "nlsp-settings.nvim": { - "commit": "114e2ff" + "commit": "fc3007e" }, "null-ls.nvim": { - "commit": "a887bd6" + "commit": "3dbded7" }, "nvim-autopairs": { - "commit": "38d486a" + "commit": "63779ea" }, "nvim-cmp": { - "commit": "433af3d" + "commit": "baa8646" }, "nvim-dap": { "commit": "d6d8317" }, "nvim-lsp-installer": { - "commit": "d86aad8" + "commit": "193f171" }, "nvim-lspconfig": { - "commit": "ad9903c" + "commit": "21102d5" }, "nvim-notify": { - "commit": "2c8f744" + "commit": "ebe78be" }, "nvim-tree.lua": { - "commit": "ce463a5" + "commit": "483f155" }, "nvim-treesitter": { - "commit": "bd2f5d7" + "commit": "4067351" }, "nvim-ts-context-commentstring": { "commit": "8834375" }, "nvim-web-devicons": { - "commit": "4febe73" + "commit": "bdd4342" }, "onedarker.nvim": { "commit": "b00dd21" @@ -90,24 +90,24 @@ "commit": "b7404d3" }, "project.nvim": { - "commit": "cef52b8" + "commit": "612443b" }, "schemastore.nvim": { - "commit": "be624ba" + "commit": "57bb4e1" }, "structlog.nvim": { "commit": "6f1403a" }, "telescope-fzf-native.nvim": { - "commit": "8ec164b" + "commit": "281b07a" }, "telescope.nvim": { - "commit": "92019d5" + "commit": "23e28d0" }, "toggleterm.nvim": { - "commit": "dca8f4d" + "commit": "6c7f5db" }, "which-key.nvim": { - "commit": "a3c19ec" + "commit": "03de564" } } diff --git a/tests/minimal_lsp.lua b/tests/minimal_lsp.lua index 660f824b..a610fd7f 100644 --- a/tests/minimal_lsp.lua +++ b/tests/minimal_lsp.lua @@ -87,7 +87,7 @@ _G.load_config = function() server:install() end local default_opts = server:get_default_options() - setup_opts.cmd_env = default_opts.cmd_env + setup_opts = vim.tbl_deep_extend("force", setup_opts, default_opts) end if not name then diff --git a/tests/specs/bootstrap_spec.lua b/tests/specs/bootstrap_spec.lua index 51c3330e..9426a16c 100644 --- a/tests/specs/bootstrap_spec.lua +++ b/tests/specs/bootstrap_spec.lua @@ -12,9 +12,7 @@ a.describe("initial start", function() assert.falsy(package.loaded["lvim.impatient"]) end) - a.it("should be able to use lunarvim directories using vim.fn", function() - assert.equal(lvim_runtime_path, vim.fn.stdpath "data") - assert.equal(lvim_config_path, vim.fn.stdpath "config") + a.it("should be able to use lunarvim cache directory using vim.fn", function() assert.equal(lvim_cache_path, vim.fn.stdpath "cache") end) diff --git a/utils/installer/config.example.lua b/utils/installer/config.example.lua index 61c2f915..562d4060 100644 --- a/utils/installer/config.example.lua +++ b/utils/installer/config.example.lua @@ -12,6 +12,8 @@ an executable lvim.log.level = "warn" lvim.format_on_save = true lvim.colorscheme = "onedarker" +-- to disable icons and use a minimalist setup, uncomment the following +-- lvim.use_icons = false -- keymappings [view all the defaults by pressing <leader>Lk] lvim.leader = "space" diff --git a/utils/installer/config_win.example.lua b/utils/installer/config_win.example.lua index c6bf470e..b659263a 100644 --- a/utils/installer/config_win.example.lua +++ b/utils/installer/config_win.example.lua @@ -29,6 +29,8 @@ vim.g.clipboard = { lvim.log.level = "warn" lvim.format_on_save = true lvim.colorscheme = "onedarker" +-- to disable icons and use a minimalist setup, uncomment the following +-- lvim.use_icons = false -- keymappings [view all the defaults by pressing <leader>Lk] lvim.leader = "space" diff --git a/utils/installer/install-neovim-from-release b/utils/installer/install-neovim-from-release index e98b1aee..08f27149 100755 --- a/utils/installer/install-neovim-from-release +++ b/utils/installer/install-neovim-from-release @@ -23,7 +23,11 @@ else exit 1 fi -declare -r RELEASE_URL="https://github.com/neovim/neovim/releases/$RELEASE_VER/download/$ARCHIVE_NAME.tar.gz" +if [[ "${RELEASE_VER}" == "latest" ]]; then + declare -r RELEASE_URL="https://github.com/neovim/neovim/releases/${RELEASE_VER}/download/${ARCHIVE_NAME}.tar.gz" +else + declare -r RELEASE_URL="https://github.com/neovim/neovim/releases/download/${RELEASE_VER}/${ARCHIVE_NAME}.tar.gz" +fi declare -r CHECKSUM_URL="$RELEASE_URL.sha256sum" DOWNLOAD_DIR="$(mktemp -d)" |