From ba5de3c833c27d084573dfa1099efe953db9f63c Mon Sep 17 00:00:00 2001 From: xeluxee <88047141+xeluxee@users.noreply.github.com> Date: Sat, 9 Oct 2021 22:28:00 +0200 Subject: feat(cmp): make popupmenu formatting options configurable (#1718) --- lua/core/cmp.lua | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'lua') diff --git a/lua/core/cmp.lua b/lua/core/cmp.lua index d5d92314..6250fb48 100644 --- a/lua/core/cmp.lua +++ b/lua/core/cmp.lua @@ -158,23 +158,27 @@ M.config = function() Value = " ", Variable = " ", }, + source_names = { + nvim_lsp = "(LSP)", + emoji = "(Emoji)", + path = "(Path)", + calc = "(Calc)", + cmp_tabnine = "(Tabnine)", + vsnip = "(Snippet)", + luasnip = "(Snippet)", + buffer = "(Buffer)", + }, + duplicates = { + buffer = 1, + path = 1, + nvim_lsp = 0, + }, + duplicates_default = 0, format = function(entry, vim_item) vim_item.kind = lvim.builtin.cmp.formatting.kind_icons[vim_item.kind] - vim_item.menu = ({ - nvim_lsp = "(LSP)", - emoji = "(Emoji)", - path = "(Path)", - calc = "(Calc)", - cmp_tabnine = "(Tabnine)", - vsnip = "(Snippet)", - luasnip = "(Snippet)", - buffer = "(Buffer)", - })[entry.source.name] - vim_item.dup = ({ - buffer = 1, - path = 1, - nvim_lsp = 0, - })[entry.source.name] or 0 + 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 return vim_item end, }, -- cgit v1.2.3 From 596db66c7f452d0f5d44cf245b265b66d55bfbd6 Mon Sep 17 00:00:00 2001 From: Abouzar Parvan Date: Sun, 10 Oct 2021 00:30:03 +0330 Subject: fix: don't hide duplicate snippets --- lua/core/cmp.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'lua') diff --git a/lua/core/cmp.lua b/lua/core/cmp.lua index 6250fb48..ad06a360 100644 --- a/lua/core/cmp.lua +++ b/lua/core/cmp.lua @@ -172,6 +172,7 @@ M.config = function() buffer = 1, path = 1, nvim_lsp = 0, + luasnip = 1, }, duplicates_default = 0, format = function(entry, vim_item) -- cgit v1.2.3 From 65f165011ad9af61b85c1f491d22c217839591b7 Mon Sep 17 00:00:00 2001 From: rebuilt Date: Sun, 10 Oct 2021 09:41:35 +0200 Subject: fix(auto-pairs): disable lazy loading for auto-pairs (#1729) --- lua/plugins.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'lua') diff --git a/lua/plugins.lua b/lua/plugins.lua index d7f47fcb..923ff7c2 100644 --- a/lua/plugins.lua +++ b/lua/plugins.lua @@ -50,7 +50,6 @@ return { { "windwp/nvim-autopairs", -- event = "InsertEnter", - after = "nvim-cmp", config = function() require("core.autopairs").setup() end, -- cgit v1.2.3 From c44550249b85307f668aff0d356c3461856c0e49 Mon Sep 17 00:00:00 2001 From: rebuilt Date: Sun, 10 Oct 2021 09:59:01 +0200 Subject: fix(nvimtree): change 0 and 1 values to true/false (#1728) --- lua/core/nvimtree.lua | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'lua') diff --git a/lua/core/nvimtree.lua b/lua/core/nvimtree.lua index 55cc6175..efed03d1 100644 --- a/lua/core/nvimtree.lua +++ b/lua/core/nvimtree.lua @@ -6,13 +6,13 @@ function M.config() active = true, on_config_done = nil, setup = { - open_on_setup = 0, - auto_close = 1, - open_on_tab = 0, + open_on_setup = false, + auto_close = true, + open_on_tab = false, update_focused_file = { - enable = 1, + enable = true, }, - lsp_diagnostics = 1, + lsp_diagnostics = true, view = { width = 30, side = "left", @@ -23,18 +23,18 @@ function M.config() }, }, show_icons = { - git = 1, - folders = 1, - files = 1, - folder_arrows = 1, + git = true, + folders = true, + files = true, + folder_arrows = true, tree_width = 30, }, ignore = { ".git", "node_modules", ".cache" }, - quit_on_open = 0, - hide_dotfiles = 1, - git_hl = 1, + quit_on_open = false, + hide_dotfiles = true, + git_hl = true, root_folder_modifier = ":t", - allow_resize = 1, + allow_resize = true, auto_ignore_ft = { "startify", "dashboard" }, icons = { default = "", @@ -73,11 +73,11 @@ function M.setup() -- Implicitly update nvim-tree when project module is active if lvim.builtin.project.active then - lvim.builtin.nvimtree.respect_buf_cwd = 1 - lvim.builtin.nvimtree.setup.update_cwd = 1 - lvim.builtin.nvimtree.setup.disable_netrw = 0 - lvim.builtin.nvimtree.setup.hijack_netrw = 0 - vim.g.netrw_banner = 0 + lvim.builtin.nvimtree.respect_buf_cwd = true + lvim.builtin.nvimtree.setup.update_cwd = true + lvim.builtin.nvimtree.setup.disable_netrw = false + lvim.builtin.nvimtree.setup.hijack_netrw = false + vim.g.netrw_banner = false end local tree_cb = nvim_tree_config.nvim_tree_callback -- cgit v1.2.3 From 8c03df505f63c5b326f16e63e06eb86023153868 Mon Sep 17 00:00:00 2001 From: Abouzar Parvan Date: Sun, 10 Oct 2021 14:04:06 +0330 Subject: fix: nvim-tree ls_disagnostics has been replaced with diagnostic (#1731) --- lua/core/nvimtree.lua | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'lua') diff --git a/lua/core/nvimtree.lua b/lua/core/nvimtree.lua index efed03d1..048e25f7 100644 --- a/lua/core/nvimtree.lua +++ b/lua/core/nvimtree.lua @@ -12,7 +12,15 @@ function M.config() update_focused_file = { enable = true, }, - lsp_diagnostics = true, + diagnostics = { + enable = true, + icons = { + hint = "", + info = "", + warning = "", + error = "", + }, + }, view = { width = 30, side = "left", -- cgit v1.2.3 From e2c85df440564a62fd804555747b1652a6844a5e Mon Sep 17 00:00:00 2001 From: Abouzar Parvan Date: Sun, 10 Oct 2021 14:25:38 +0330 Subject: fix: anything not in setup should be set using zero and one (#1733) --- lua/core/nvimtree.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'lua') diff --git a/lua/core/nvimtree.lua b/lua/core/nvimtree.lua index 048e25f7..2d131147 100644 --- a/lua/core/nvimtree.lua +++ b/lua/core/nvimtree.lua @@ -31,18 +31,18 @@ function M.config() }, }, show_icons = { - git = true, - folders = true, - files = true, - folder_arrows = true, + git = 1, + folders = 1, + files = 1, + folder_arrows = 1, tree_width = 30, }, ignore = { ".git", "node_modules", ".cache" }, - quit_on_open = false, - hide_dotfiles = true, - git_hl = true, + quit_on_open = 0, + hide_dotfiles = 1, + git_hl = 1, root_folder_modifier = ":t", - allow_resize = true, + allow_resize = 1, auto_ignore_ft = { "startify", "dashboard" }, icons = { default = "", @@ -81,7 +81,7 @@ function M.setup() -- Implicitly update nvim-tree when project module is active if lvim.builtin.project.active then - lvim.builtin.nvimtree.respect_buf_cwd = true + lvim.builtin.nvimtree.respect_buf_cwd = 1 lvim.builtin.nvimtree.setup.update_cwd = true lvim.builtin.nvimtree.setup.disable_netrw = false lvim.builtin.nvimtree.setup.hijack_netrw = false -- cgit v1.2.3 From 52b74557415eb757ad4b7481b0aec8a3f98dd58d Mon Sep 17 00:00:00 2001 From: kylo252 <59826753+kylo252@users.noreply.github.com> Date: Sun, 10 Oct 2021 21:07:41 +0200 Subject: feat: add an independent lvim namespace (#1699) --- lua/bootstrap.lua | 193 ------------------ lua/config/defaults.lua | 37 ---- lua/config/init.lua | 170 ---------------- lua/config/settings.lua | 76 ------- lua/core/autocmds.lua | 129 ------------ lua/core/autopairs.lua | 81 -------- lua/core/bufferline.lua | 25 --- lua/core/builtins/init.lua | 28 --- lua/core/cmp.lua | 265 ------------------------ lua/core/commands.lua | 25 --- lua/core/comment.lua | 31 --- lua/core/dap.lua | 76 ------- lua/core/dashboard.lua | 112 ---------- lua/core/gitsigns.lua | 64 ------ lua/core/info.lua | 175 ---------------- lua/core/log.lua | 60 ------ lua/core/lualine/colors.lua | 16 -- lua/core/lualine/components.lua | 154 -------------- lua/core/lualine/conditions.lua | 17 -- lua/core/lualine/init.lua | 47 ----- lua/core/lualine/styles.lua | 137 ------------- lua/core/lualine/utils.lua | 27 --- lua/core/nvimtree.lua | 141 ------------- lua/core/project.lua | 51 ----- lua/core/telescope.lua | 194 ------------------ lua/core/terminal.lua | 114 ----------- lua/core/treesitter.lua | 81 -------- lua/core/which-key.lua | 267 ------------------------ lua/impatient.lua | 360 --------------------------------- lua/impatient/profile.lua | 145 ------------- lua/interface/popup.lua | 62 ------ lua/interface/text.lua | 95 --------- lua/keymappings.lua | 180 ----------------- lua/lsp/config.lua | 45 ----- lua/lsp/handlers.lua | 169 ---------------- lua/lsp/init.lua | 165 --------------- lua/lsp/manager.lua | 86 -------- lua/lsp/null-ls/formatters.lua | 66 ------ lua/lsp/null-ls/init.lua | 32 --- lua/lsp/null-ls/linters.lua | 66 ------ lua/lsp/null-ls/services.lua | 63 ------ lua/lsp/peek.lua | 152 -------------- lua/lsp/providers/jsonls.lua | 197 ------------------ lua/lsp/providers/sumneko_lua.lua | 19 -- lua/lsp/providers/vuels.lua | 26 --- lua/lsp/providers/yamlls.lua | 30 --- lua/lsp/templates.lua | 98 --------- lua/lsp/utils.lua | 62 ------ lua/lualine/themes/onedarker.lua | 35 ---- lua/lvim/bootstrap.lua | 196 ++++++++++++++++++ lua/lvim/config/defaults.lua | 32 +++ lua/lvim/config/init.lua | 202 ++++++++++++++++++ lua/lvim/config/settings.lua | 76 +++++++ lua/lvim/core/autocmds.lua | 129 ++++++++++++ lua/lvim/core/autopairs.lua | 81 ++++++++ lua/lvim/core/bufferline.lua | 25 +++ lua/lvim/core/builtins/init.lua | 28 +++ lua/lvim/core/cmp.lua | 265 ++++++++++++++++++++++++ lua/lvim/core/commands.lua | 25 +++ lua/lvim/core/comment.lua | 31 +++ lua/lvim/core/dap.lua | 76 +++++++ lua/lvim/core/dashboard.lua | 112 ++++++++++ lua/lvim/core/gitsigns.lua | 64 ++++++ lua/lvim/core/info.lua | 174 ++++++++++++++++ lua/lvim/core/log.lua | 60 ++++++ lua/lvim/core/lualine/colors.lua | 16 ++ lua/lvim/core/lualine/components.lua | 154 ++++++++++++++ lua/lvim/core/lualine/conditions.lua | 17 ++ lua/lvim/core/lualine/init.lua | 47 +++++ lua/lvim/core/lualine/styles.lua | 137 +++++++++++++ lua/lvim/core/lualine/utils.lua | 27 +++ lua/lvim/core/nvimtree.lua | 141 +++++++++++++ lua/lvim/core/project.lua | 51 +++++ lua/lvim/core/telescope.lua | 193 ++++++++++++++++++ lua/lvim/core/terminal.lua | 114 +++++++++++ lua/lvim/core/treesitter.lua | 81 ++++++++ lua/lvim/core/which-key.lua | 270 +++++++++++++++++++++++++ lua/lvim/impatient.lua | 360 +++++++++++++++++++++++++++++++++ lua/lvim/impatient/profile.lua | 145 +++++++++++++ lua/lvim/interface/popup.lua | 62 ++++++ lua/lvim/interface/text.lua | 95 +++++++++ lua/lvim/keymappings.lua | 180 +++++++++++++++++ lua/lvim/lsp/config.lua | 45 +++++ lua/lvim/lsp/handlers.lua | 169 ++++++++++++++++ lua/lvim/lsp/init.lua | 165 +++++++++++++++ lua/lvim/lsp/manager.lua | 86 ++++++++ lua/lvim/lsp/null-ls/formatters.lua | 66 ++++++ lua/lvim/lsp/null-ls/init.lua | 32 +++ lua/lvim/lsp/null-ls/linters.lua | 66 ++++++ lua/lvim/lsp/null-ls/services.lua | 63 ++++++ lua/lvim/lsp/peek.lua | 152 ++++++++++++++ lua/lvim/lsp/providers/jsonls.lua | 197 ++++++++++++++++++ lua/lvim/lsp/providers/sumneko_lua.lua | 19 ++ lua/lvim/lsp/providers/vuels.lua | 26 +++ lua/lvim/lsp/providers/yamlls.lua | 30 +++ lua/lvim/lsp/templates.lua | 98 +++++++++ lua/lvim/lsp/utils.lua | 62 ++++++ lua/lvim/lualine/themes/onedarker.lua | 35 ++++ lua/lvim/plugin-loader.lua | 63 ++++++ lua/lvim/plugins.lua | 180 +++++++++++++++++ lua/lvim/utils/ft.lua | 47 +++++ lua/lvim/utils/hooks.lua | 35 ++++ lua/lvim/utils/init.lua | 205 +++++++++++++++++++ lua/lvim/utils/table.lua | 24 +++ lua/plugin-loader.lua | 63 ------ lua/plugins.lua | 180 ----------------- lua/utils/ft.lua | 47 ----- lua/utils/hooks.lua | 33 --- lua/utils/init.lua | 237 ---------------------- lua/utils/table.lua | 24 --- 110 files changed, 5531 insertions(+), 5530 deletions(-) delete mode 100644 lua/bootstrap.lua delete mode 100644 lua/config/defaults.lua delete mode 100644 lua/config/init.lua delete mode 100644 lua/config/settings.lua delete mode 100644 lua/core/autocmds.lua delete mode 100644 lua/core/autopairs.lua delete mode 100644 lua/core/bufferline.lua delete mode 100644 lua/core/builtins/init.lua delete mode 100644 lua/core/cmp.lua delete mode 100644 lua/core/commands.lua delete mode 100644 lua/core/comment.lua delete mode 100644 lua/core/dap.lua delete mode 100644 lua/core/dashboard.lua delete mode 100644 lua/core/gitsigns.lua delete mode 100644 lua/core/info.lua delete mode 100644 lua/core/log.lua delete mode 100644 lua/core/lualine/colors.lua delete mode 100644 lua/core/lualine/components.lua delete mode 100644 lua/core/lualine/conditions.lua delete mode 100644 lua/core/lualine/init.lua delete mode 100644 lua/core/lualine/styles.lua delete mode 100644 lua/core/lualine/utils.lua delete mode 100644 lua/core/nvimtree.lua delete mode 100644 lua/core/project.lua delete mode 100644 lua/core/telescope.lua delete mode 100644 lua/core/terminal.lua delete mode 100644 lua/core/treesitter.lua delete mode 100644 lua/core/which-key.lua delete mode 100644 lua/impatient.lua delete mode 100644 lua/impatient/profile.lua delete mode 100644 lua/interface/popup.lua delete mode 100644 lua/interface/text.lua delete mode 100644 lua/keymappings.lua delete mode 100644 lua/lsp/config.lua delete mode 100644 lua/lsp/handlers.lua delete mode 100644 lua/lsp/init.lua delete mode 100644 lua/lsp/manager.lua delete mode 100644 lua/lsp/null-ls/formatters.lua delete mode 100644 lua/lsp/null-ls/init.lua delete mode 100644 lua/lsp/null-ls/linters.lua delete mode 100644 lua/lsp/null-ls/services.lua delete mode 100644 lua/lsp/peek.lua delete mode 100644 lua/lsp/providers/jsonls.lua delete mode 100644 lua/lsp/providers/sumneko_lua.lua delete mode 100644 lua/lsp/providers/vuels.lua delete mode 100644 lua/lsp/providers/yamlls.lua delete mode 100644 lua/lsp/templates.lua delete mode 100644 lua/lsp/utils.lua delete mode 100644 lua/lualine/themes/onedarker.lua create mode 100644 lua/lvim/bootstrap.lua create mode 100644 lua/lvim/config/defaults.lua create mode 100644 lua/lvim/config/init.lua create mode 100644 lua/lvim/config/settings.lua create mode 100644 lua/lvim/core/autocmds.lua create mode 100644 lua/lvim/core/autopairs.lua create mode 100644 lua/lvim/core/bufferline.lua create mode 100644 lua/lvim/core/builtins/init.lua create mode 100644 lua/lvim/core/cmp.lua create mode 100644 lua/lvim/core/commands.lua create mode 100644 lua/lvim/core/comment.lua create mode 100644 lua/lvim/core/dap.lua create mode 100644 lua/lvim/core/dashboard.lua create mode 100644 lua/lvim/core/gitsigns.lua create mode 100644 lua/lvim/core/info.lua create mode 100644 lua/lvim/core/log.lua create mode 100644 lua/lvim/core/lualine/colors.lua create mode 100644 lua/lvim/core/lualine/components.lua create mode 100644 lua/lvim/core/lualine/conditions.lua create mode 100644 lua/lvim/core/lualine/init.lua create mode 100644 lua/lvim/core/lualine/styles.lua create mode 100644 lua/lvim/core/lualine/utils.lua create mode 100644 lua/lvim/core/nvimtree.lua create mode 100644 lua/lvim/core/project.lua create mode 100644 lua/lvim/core/telescope.lua create mode 100644 lua/lvim/core/terminal.lua create mode 100644 lua/lvim/core/treesitter.lua create mode 100644 lua/lvim/core/which-key.lua create mode 100644 lua/lvim/impatient.lua create mode 100644 lua/lvim/impatient/profile.lua create mode 100644 lua/lvim/interface/popup.lua create mode 100644 lua/lvim/interface/text.lua create mode 100644 lua/lvim/keymappings.lua create mode 100644 lua/lvim/lsp/config.lua create mode 100644 lua/lvim/lsp/handlers.lua create mode 100644 lua/lvim/lsp/init.lua create mode 100644 lua/lvim/lsp/manager.lua create mode 100644 lua/lvim/lsp/null-ls/formatters.lua create mode 100644 lua/lvim/lsp/null-ls/init.lua create mode 100644 lua/lvim/lsp/null-ls/linters.lua create mode 100644 lua/lvim/lsp/null-ls/services.lua create mode 100644 lua/lvim/lsp/peek.lua create mode 100644 lua/lvim/lsp/providers/jsonls.lua create mode 100644 lua/lvim/lsp/providers/sumneko_lua.lua create mode 100644 lua/lvim/lsp/providers/vuels.lua create mode 100644 lua/lvim/lsp/providers/yamlls.lua create mode 100644 lua/lvim/lsp/templates.lua create mode 100644 lua/lvim/lsp/utils.lua create mode 100644 lua/lvim/lualine/themes/onedarker.lua create mode 100644 lua/lvim/plugin-loader.lua create mode 100644 lua/lvim/plugins.lua create mode 100644 lua/lvim/utils/ft.lua create mode 100644 lua/lvim/utils/hooks.lua create mode 100644 lua/lvim/utils/init.lua create mode 100644 lua/lvim/utils/table.lua delete mode 100644 lua/plugin-loader.lua delete mode 100644 lua/plugins.lua delete mode 100644 lua/utils/ft.lua delete mode 100644 lua/utils/hooks.lua delete mode 100644 lua/utils/init.lua delete mode 100644 lua/utils/table.lua (limited to 'lua') diff --git a/lua/bootstrap.lua b/lua/bootstrap.lua deleted file mode 100644 index 866403b7..00000000 --- a/lua/bootstrap.lua +++ /dev/null @@ -1,193 +0,0 @@ -local M = {} - -package.loaded["utils.hooks"] = nil -local _, hooks = pcall(require, "utils.hooks") - ----Join path segments that were passed as input ----@return string -function _G.join_paths(...) - local uv = vim.loop - local path_sep = uv.os_uname().version:match "Windows" and "\\" or "/" - local result = table.concat({ ... }, path_sep) - return result -end - ----Get the full path to `$LUNARVIM_RUNTIME_DIR` ----@return string -function _G.get_runtime_dir() - 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 lvim_runtime_dir -end - ----Get the full path to `$LUNARVIM_CONFIG_DIR` ----@return string -function _G.get_config_dir() - local lvim_config_dir = os.getenv "LUNARVIM_CONFIG_DIR" - if not lvim_config_dir then - return vim.fn.stdpath "config" - end - return lvim_config_dir -end - ----Get the full path to `$LUNARVIM_CACHE_DIR` ----@return string -function _G.get_cache_dir() - local lvim_cache_dir = os.getenv "LUNARVIM_CACHE_DIR" - if not lvim_cache_dir then - return vim.fn.stdpath "cache" - end - 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_install_path() .. " describe --tags") - - if string.match(lvim_full_ver, "%d") == nil then - return nil - end - if type == "short" then - return vim.fn.split(lvim_full_ver, "-")[1] - else - return string.sub(lvim_full_ver, 1, #lvim_full_ver - 1) - end -end - ----Initialize the `&runtimepath` variables and prepare for startup ----@return table -function M:init() - self.runtime_dir = get_runtime_dir() - self.config_dir = get_config_dir() - self.cache_path = get_cache_dir() - 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") - self.packer_cache_path = join_paths(self.config_dir, "plugin", "packer_compiled.lua") - - if os.getenv "LUNARVIM_RUNTIME_DIR" then - vim.opt.rtp:remove(join_paths(vim.fn.stdpath "data", "site")) - vim.opt.rtp:remove(join_paths(vim.fn.stdpath "data", "site", "after")) - vim.opt.rtp:prepend(join_paths(self.runtime_dir, "site")) - vim.opt.rtp:append(join_paths(self.runtime_dir, "site", "after")) - - vim.opt.rtp:remove(vim.fn.stdpath "config") - vim.opt.rtp:remove(join_paths(vim.fn.stdpath "config", "after")) - vim.opt.rtp:prepend(self.config_dir) - vim.opt.rtp:append(join_paths(self.config_dir, "after")) - -- TODO: we need something like this: vim.opt.packpath = vim.opt.rtp - - vim.cmd [[let &packpath = &runtimepath]] - vim.cmd("set spellfile=" .. join_paths(self.config_dir, "spell", "en.utf-8.add")) - end - - vim.fn.mkdir(vim.fn.stdpath "cache", "p") - - -- FIXME: currently unreliable in unit-tests - if not os.getenv "LVIM_TEST_ENV" then - require("impatient").setup { - path = vim.fn.stdpath "cache" .. "/lvim_cache", - enable_profiling = true, - } - end - - local config = require "config" - config:init { - path = join_paths(self.config_dir, "config.lua"), - } - - require("plugin-loader"):init { - package_root = self.pack_dir, - install_path = self.packer_install_dir, - } - - return self -end - ----Update LunarVim ----pulls the latest changes from github and, resets the startup cache -function M:update() - hooks.run_pre_update() - M:update_repo() - hooks.run_post_update() -end - -local function git_cmd(subcmd) - local Job = require "plenary.job" - local Log = require "core.log" - local args = { "-C", get_install_path() } - vim.list_extend(args, subcmd) - - local stderr = {} - local stdout, ret = Job - :new({ - command = "git", - args = args, - cwd = get_install_path(), - on_stderr = function(_, data) - table.insert(stderr, data) - end, - }) - :sync() - - if not vim.tbl_isempty(stderr) then - Log:debug(stderr) - end - - if not vim.tbl_isempty(stdout) then - Log:debug(stdout) - end - - return ret -end - ----pulls the latest changes from github -function M:update_repo() - local Log = require "core.log" - local sub_commands = { - fetch = { "fetch" }, - diff = { "diff", "--quiet", "@{upstream}" }, - merge = { "merge", "--ff-only", "--progress" }, - } - Log:info "Checking for updates" - - local ret = git_cmd(sub_commands.fetch) - if ret ~= 0 then - Log:error "Update failed! Check the log for further information" - return - end - - ret = git_cmd(sub_commands.diff) - - if ret == 0 then - Log:info "LunarVim is already up-to-date" - return - end - - ret = git_cmd(sub_commands.merge) - - if ret ~= 0 then - Log:error "Update failed! Please pull the changes manually instead." - return - end -end - -return M diff --git a/lua/config/defaults.lua b/lua/config/defaults.lua deleted file mode 100644 index f030234d..00000000 --- a/lua/config/defaults.lua +++ /dev/null @@ -1,37 +0,0 @@ -local home_dir = vim.loop.os_homedir() -local utils = require "utils" - -lvim = { - leader = "space", - colorscheme = "onedarker", - line_wrap_cursor_movement = true, - transparent_window = false, - format_on_save = true, - vsnip_dir = utils.join_paths(home_dir, ".config", "snippets"), - database = { save_location = utils.join_paths(home_dir, ".config", "lunarvim_db"), auto_execute = 1 }, - keys = {}, - - builtin = {}, - - log = { - ---@usage can be { "trace", "debug", "info", "warn", "error", "fatal" }, - level = "warn", - viewer = { - ---@usage this will fallback on "less +F" if not found - cmd = "lnav", - layout_config = { - ---@usage direction = 'vertical' | 'horizontal' | 'window' | 'float', - direction = "horizontal", - open_mapping = "", - size = 40, - float_opts = {}, - }, - }, - }, - plugins = { - -- use config.lua for this not put here - }, - - autocommands = {}, - lang = {}, -} diff --git a/lua/config/init.lua b/lua/config/init.lua deleted file mode 100644 index 411f7a93..00000000 --- a/lua/config/init.lua +++ /dev/null @@ -1,170 +0,0 @@ -local M = {} - ---- Initialize lvim default configuration --- Define lvim global variable -function M:init(opts) - opts = opts or {} - self.path = opts.path - local utils = require "utils" - - require "config.defaults" - - -- Fallback config.lua to lv-config.lua - if not utils.is_file(self.path) then - local lv_config = self.path:gsub("config.lua$", "lv-config.lua") - print(self.path, "not found, falling back to", lv_config) - - self.path = lv_config - end - - local builtins = require "core.builtins" - builtins.config(self) - - local settings = require "config.settings" - settings.load_options() - - local lvim_lsp_config = require "lsp.config" - lvim.lsp = vim.deepcopy(lvim_lsp_config) - - local supported_languages = { - "asm", - "bash", - "beancount", - "bibtex", - "bicep", - "c", - "c_sharp", - "clojure", - "cmake", - "comment", - "commonlisp", - "cpp", - "crystal", - "cs", - "css", - "cuda", - "d", - "dart", - "dockerfile", - "dot", - "elixir", - "elm", - "emmet", - "erlang", - "fennel", - "fish", - "fortran", - "gdscript", - "glimmer", - "go", - "gomod", - "graphql", - "haskell", - "hcl", - "heex", - "html", - "java", - "javascript", - "javascriptreact", - "jsdoc", - "json", - "json5", - "jsonc", - "julia", - "kotlin", - "latex", - "ledger", - "less", - "lua", - "markdown", - "nginx", - "nix", - "ocaml", - "ocaml_interface", - "perl", - "php", - "pioasm", - "ps1", - "puppet", - "python", - "ql", - "query", - "r", - "regex", - "rst", - "ruby", - "rust", - "scala", - "scss", - "sh", - "solidity", - "sparql", - "sql", - "supercollider", - "surface", - "svelte", - "swift", - "tailwindcss", - "terraform", - "tex", - "tlaplus", - "toml", - "tsx", - "turtle", - "typescript", - "typescriptreact", - "verilog", - "vim", - "vue", - "yaml", - "yang", - "zig", - } - - require("lsp.manager").init_defaults(supported_languages) -end - -local function deprecation_notice() - local in_headless = #vim.api.nvim_list_uis() == 0 - if in_headless then - return - end - - for lang, entry in pairs(lvim.lang) do - local deprecated_config = entry["lsp"] or {} - if not vim.tbl_isempty(deprecated_config) then - local msg = string.format( - "Deprecation notice: [lvim.lang.%s.lsp] setting is no longer supported. See https://github.com/LunarVim/LunarVim#breaking-changes", - lang - ) - vim.schedule(function() - vim.notify(msg, vim.log.levels.WARN) - end) - end - end -end - ---- Override the configuration with a user provided one --- @param config_path The path to the configuration overrides -function M:load(config_path) - local autocmds = require "core.autocmds" - - config_path = config_path or self.path - local ok, err = pcall(vim.cmd, "luafile " .. config_path) - if not ok then - print("Invalid configuration", config_path) - print(err) - return - end - - deprecation_notice() - - self.path = config_path - - autocmds.define_augroups(lvim.autocommands) - - local settings = require "config.settings" - settings.load_commands() -end - -return M diff --git a/lua/config/settings.lua b/lua/config/settings.lua deleted file mode 100644 index 90042c4f..00000000 --- a/lua/config/settings.lua +++ /dev/null @@ -1,76 +0,0 @@ -local M = {} -local utils = require "utils" -M.load_options = function() - local default_options = { - backup = false, -- creates a backup file - clipboard = "unnamedplus", -- allows neovim to access the system clipboard - cmdheight = 2, -- more space in the neovim command line for displaying messages - colorcolumn = "99999", -- fixes indentline for now - completeopt = { "menuone", "noselect" }, - conceallevel = 0, -- so that `` is visible in markdown files - fileencoding = "utf-8", -- the encoding written to a file - foldmethod = "manual", -- folding, set to "expr" for treesitter based folding - foldexpr = "", -- set to "nvim_treesitter#foldexpr()" for treesitter based folding - guifont = "monospace:h17", -- the font used in graphical neovim applications - hidden = true, -- required to keep multiple buffers and open multiple buffers - hlsearch = true, -- highlight all matches on previous search pattern - ignorecase = true, -- ignore case in search patterns - mouse = "a", -- allow the mouse to be used in neovim - pumheight = 10, -- pop up menu height - showmode = false, -- we don't need to see things like -- INSERT -- anymore - showtabline = 2, -- always show tabs - smartcase = true, -- smart case - smartindent = true, -- make indenting smarter again - splitbelow = true, -- force all horizontal splits to go below current window - splitright = true, -- force all vertical splits to go to the right of current window - swapfile = false, -- creates a swapfile - termguicolors = true, -- set term gui colors (most terminals support this) - timeoutlen = 100, -- time to wait for a mapped sequence to complete (in milliseconds) - title = true, -- set the title of window to the value of the titlestring - -- opt.titlestring = "%<%F%=%l/%L - nvim" -- what the title of the window will be set to - undodir = utils.join_paths(get_cache_dir(), "undo"), -- set an undo directory - undofile = true, -- enable persistent undo - updatetime = 300, -- faster completion - writebackup = false, -- if a file is being edited by another program (or was written to file while editing with another program), it is not allowed to be edited - expandtab = true, -- convert tabs to spaces - shiftwidth = 2, -- the number of spaces inserted for each indentation - tabstop = 2, -- insert 2 spaces for a tab - cursorline = true, -- highlight the current line - number = true, -- set numbered lines - relativenumber = false, -- set relative numbered lines - numberwidth = 4, -- set number column width to 2 {default 4} - signcolumn = "yes", -- always show the sign column, otherwise it would shift the text each time - wrap = false, -- display lines as one long line - spell = false, - spelllang = "en", - scrolloff = 8, -- is one of my fav - sidescrolloff = 8, - } - - --- SETTINGS --- - - vim.opt.shortmess:append "c" - - for k, v in pairs(default_options) do - vim.opt[k] = v - end -end - -M.load_commands = function() - local cmd = vim.cmd - if lvim.line_wrap_cursor_movement then - cmd "set whichwrap+=<,>,[,],h,l" - end - - if lvim.transparent_window then - cmd "au ColorScheme * hi Normal ctermbg=none guibg=none" - cmd "au ColorScheme * hi SignColumn ctermbg=none guibg=none" - cmd "au ColorScheme * hi NormalNC ctermbg=none guibg=none" - cmd "au ColorScheme * hi MsgArea ctermbg=none guibg=none" - cmd "au ColorScheme * hi TelescopeBorder ctermbg=none guibg=none" - cmd "au ColorScheme * hi NvimTreeNormal ctermbg=none guibg=none" - cmd "let &fcs='eob: '" - end -end - -return M diff --git a/lua/core/autocmds.lua b/lua/core/autocmds.lua deleted file mode 100644 index 662afcfa..00000000 --- a/lua/core/autocmds.lua +++ /dev/null @@ -1,129 +0,0 @@ -local autocommands = {} -local config = require "config" - -lvim.autocommands = { - _general_settings = { - { - "Filetype", - "*", - "lua require('utils.ft').do_filetype(vim.fn.expand(\"\"))", - }, - { - "FileType", - "qf", - "nnoremap q :q", - }, - { - "FileType", - "lsp-installer", - "nnoremap q :q", - }, - { - "TextYankPost", - "*", - "lua require('vim.highlight').on_yank({higroup = 'Search', timeout = 200})", - }, - { - "BufWinEnter", - "*", - "setlocal formatoptions-=c formatoptions-=r formatoptions-=o", - }, - { - "BufWinEnter", - "dashboard", - "setlocal cursorline signcolumn=yes cursorcolumn number", - }, - { - "BufRead", - "*", - "setlocal formatoptions-=c formatoptions-=r formatoptions-=o", - }, - { - "BufNewFile", - "*", - "setlocal formatoptions-=c formatoptions-=r formatoptions-=o", - }, - { "BufWritePost", config.path, "lua require('utils').reload_lv_config()" }, - { - "FileType", - "qf", - "set nobuflisted", - }, - -- { "VimLeavePre", "*", "set title set titleold=" }, - }, - _filetypechanges = { - { "BufWinEnter", ".tf", "setlocal filetype=terraform" }, - { "BufRead", "*.tf", "setlocal filetype=terraform" }, - { "BufNewFile", "*.tf", "setlocal filetype=terraform" }, - { "BufWinEnter", ".zsh", "setlocal filetype=sh" }, - { "BufRead", "*.zsh", "setlocal filetype=sh" }, - { "BufNewFile", "*.zsh", "setlocal filetype=sh" }, - }, - -- _solidity = { - -- {'BufWinEnter', '.sol', 'setlocal filetype=solidity'}, {'BufRead', '*.sol', 'setlocal filetype=solidity'}, - -- {'BufNewFile', '*.sol', 'setlocal filetype=solidity'} - -- }, - -- _gemini = { - -- {'BufWinEnter', '.gmi', 'setlocal filetype=markdown'}, {'BufRead', '*.gmi', 'setlocal filetype=markdown'}, - -- {'BufNewFile', '*.gmi', 'setlocal filetype=markdown'} - -- }, - _git = { - { "FileType", "gitcommit", "setlocal wrap" }, - { "FileType", "gitcommit", "setlocal spell" }, - }, - _markdown = { - { "FileType", "markdown", "setlocal wrap" }, - { "FileType", "markdown", "setlocal spell" }, - }, - _buffer_bindings = { - { "FileType", "floaterm", "nnoremap q :q" }, - }, - _auto_resize = { - -- will cause split windows to be resized evenly if main window is resized - { "VimResized", "*", "wincmd =" }, - }, - _packer_compile = { - -- will run PackerCompile after writing plugins.lua - { "BufWritePost", "plugins.lua", "PackerCompile" }, - }, - _general_lsp = { - { "FileType", "lspinfo", "nnoremap q :q" }, - }, - - -- _fterm_lazygit = { - -- -- will cause esc key to exit lazy git - -- {"TermEnter", "*", "call LazyGitNativation()"} - -- }, - -- _mode_switching = { - -- -- will switch between absolute and relative line numbers depending on mode - -- {'InsertEnter', '*', 'if &relativenumber | let g:ms_relativenumberoff = 1 | setlocal number norelativenumber | endif'}, - -- {'InsertLeave', '*', 'if exists("g:ms_relativenumberoff") | setlocal relativenumber | endif'}, - -- {'InsertEnter', '*', 'if &cursorline | let g:ms_cursorlineoff = 1 | setlocal nocursorline | endif'}, - -- {'InsertLeave', '*', 'if exists("g:ms_cursorlineoff") | setlocal cursorline | endif'}, - -- }, - custom_groups = {}, -} - -function autocommands.define_augroups(definitions) -- {{{1 - -- Create autocommand groups based on the passed definitions - -- - -- The key will be the name of the group, and each definition - -- within the group should have: - -- 1. Trigger - -- 2. Pattern - -- 3. Text - -- just like how they would normally be defined from Vim itself - for group_name, definition in pairs(definitions) do - vim.cmd("augroup " .. group_name) - vim.cmd "autocmd!" - - for _, def in pairs(definition) do - local command = table.concat(vim.tbl_flatten { "autocmd", def }, " ") - vim.cmd(command) - end - - vim.cmd "augroup END" - end -end - -return autocommands diff --git a/lua/core/autopairs.lua b/lua/core/autopairs.lua deleted file mode 100644 index eb080fb1..00000000 --- a/lua/core/autopairs.lua +++ /dev/null @@ -1,81 +0,0 @@ -local M = {} - -function M.config() - lvim.builtin.autopairs = { - active = true, - on_config_done = nil, - ---@usage auto insert after select function or method item - map_complete = true, - ---@usage -- modifies the function or method delimiter by filetypes - map_char = { - all = "(", - tex = "{", - }, - ---@usage check treesitter - check_ts = true, - ts_config = { - lua = { "string" }, - javascript = { "template_string" }, - java = false, - }, - } -end - -M.setup = function() - local autopairs = require "nvim-autopairs" - local Rule = require "nvim-autopairs.rule" - local cond = require "nvim-autopairs.conds" - - autopairs.setup { - check_ts = lvim.builtin.autopairs.check_ts, - ts_config = lvim.builtin.autopairs.ts_config, - } - - -- vim.g.completion_confirm_key = "" - - autopairs.add_rule(Rule("$$", "$$", "tex")) - autopairs.add_rules { - Rule("$", "$", { "tex", "latex" }) -- don't add a pair if the next character is % - :with_pair(cond.not_after_regex_check "%%") -- don't add a pair if the previous character is xxx - :with_pair(cond.not_before_regex_check("xxx", 3)) -- don't move right when repeat character - :with_move(cond.none()) -- don't delete if the next character is xx - :with_del(cond.not_after_regex_check "xx") -- disable add newline when press - :with_cr(cond.none()), - } - autopairs.add_rules { - Rule("$$", "$$", "tex"):with_pair(function(opts) - print(vim.inspect(opts)) - if opts.line == "aa $$" then - -- don't add pair on that line - return false - end - end), - } - - if package.loaded["cmp"] then - require("nvim-autopairs.completion.cmp").setup { - map_cr = false, - map_complete = lvim.builtin.autopairs.map_complete, - map_char = lvim.builtin.autopairs.map_char, - } - -- we map CR explicitly in cmp.lua but we still need to setup the autopairs CR keymap - vim.api.nvim_set_keymap("i", "", "v:lua.MPairs.autopairs_cr()", { expr = true, noremap = true }) - end - - require("nvim-treesitter.configs").setup { autopairs = { enable = true } } - - local ts_conds = require "nvim-autopairs.ts-conds" - - -- TODO: can these rules be safely added from "config.lua" ? - -- press % => %% is only inside comment or string - autopairs.add_rules { - Rule("%", "%", "lua"):with_pair(ts_conds.is_ts_node { "string", "comment" }), - Rule("$", "$", "lua"):with_pair(ts_conds.is_not_ts_node { "function" }), - } - - if lvim.builtin.autopairs.on_config_done then - lvim.builtin.autopairs.on_config_done(autopairs) - end -end - -return M diff --git a/lua/core/bufferline.lua b/lua/core/bufferline.lua deleted file mode 100644 index e3f6b5de..00000000 --- a/lua/core/bufferline.lua +++ /dev/null @@ -1,25 +0,0 @@ -local M = {} - -M.config = function() - lvim.builtin.bufferline = { - active = true, - on_config_done = nil, - keymap = { - normal_mode = { - [""] = ":BufferNext", - [""] = ":BufferPrevious", - }, - }, - } -end - -M.setup = function() - local keymap = require "keymappings" - keymap.append_to_defaults(lvim.builtin.bufferline.keymap) - - if lvim.builtin.bufferline.on_config_done then - lvim.builtin.bufferline.on_config_done() - end -end - -return M diff --git a/lua/core/builtins/init.lua b/lua/core/builtins/init.lua deleted file mode 100644 index c3b3618f..00000000 --- a/lua/core/builtins/init.lua +++ /dev/null @@ -1,28 +0,0 @@ -local M = {} - -local builtins = { - "keymappings", - "core.which-key", - "core.gitsigns", - "core.cmp", - "core.dashboard", - "core.dap", - "core.terminal", - "core.telescope", - "core.treesitter", - "core.nvimtree", - "core.project", - "core.bufferline", - "core.autopairs", - "core.comment", - "core.lualine", -} - -function M.config(config) - for _, builtin_path in ipairs(builtins) do - local builtin = require(builtin_path) - builtin.config(config) - end -end - -return M diff --git a/lua/core/cmp.lua b/lua/core/cmp.lua deleted file mode 100644 index ad06a360..00000000 --- a/lua/core/cmp.lua +++ /dev/null @@ -1,265 +0,0 @@ -local M = {} - -local check_backspace = function() - local col = vim.fn.col "." - 1 - return col == 0 or vim.fn.getline("."):sub(col, col):match "%s" -end - -local function T(str) - return vim.api.nvim_replace_termcodes(str, true, true, true) -end - -local is_emmet_active = function() - local clients = vim.lsp.buf_get_clients() - - for _, client in pairs(clients) do - if client.name == "emmet_ls" then - return true - end - end - return false -end - -M.config = function() - local status_cmp_ok, cmp = pcall(require, "cmp") - if not status_cmp_ok then - return - end - local status_luasnip_ok, luasnip = pcall(require, "luasnip") - if not status_luasnip_ok then - return - 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() - -- 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 - end - - local snippet = node.parent.snippet - local exit_node = snippet.insert_nodes[0] - - -- exit early if we're past the exit node - if exit_node then - local exit_pos_end = exit_node.mark:pos_end() - if (pos[1] > exit_pos_end[1]) or (pos[1] == exit_pos_end[1] and pos[2] > exit_pos_end[2]) then - snippet:remove_from_jumplist() - luasnip.session.current_nodes[get_current_buf()] = nil - - return false - end - end - - node = snippet.inner_first:jump_into(1, true) - while node ~= nil and node.next ~= nil and node ~= snippet do - local n_next = node.next - local next_pos = n_next and n_next.mark:pos_begin() - local candidate = n_next ~= snippet and next_pos and (pos[1] < next_pos[1]) - or (pos[1] == next_pos[1] and pos[2] < next_pos[2]) - - -- Past unmarked exit node, exit early - if n_next == nil or n_next == snippet.next then - snippet:remove_from_jumplist() - luasnip.session.current_nodes[get_current_buf()] = nil - - return false - end - - if candidate then - luasnip.session.current_nodes[get_current_buf()] = node - return true - end - - local ok - ok, node = pcall(node.jump_from, node, 1, true) -- no_move until last stop - if not ok then - snippet:remove_from_jumplist() - luasnip.session.current_nodes[get_current_buf()] = nil - - return false - end - end - - -- No candidate, but have an exit node - if exit_node then - -- to jump to the exit node, seek to snippet - luasnip.session.current_nodes[get_current_buf()] = snippet - return true - end - - -- No exit node, exit from snippet - snippet:remove_from_jumplist() - luasnip.session.current_nodes[get_current_buf()] = nil - return false - end - - lvim.builtin.cmp = { - confirm_opts = { - behavior = cmp.ConfirmBehavior.Replace, - select = false, - }, - experimental = { - ghost_text = true, - native_menu = false, - }, - formatting = { - kind_icons = { - Class = " ", - Color = " ", - Constant = "ﲀ ", - Constructor = " ", - Enum = "練", - EnumMember = " ", - Event = " ", - Field = " ", - File = "", - Folder = " ", - Function = " ", - Interface = "ﰮ ", - Keyword = " ", - Method = " ", - Module = " ", - Operator = "", - Property = " ", - Reference = " ", - Snippet = " ", - Struct = " ", - Text = " ", - TypeParameter = " ", - Unit = "塞", - Value = " ", - Variable = " ", - }, - source_names = { - nvim_lsp = "(LSP)", - emoji = "(Emoji)", - path = "(Path)", - calc = "(Calc)", - cmp_tabnine = "(Tabnine)", - vsnip = "(Snippet)", - luasnip = "(Snippet)", - buffer = "(Buffer)", - }, - duplicates = { - buffer = 1, - path = 1, - nvim_lsp = 0, - luasnip = 1, - }, - duplicates_default = 0, - format = function(entry, vim_item) - vim_item.kind = lvim.builtin.cmp.formatting.kind_icons[vim_item.kind] - 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 - return vim_item - end, - }, - snippet = { - expand = function(args) - require("luasnip").lsp_expand(args.body) - end, - }, - documentation = { - border = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, - }, - sources = { - { name = "nvim_lsp" }, - { name = "path" }, - { name = "luasnip" }, - { name = "cmp_tabnine" }, - { name = "nvim_lua" }, - { name = "buffer" }, - { name = "calc" }, - { name = "emoji" }, - { name = "treesitter" }, - { name = "crates" }, - }, - mapping = { - [""] = cmp.mapping.scroll_docs(-4), - [""] = cmp.mapping.scroll_docs(4), - -- TODO: potentially fix emmet nonsense - [""] = cmp.mapping(function() - if cmp.visible() then - cmp.select_next_item() - elseif luasnip.expandable() then - luasnip.expand() - elseif inside_snippet() and seek_luasnip_cursor_node() and luasnip.jumpable() then - luasnip.jump(1) - elseif check_backspace() then - vim.fn.feedkeys(T "", "n") - elseif is_emmet_active() then - return vim.fn["cmp#complete"]() - else - vim.fn.feedkeys(T "", "n") - end - end, { - "i", - "s", - }), - [""] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_prev_item() - elseif inside_snippet() and luasnip.jumpable(-1) then - luasnip.jump(-1) - else - fallback() - end - end, { - "i", - "s", - }), - - [""] = cmp.mapping.complete(), - [""] = cmp.mapping.close(), - [""] = cmp.mapping(function(fallback) - if cmp.visible() and cmp.confirm(lvim.builtin.cmp.confirm_opts) then - return - end - - if inside_snippet() and seek_luasnip_cursor_node() and luasnip.jumpable() then - if not luasnip.jump(1) then - fallback() - end - else - fallback() - end - end), - }, - } -end - -M.setup = function() - require("luasnip/loaders/from_vscode").lazy_load() - require("cmp").setup(lvim.builtin.cmp) -end - -return M diff --git a/lua/core/commands.lua b/lua/core/commands.lua deleted file mode 100644 index 6ceeaaff..00000000 --- a/lua/core/commands.lua +++ /dev/null @@ -1,25 +0,0 @@ -local M = {} - -M.defaults = { - [[ - function! QuickFixToggle() - if empty(filter(getwininfo(), 'v:val.quickfix')) - copen - else - cclose - endif - endfunction - ]], - -- :LvimInfo - [[ 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() ]], -} - -M.load = function(commands) - for _, command in ipairs(commands) do - vim.cmd(command) - end -end - -return M diff --git a/lua/core/comment.lua b/lua/core/comment.lua deleted file mode 100644 index b98410ab..00000000 --- a/lua/core/comment.lua +++ /dev/null @@ -1,31 +0,0 @@ -local M = {} - -function M.config() - lvim.builtin.comment = { - active = true, - on_config_done = nil, - -- Linters prefer comment and line to have a space in between markers - marker_padding = true, - -- should comment out empty or whitespace only lines - comment_empty = false, - -- Should key mappings be created - create_mappings = true, - -- Normal mode mapping left hand side - line_mapping = "gcc", - -- Visual/Operator mapping left hand side - operator_mapping = "gc", - -- Hook function to call before commenting takes place - hook = nil, - } -end - -function M.setup() - local nvim_comment = require "nvim_comment" - - nvim_comment.setup(lvim.builtin.comment) - if lvim.builtin.comment.on_config_done then - lvim.builtin.comment.on_config_done(nvim_comment) - end -end - -return M diff --git a/lua/core/dap.lua b/lua/core/dap.lua deleted file mode 100644 index d9b59641..00000000 --- a/lua/core/dap.lua +++ /dev/null @@ -1,76 +0,0 @@ -local M = {} - -M.config = function() - lvim.builtin.dap = { - active = false, - on_config_done = nil, - breakpoint = { - text = "", - texthl = "LspDiagnosticsSignError", - linehl = "", - numhl = "", - }, - breakpoint_rejected = { - text = "", - texthl = "LspDiagnosticsSignHint", - linehl = "", - numhl = "", - }, - stopped = { - text = "", - texthl = "LspDiagnosticsSignInformation", - linehl = "DiagnosticUnderlineInfo", - numhl = "LspDiagnosticsSignInformation", - }, - } -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) - - dap.defaults.fallback.terminal_win_cmd = "50vsplit new" - - lvim.builtin.which_key.mappings["d"] = { - name = "Debug", - t = { "lua require'dap'.toggle_breakpoint()", "Toggle Breakpoint" }, - b = { "lua require'dap'.step_back()", "Step Back" }, - c = { "lua require'dap'.continue()", "Continue" }, - C = { "lua require'dap'.run_to_cursor()", "Run To Cursor" }, - d = { "lua require'dap'.disconnect()", "Disconnect" }, - g = { "lua require'dap'.session()", "Get Session" }, - i = { "lua require'dap'.step_into()", "Step Into" }, - o = { "lua require'dap'.step_over()", "Step Over" }, - u = { "lua require'dap'.step_out()", "Step Out" }, - p = { "lua require'dap'.pause.toggle()", "Pause" }, - r = { "lua require'dap'.repl.toggle()", "Toggle Repl" }, - s = { "lua require'dap'.continue()", "Start" }, - q = { "lua require'dap'.close()", "Quit" }, - } - - if lvim.builtin.dap.on_config_done then - lvim.builtin.dap.on_config_done(dap) - end -end - --- TODO put this up there ^^^ call in ftplugin - --- M.dap = function() --- if lvim.plugin.dap.active then --- local dap_install = require "dap-install" --- dap_install.config("python_dbg", {}) --- end --- end --- --- M.dap = function() --- -- gem install readapt ruby-debug-ide --- if lvim.plugin.dap.active then --- local dap_install = require "dap-install" --- dap_install.config("ruby_vsc_dbg", {}) --- end --- end - -return M diff --git a/lua/core/dashboard.lua b/lua/core/dashboard.lua deleted file mode 100644 index 505350cb..00000000 --- a/lua/core/dashboard.lua +++ /dev/null @@ -1,112 +0,0 @@ -local M = {} -local utils = require "utils" - -M.config = function(config) - lvim.builtin.dashboard = { - active = false, - on_config_done = nil, - search_handler = "telescope", - disable_at_vim_enter = 0, - session_directory = utils.join_paths(get_cache_dir(), "sessions"), - custom_header = { - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⣶⣾⠿⠿⠟⠛⠛⠛⠛⠿⠿⣿⣷⣤⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - " ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣾⡿⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠿⣷⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣤⡿⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⢿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠒⠂⠉⠉⠉⠉⢩⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠸⡀⠀⠀⠀⠀⠀⢰⣿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⠠⡀⠀⠀⢀⣾⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢⢀⣸⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡧⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡇⠀⠈⠁⠒⠤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣇⠀⠀⠀⠀⠀⠀⠉⠢⠤⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⡟⠈⠑⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠑⠒⠤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⡇⠀⠀⢀⣣⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠀⠀⠒⠢⠤⠄⣀⣀⠀⠀⠀⢠⣿⡟⠀⠀⠀⣺⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⣿⠇⠀⠀⠀⠀⠀⣤⡄⠀⠀⢠⣤⡄⠀⢨⣭⣠⣤⣤⣤⡀⠀⠀⢀⣤⣤⣤⣤⡄⠀⠀⠀⣤⣄⣤⣤⣤⠀⠀⣿⣯⠉⠉⣿⡟⠀⠈⢩⣭⣤⣤⠀⠀⠀⠀⣠⣤⣤⣤⣄⣤⣤", - "⢠⣿⠀⠀⠀⠀⠀⠀⣿⠃⠀⠀⣸⣿⠁⠀⣿⣿⠉⠀⠈⣿⡇⠀⠀⠛⠋⠀⠀⢹⣿⠀⠀⠀⣿⠏⠀⠸⠿⠃⠀⣿⣿⠀⣰⡟⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⣿⡟⢸⣿⡇⢀⣿", - "⣸⡇⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⣿⡟⠀⢠⣿⡇⠀⠀⢰⣿⡇⠀⣰⣾⠟⠛⠛⣻⡇⠀⠀⢸⡿⠀⠀⠀⠀⠀⠀⢻⣿⢰⣿⠀⠀⠀⠀⠀⠀⣾⡇⠀⠀⠀⢸⣿⠇⢸⣿⠀⢸⡏", - "⣿⣧⣤⣤⣤⡄⠀⠘⣿⣤⣤⡤⣿⠇⠀⢸⣿⠁⠀⠀⣼⣿⠀⠀⢿⣿⣤⣤⠔⣿⠃⠀⠀⣾⡇⠀⠀⠀⠀⠀⠀⢸⣿⣿⠋⠀⠀⠀⢠⣤⣤⣿⣥⣤⡄⠀⣼⣿⠀⣸⡏⠀⣿⠃", - "⠉⠉⠉⠉⠉⠁⠀⠀⠈⠉⠉⠀⠉⠀⠀⠈⠉⠀⠀⠀⠉⠉⠀⠀⠀⠉⠉⠁⠈⠉⠀⠀⠀⠉⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠀⠀⠀⠀⠈⠉⠉⠉⠉⠉⠁⠀⠉⠁⠀⠉⠁⠀⠉⠀", - }, - - custom_section = { - a = { - description = { " Find File " }, - command = "Telescope find_files", - }, - b = { - description = { " Recent Projects " }, - command = "Telescope projects", - }, - c = { - description = { " Recently Used Files" }, - command = "Telescope oldfiles", - }, - d = { - description = { " Find Word " }, - command = "Telescope live_grep", - }, - e = { - description = { " Configuration " }, - command = ":e " .. config.path, - }, - }, - - footer = { "lunarvim.org" }, - } -end - -M.setup = function() - vim.g.dashboard_disable_at_vimenter = lvim.builtin.dashboard.disable_at_vim_enter - - vim.g.dashboard_custom_header = lvim.builtin.dashboard.custom_header - - vim.g.dashboard_default_executive = lvim.builtin.dashboard.search_handler - - vim.g.dashboard_custom_section = lvim.builtin.dashboard.custom_section - - lvim.builtin.which_key.mappings[";"] = { "Dashboard", "Dashboard" } - - vim.g.dashboard_session_directory = lvim.builtin.dashboard.session_directory - - local lvim_site = "lunarvim.org" - local lvim_version = get_version "short" - local num_plugins_loaded = #vim.fn.globpath(get_runtime_dir() .. "/site/pack/packer/start", "*", 0, 1) - - local footer = { - "LunarVim loaded " .. num_plugins_loaded .. " plugins ", - "", - lvim_site, - } - - if lvim_version then - table.insert(footer, 2, "") - table.insert(footer, 3, "v" .. lvim_version) - end - - local text = require "interface.text" - vim.g.dashboard_custom_footer = text.align_center({ width = 0 }, footer, 0.49) -- Use 0.49 as  counts for 2 characters - - require("core.autocmds").define_augroups { - _dashboard = { - -- seems to be nobuflisted that makes my stuff disappear will do more testing - { - "FileType", - "dashboard", - "setlocal nocursorline noswapfile synmaxcol& signcolumn=no norelativenumber nocursorcolumn nospell nolist nonumber bufhidden=wipe colorcolumn= foldcolumn=0 matchpairs= ", - }, - { - "FileType", - "dashboard", - "set showtabline=0 | autocmd BufLeave set showtabline=" .. vim.opt.showtabline._value, - }, - { "FileType", "dashboard", "nnoremap q :q" }, - }, - } - - if lvim.builtin.dashboard.on_config_done then - lvim.builtin.dashboard.on_config_done() - end -end - -return M diff --git a/lua/core/gitsigns.lua b/lua/core/gitsigns.lua deleted file mode 100644 index cc6387dc..00000000 --- a/lua/core/gitsigns.lua +++ /dev/null @@ -1,64 +0,0 @@ -local M = {} - -M.config = function() - lvim.builtin.gitsigns = { - active = true, - on_config_done = nil, - opts = { - signs = { - add = { - hl = "GitSignsAdd", - text = "▎", - numhl = "GitSignsAddNr", - linehl = "GitSignsAddLn", - }, - change = { - hl = "GitSignsChange", - text = "▎", - numhl = "GitSignsChangeNr", - linehl = "GitSignsChangeLn", - }, - delete = { - hl = "GitSignsDelete", - text = "契", - numhl = "GitSignsDeleteNr", - linehl = "GitSignsDeleteLn", - }, - topdelete = { - hl = "GitSignsDelete", - text = "契", - numhl = "GitSignsDeleteNr", - linehl = "GitSignsDeleteLn", - }, - changedelete = { - hl = "GitSignsChange", - text = "▎", - numhl = "GitSignsChangeNr", - linehl = "GitSignsChangeLn", - }, - }, - numhl = false, - linehl = false, - keymaps = { - -- Default keymap options - noremap = true, - buffer = true, - }, - watch_gitdir = { interval = 1000 }, - sign_priority = 6, - update_debounce = 200, - status_formatter = nil, -- Use default - }, - } -end - -M.setup = function() - local gitsigns = require "gitsigns" - - gitsigns.setup(lvim.builtin.gitsigns.opts) - if lvim.builtin.gitsigns.on_config_done then - lvim.builtin.gitsigns.on_config_done(gitsigns) - end -end - -return M diff --git a/lua/core/info.lua b/lua/core/info.lua deleted file mode 100644 index 16001d07..00000000 --- a/lua/core/info.lua +++ /dev/null @@ -1,175 +0,0 @@ -local M = { - banner = { - "", - [[ __ _ ___ ]], - [[ / / __ ______ ____ _____| | / (_)___ ___ ]], - [[ / / / / / / __ \/ __ `/ ___/ | / / / __ `__ \]], - [[ / /___/ /_/ / / / / /_/ / / | |/ / / / / / / /]], - [[/_____/\__,_/_/ /_/\__,_/_/ |___/_/_/ /_/ /_/ ]], - }, -} - -local fmt = string.format -local text = require "interface.text" -local lsp_utils = require "lsp.utils" - -local function str_list(list) - return fmt("[ %s ]", table.concat(list, ", ")) -end - -local function get_formatter_suggestion_msg(ft) - local config = require "config" - local null_formatters = require "lsp.null-ls.formatters" - local supported_formatters = null_formatters.list_available(ft) - local section = { - " HINT ", - "", - fmt("* List of supported formatters: %s", str_list(supported_formatters)), - } - - if not vim.tbl_isempty(supported_formatters) then - vim.list_extend(section, { - "* Configured formatter needs to be installed and executable.", - fmt("* Enable installed formatter(s) with following config in %s", config.path), - "", - fmt(" lvim.lang.%s.formatters = { { exe = '%s' } }", ft, table.concat(supported_formatters, "│")), - }) - end - - return section -end - -local function get_linter_suggestion_msg(ft) - local config = require "config" - local null_linters = require "lsp.null-ls.linters" - local supported_linters = null_linters.list_available(ft) - local section = { - " HINT ", - "", - fmt("* List of supported linters: %s", str_list(supported_linters)), - } - - if not vim.tbl_isempty(supported_linters) then - vim.list_extend(section, { - "* Configured linter needs to be installed and executable.", - fmt("* Enable installed linter(s) with following config in %s", config.path), - "", - fmt(" lvim.lang.%s.linters = { { exe = '%s' } }", ft, table.concat(supported_linters, "│")), - }) - end - - return section -end - -local function tbl_set_highlight(terms, highlight_group) - for _, v in pairs(terms) do - vim.cmd('let m=matchadd("' .. highlight_group .. '", "' .. v .. "[ ,│']\")") - end -end - -local function make_client_info(client) - local client_enabled_caps = lsp_utils.get_client_capabilities(client.id) - local name = client.name - local id = client.id - local document_formatting = client.resolved_capabilities.document_formatting - local client_info = { - fmt("* Name: %s", name), - fmt("* Id: %s", tostring(id)), - fmt("* Supports formatting: %s", tostring(document_formatting)), - } - if not vim.tbl_isempty(client_enabled_caps) then - local caps_text = "* Capabilities list: " - local caps_text_len = caps_text:len() - local enabled_caps = text.format_table(client_enabled_caps, 3, " | ") - enabled_caps = text.shift_right(enabled_caps, caps_text_len) - enabled_caps[1] = fmt("%s%s", caps_text, enabled_caps[1]:sub(caps_text_len + 1)) - vim.list_extend(client_info, enabled_caps) - end - - return client_info -end - -function M.toggle_popup(ft) - local clients = lsp_utils.get_active_clients_by_ft(ft) - local client_names = {} - - local header = { - fmt("Detected filetype: %s", ft), - fmt("Treesitter active: %s", tostring(next(vim.treesitter.highlighter.active) ~= nil)), - } - - local lsp_info = { - "Language Server Protocol (LSP) info", - fmt "* Associated server(s):", - } - - for _, client in pairs(clients) do - vim.list_extend(lsp_info, make_client_info(client)) - table.insert(client_names, client.name) - end - - local null_formatters = require "lsp.null-ls.formatters" - local null_linters = require "lsp.null-ls.linters" - local registered_formatters = null_formatters.list_supported_names(ft) - local registered_linters = null_linters.list_supported_names(ft) - local registered_providers = {} - vim.list_extend(registered_providers, registered_formatters) - vim.list_extend(registered_providers, registered_linters) - local registered_count = vim.tbl_count(registered_providers) - local null_ls_info = { - "Formatters and linters", - fmt( - "* Configured providers: %s%s", - table.concat(registered_providers, "  , "), - registered_count > 0 and "  " or "" - ), - } - - local content_provider = function(popup) - local content = {} - - for _, section in ipairs { - M.banner, - { "" }, - { "" }, - header, - { "" }, - lsp_info, - { "" }, - null_ls_info, - { "" }, - { "" }, - get_formatter_suggestion_msg(ft), - { "" }, - { "" }, - get_linter_suggestion_msg(ft), - } do - vim.list_extend(content, section) - end - - return text.align_left(popup, content, 0.5) - end - - local function set_syntax_hl() - vim.cmd [[highlight LvimInfoIdentifier gui=bold]] - vim.cmd [[highlight link LvimInfoHeader Type]] - vim.cmd [[let m=matchadd("LvimInfoHeader", "Language Server Protocol (LSP) info")]] - vim.cmd [[let m=matchadd("LvimInfoHeader", "Formatters and linters")]] - vim.cmd('let m=matchadd("LvimInfoIdentifier", " ' .. ft .. '$")') - vim.cmd 'let m=matchadd("string", "true")' - vim.cmd 'let m=matchadd("error", "false")' - tbl_set_highlight(registered_providers, "LvimInfoIdentifier") - -- tbl_set_highlight(require("lsp.null-ls.formatters").list_available(ft), "LvimInfoIdentifier") - -- tbl_set_highlight(require("lsp.null-ls.linters").list_available(ft), "LvimInfoIdentifier") - end - - local Popup = require("interface.popup"):new { - win_opts = { number = false }, - buf_opts = { modifiable = false, filetype = "lspinfo" }, - } - Popup:display(content_provider) - set_syntax_hl() - - return Popup -end -return M diff --git a/lua/core/log.lua b/lua/core/log.lua deleted file mode 100644 index fca1fcb4..00000000 --- a/lua/core/log.lua +++ /dev/null @@ -1,60 +0,0 @@ -local Log = {} - ---- Adds a log entry using Plenary.log ----@param msg any ----@param level string [same as vim.log.log_levels] -function Log:add_entry(msg, level) - assert(type(level) == "string") - if self.__handle then - -- plenary uses lower-case log levels - self.__handle[level:lower()](msg) - return - end - local status_ok, plenary = pcall(require, "plenary") - if status_ok then - local default_opts = { plugin = "lunarvim", level = lvim.log.level } - local handle = plenary.log.new(default_opts) - handle[level:lower()](msg) - self.__handle = handle - end - -- don't do anything if plenary is not available -end - ----Retrieves the path of the logfile ----@return string path of the logfile -function Log:get_path() - return string.format("%s/%s.log", vim.fn.stdpath "cache", "lunarvim") -end - ----Add a log entry at TRACE level ----@param msg any -function Log:trace(msg) - self:add_entry(msg, "TRACE") -end - ----Add a log entry at DEBUG level ----@param msg any -function Log:debug(msg) - self:add_entry(msg, "DEBUG") -end - ----Add a log entry at INFO level ----@param msg any -function Log:info(msg) - self:add_entry(msg, "INFO") -end - ----Add a log entry at WARN level ----@param msg any -function Log:warn(msg) - self:add_entry(msg, "WARN") -end - ----Add a log entry at ERROR level ----@param msg any -function Log:error(msg) - self:add_entry(msg, "ERROR") -end - -setmetatable({}, Log) -return Log diff --git a/lua/core/lualine/colors.lua b/lua/core/lualine/colors.lua deleted file mode 100644 index 4984cd1f..00000000 --- a/lua/core/lualine/colors.lua +++ /dev/null @@ -1,16 +0,0 @@ -local colors = { - bg = "#202328", - fg = "#bbc2cf", - yellow = "#ECBE7B", - cyan = "#008080", - darkblue = "#081633", - green = "#98be65", - orange = "#FF8800", - violet = "#a9a1e1", - magenta = "#c678dd", - purple = "#c678dd", - blue = "#51afef", - red = "#ec5f67", -} - -return colors diff --git a/lua/core/lualine/components.lua b/lua/core/lualine/components.lua deleted file mode 100644 index 3ee2fdf8..00000000 --- a/lua/core/lualine/components.lua +++ /dev/null @@ -1,154 +0,0 @@ -local conditions = require "core.lualine.conditions" -local colors = require "core.lualine.colors" - -local function diff_source() - local gitsigns = vim.b.gitsigns_status_dict - if gitsigns then - return { - added = gitsigns.added, - modified = gitsigns.changed, - removed = gitsigns.removed, - } - end -end - -return { - mode = { - function() - return " " - end, - padding = { left = 0, right = 0 }, - color = {}, - cond = nil, - }, - branch = { - "b:gitsigns_head", - icon = " ", - color = { gui = "bold" }, - cond = conditions.hide_in_width, - }, - filename = { - "filename", - color = {}, - cond = nil, - }, - diff = { - "diff", - source = diff_source, - symbols = { added = "  ", modified = "柳", removed = " " }, - diff_color = { - added = { fg = colors.green }, - modified = { fg = colors.yellow }, - removed = { fg = colors.red }, - }, - color = {}, - cond = nil, - }, - python_env = { - function() - local utils = require "core.lualine.utils" - if vim.bo.filetype == "python" then - local venv = os.getenv "CONDA_DEFAULT_ENV" - if venv then - return string.format("  (%s)", utils.env_cleanup(venv)) - end - venv = os.getenv "VIRTUAL_ENV" - if venv then - return string.format("  (%s)", utils.env_cleanup(venv)) - end - return "" - end - return "" - end, - color = { fg = colors.green }, - cond = conditions.hide_in_width, - }, - diagnostics = { - "diagnostics", - sources = { "nvim_lsp" }, - symbols = { error = " ", warn = " ", info = " ", hint = " " }, - color = {}, - cond = conditions.hide_in_width, - }, - treesitter = { - function() - local b = vim.api.nvim_get_current_buf() - if next(vim.treesitter.highlighter.active[b]) then - return "  " - end - return "" - end, - color = { fg = colors.green }, - cond = conditions.hide_in_width, - }, - lsp = { - function(msg) - msg = msg or "LS Inactive" - local buf_clients = vim.lsp.buf_get_clients() - if next(buf_clients) == nil then - -- TODO: clean up this if statement - if type(msg) == "boolean" or #msg == 0 then - return "LS Inactive" - end - return msg - end - local buf_ft = vim.bo.filetype - local buf_client_names = {} - - -- add client - for _, client in pairs(buf_clients) do - if client.name ~= "null-ls" then - table.insert(buf_client_names, client.name) - end - end - - -- add formatter - local formatters = require "lsp.null-ls.formatters" - local supported_formatters = formatters.list_supported_names(buf_ft) - vim.list_extend(buf_client_names, supported_formatters) - - -- add linter - local linters = require "lsp.null-ls.linters" - local supported_linters = linters.list_supported_names(buf_ft) - vim.list_extend(buf_client_names, supported_linters) - - return table.concat(buf_client_names, ", ") - end, - icon = " ", - color = { gui = "bold" }, - cond = conditions.hide_in_width, - }, - location = { "location", cond = conditions.hide_in_width, color = {} }, - progress = { "progress", cond = conditions.hide_in_width, color = {} }, - spaces = { - function() - local label = "Spaces: " - if not vim.api.nvim_buf_get_option(0, "expandtab") then - label = "Tab size: " - end - return label .. vim.api.nvim_buf_get_option(0, "shiftwidth") .. " " - end, - cond = conditions.hide_in_width, - color = {}, - }, - encoding = { - "o:encoding", - fmt = string.upper, - color = {}, - cond = conditions.hide_in_width, - }, - filetype = { "filetype", cond = conditions.hide_in_width, color = {} }, - scrollbar = { - function() - local current_line = vim.fn.line "." - local total_lines = vim.fn.line "$" - local chars = { "__", "▁▁", "▂▂", "▃▃", "▄▄", "▅▅", "▆▆", "▇▇", "██" } - local line_ratio = current_line / total_lines - local index = math.ceil(line_ratio * #chars) - return chars[index] - end, - padding = { left = 0, right = 0 }, - color = { fg = colors.yellow, bg = colors.bg }, - cond = nil, - }, -} diff --git a/lua/core/lualine/conditions.lua b/lua/core/lualine/conditions.lua deleted file mode 100644 index 3ee4fbb8..00000000 --- a/lua/core/lualine/conditions.lua +++ /dev/null @@ -1,17 +0,0 @@ -local window_width_limit = 80 - -local conditions = { - buffer_not_empty = function() - return vim.fn.empty(vim.fn.expand "%:t") ~= 1 - end, - hide_in_width = function() - return vim.fn.winwidth(0) > window_width_limit - end, - -- check_git_workspace = function() - -- local filepath = vim.fn.expand "%:p:h" - -- local gitdir = vim.fn.finddir(".git", filepath .. ";") - -- return gitdir and #gitdir > 0 and #gitdir < #filepath - -- end, -} - -return conditions diff --git a/lua/core/lualine/init.lua b/lua/core/lualine/init.lua deleted file mode 100644 index aa6fe098..00000000 --- a/lua/core/lualine/init.lua +++ /dev/null @@ -1,47 +0,0 @@ -local M = {} -M.config = function() - lvim.builtin.lualine = { - active = true, - style = "lvim", - options = { - icons_enabled = nil, - component_separators = nil, - section_separators = nil, - theme = nil, - disabled_filetypes = nil, - }, - sections = { - lualine_a = nil, - lualine_b = nil, - lualine_c = nil, - lualine_x = nil, - lualine_y = nil, - lualine_z = nil, - }, - inactive_sections = { - lualine_a = nil, - lualine_b = nil, - lualine_c = nil, - lualine_x = nil, - lualine_y = nil, - lualine_z = nil, - }, - tabline = nil, - extensions = nil, - on_config_done = nil, - } -end - -M.setup = function() - require("core.lualine.styles").update() - require("core.lualine.utils").validate_theme() - - local lualine = require "lualine" - lualine.setup(lvim.builtin.lualine) - - if lvim.builtin.lualine.on_config_done then - lvim.builtin.lualine.on_config_done(lualine) - end -end - -return M diff --git a/lua/core/lualine/styles.lua b/lua/core/lualine/styles.lua deleted file mode 100644 index 19097424..00000000 --- a/lua/core/lualine/styles.lua +++ /dev/null @@ -1,137 +0,0 @@ -local M = {} -local components = require "core.lualine.components" - -local styles = { - lvim = nil, - default = nil, - none = nil, -} - -styles.none = { - style = "none", - options = { - icons_enabled = true, - component_separators = { left = "", right = "" }, - section_separators = { left = "", right = "" }, - disabled_filetypes = {}, - }, - sections = { - lualine_a = {}, - lualine_b = {}, - lualine_c = {}, - lualine_x = {}, - lualine_y = {}, - lualine_z = {}, - }, - inactive_sections = { - lualine_a = {}, - lualine_b = {}, - lualine_c = {}, - lualine_x = {}, - lualine_y = {}, - lualine_z = {}, - }, - tabline = {}, - extensions = {}, -} - -styles.default = { - style = "default", - options = { - icons_enabled = true, - component_separators = { left = "", right = "" }, - section_separators = { left = "", right = "" }, - disabled_filetypes = {}, - }, - sections = { - lualine_a = { "mode" }, - lualine_b = { "branch" }, - lualine_c = { "filename" }, - lualine_x = { "encoding", "fileformat", "filetype" }, - lualine_y = { "progress" }, - lualine_z = { "location" }, - }, - inactive_sections = { - lualine_a = {}, - lualine_b = {}, - lualine_c = { "filename" }, - lualine_x = { "location" }, - lualine_y = {}, - lualine_z = {}, - }, - tabline = {}, - extensions = {}, -} - -styles.lvim = { - style = "lvim", - options = { - icons_enabled = true, - component_separators = { left = "", right = "" }, - section_separators = { left = "", right = "" }, - disabled_filetypes = { "dashboard", "NvimTree", "Outline" }, - }, - sections = { - lualine_a = { - components.mode, - }, - lualine_b = { - components.branch, - components.filename, - }, - lualine_c = { - components.diff, - components.python_env, - }, - lualine_x = { - components.diagnostics, - components.treesitter, - components.lsp, - components.filetype, - }, - lualine_y = {}, - lualine_z = { - components.scrollbar, - }, - }, - inactive_sections = { - lualine_a = { - "filename", - }, - lualine_b = {}, - lualine_c = {}, - lualine_x = {}, - lualine_y = {}, - lualine_z = {}, - }, - tabline = {}, - extensions = { "nvim-tree" }, -} - -function M.get_style(style) - local style_keys = vim.tbl_keys(styles) - if not vim.tbl_contains(style_keys, style) then - local Log = require "core.log" - Log:error( - "Invalid lualine style", - string.format('"%s"', style), - "options are: ", - string.format('"%s"', table.concat(style_keys, '", "')) - ) - Log:debug '"lvim" style is applied.' - style = "lvim" - end - - return vim.deepcopy(styles[style]) -end - -function M.update() - local style = M.get_style(lvim.builtin.lualine.style) - if lvim.builtin.lualine.options.theme == nil then - lvim.builtin.lualine.options.theme = lvim.colorscheme - end - - lvim.builtin.lualine = vim.tbl_deep_extend("keep", lvim.builtin.lualine, style) -end - -return M diff --git a/lua/core/lualine/utils.lua b/lua/core/lualine/utils.lua deleted file mode 100644 index cf80a99e..00000000 --- a/lua/core/lualine/utils.lua +++ /dev/null @@ -1,27 +0,0 @@ -local M = {} - -function M.validate_theme() - local theme = lvim.builtin.lualine.options.theme - if type(theme) == "table" then - return - end - - local lualine_loader = require "lualine.utils.loader" - local ok = pcall(lualine_loader.load_theme, theme) - if not ok then - lvim.builtin.lualine.options.theme = "auto" - end -end - -function M.env_cleanup(venv) - if string.find(venv, "/") then - local final_venv = venv - for w in venv:gmatch "([^/]+)" do - final_venv = w - end - venv = final_venv - end - return venv -end - -return M diff --git a/lua/core/nvimtree.lua b/lua/core/nvimtree.lua deleted file mode 100644 index 2d131147..00000000 --- a/lua/core/nvimtree.lua +++ /dev/null @@ -1,141 +0,0 @@ -local M = {} -local Log = require "core.log" - -function M.config() - lvim.builtin.nvimtree = { - active = true, - on_config_done = nil, - setup = { - open_on_setup = false, - auto_close = true, - open_on_tab = false, - update_focused_file = { - enable = true, - }, - diagnostics = { - enable = true, - icons = { - hint = "", - info = "", - warning = "", - error = "", - }, - }, - view = { - width = 30, - side = "left", - auto_resize = false, - mappings = { - custom_only = false, - }, - }, - }, - show_icons = { - git = 1, - folders = 1, - files = 1, - folder_arrows = 1, - tree_width = 30, - }, - ignore = { ".git", "node_modules", ".cache" }, - quit_on_open = 0, - hide_dotfiles = 1, - git_hl = 1, - root_folder_modifier = ":t", - allow_resize = 1, - auto_ignore_ft = { "startify", "dashboard" }, - icons = { - default = "", - symlink = "", - git = { - unstaged = "", - staged = "S", - unmerged = "", - renamed = "➜", - deleted = "", - untracked = "U", - ignored = "◌", - }, - folder = { - default = "", - open = "", - empty = "", - empty_open = "", - symlink = "", - }, - }, - } -end - -function M.setup() - local status_ok, nvim_tree_config = pcall(require, "nvim-tree.config") - if not status_ok then - Log:error "Failed to load nvim-tree.config" - return - end - local g = vim.g - - for opt, val in pairs(lvim.builtin.nvimtree) do - g["nvim_tree_" .. opt] = val - end - - -- Implicitly update nvim-tree when project module is active - if lvim.builtin.project.active then - lvim.builtin.nvimtree.respect_buf_cwd = 1 - lvim.builtin.nvimtree.setup.update_cwd = true - lvim.builtin.nvimtree.setup.disable_netrw = false - lvim.builtin.nvimtree.setup.hijack_netrw = false - vim.g.netrw_banner = false - end - - local tree_cb = nvim_tree_config.nvim_tree_callback - - if not lvim.builtin.nvimtree.setup.view.mappings.list then - lvim.builtin.nvimtree.setup.view.mappings.list = { - { key = { "l", "", "o" }, cb = tree_cb "edit" }, - { key = "h", cb = tree_cb "close_node" }, - { key = "v", cb = tree_cb "vsplit" }, - } - end - - lvim.builtin.which_key.mappings["e"] = { "NvimTreeToggle", "Explorer" } - - local tree_view = require "nvim-tree.view" - - -- Add nvim_tree open callback - local open = tree_view.open - tree_view.open = function() - M.on_open() - open() - end - - vim.cmd "au WinClosed * lua require('core.nvimtree').on_close()" - - if lvim.builtin.nvimtree.on_config_done then - lvim.builtin.nvimtree.on_config_done(nvim_tree_config) - end - require("nvim-tree").setup(lvim.builtin.nvimtree.setup) -end - -function M.on_open() - if package.loaded["bufferline.state"] and lvim.builtin.nvimtree.setup.view.side == "left" then - require("bufferline.state").set_offset(lvim.builtin.nvimtree.setup.view.width + 1, "") - end -end - -function M.on_close() - local buf = tonumber(vim.fn.expand "") - local ft = vim.api.nvim_buf_get_option(buf, "filetype") - if ft == "NvimTree" and package.loaded["bufferline.state"] then - require("bufferline.state").set_offset(0) - end -end - -function M.change_tree_dir(dir) - local lib_status_ok, lib = pcall(require, "nvim-tree.lib") - if lib_status_ok then - lib.change_dir(dir) - end -end - -return M diff --git a/lua/core/project.lua b/lua/core/project.lua deleted file mode 100644 index e7527440..00000000 --- a/lua/core/project.lua +++ /dev/null @@ -1,51 +0,0 @@ -local M = {} - -function M.config() - lvim.builtin.project = { - ---@usage set to false to disable project.nvim. - --- This is on by default since it's currently the expected behavior. - active = true, - - on_config_done = nil, - - ---@usage set to true to disable setting the current-woriking directory - --- Manual mode doesn't automatically change your root directory, so you have - --- the option to manually do so using `:ProjectRoot` command. - manual_mode = false, - - ---@usage Methods of detecting the root directory - --- Allowed values: **"lsp"** uses the native neovim lsp - --- **"pattern"** uses vim-rooter like glob pattern matching. Here - --- order matters: if one is not detected, the other is used as fallback. You - --- can also delete or rearangne the detection methods. - detection_methods = { "lsp", "pattern" }, - - ---@usage patterns used to detect root dir, when **"pattern"** is in detection_methods - patterns = { ".git", "_darcs", ".hg", ".bzr", ".svn", "Makefile", "package.json" }, - - ---@ Show hidden files in telescope when searching for files in a project - show_hidden = false, - - ---@usage When set to false, you will get a message when project.nvim changes your directory. - -- When set to false, you will get a message when project.nvim changes your directory. - silent_chdir = true, - - ---@usage list of lsp client names to ignore when using **lsp** detection. eg: { "efm", ... } - ignore_lsp = {}, - - ---@type string - ---@usage path to store the project history for use in telescope - datapath = get_cache_dir(), - } -end - -function M.setup() - local project = require "project_nvim" - - project.setup(lvim.builtin.project) - if lvim.builtin.project.on_config_done then - lvim.builtin.project.on_config_done(project) - end -end - -return M diff --git a/lua/core/telescope.lua b/lua/core/telescope.lua deleted file mode 100644 index ba0a9ee1..00000000 --- a/lua/core/telescope.lua +++ /dev/null @@ -1,194 +0,0 @@ -local M = {} - -local utils = require "utils" - -function M.config() - -- Define this minimal config so that it's available if telescope is not yet available. - lvim.builtin.telescope = { - ---@usage disable telescope completely [not recommeded] - active = true, - on_config_done = nil, - } - - local status_ok, actions = pcall(require, "telescope.actions") - if not status_ok then - return - end - - lvim.builtin.telescope = vim.tbl_extend("force", lvim.builtin.telescope, { - defaults = { - prompt_prefix = " ", - selection_caret = " ", - entry_prefix = " ", - initial_mode = "insert", - selection_strategy = "reset", - sorting_strategy = "descending", - layout_strategy = "horizontal", - layout_config = { - width = 0.75, - preview_cutoff = 120, - horizontal = { mirror = false }, - vertical = { mirror = false }, - }, - file_sorter = require("telescope.sorters").get_fzy_sorter, - file_ignore_patterns = {}, - generic_sorter = require("telescope.sorters").get_generic_fuzzy_sorter, - path_display = { shorten = 5 }, - winblend = 0, - border = {}, - borderchars = { "─", "│", "─", "│", "╭", "╮", "╯", "╰" }, - color_devicons = true, - use_less = true, - set_env = { ["COLORTERM"] = "truecolor" }, -- default = nil, - file_previewer = require("telescope.previewers").vim_buffer_cat.new, - grep_previewer = require("telescope.previewers").vim_buffer_vimgrep.new, - qflist_previewer = require("telescope.previewers").vim_buffer_qflist.new, - - -- Developer configurations: Not meant for general override - -- buffer_previewer_maker = require("telescope.previewers").buffer_previewer_maker, - mappings = { - i = { - [""] = actions.move_selection_next, - [""] = actions.move_selection_previous, - [""] = actions.close, - [""] = actions.cycle_history_next, - [""] = actions.cycle_history_prev, - [""] = actions.smart_send_to_qflist + actions.open_qflist, - [""] = actions.select_default + actions.center, - -- To disable a keymap, put [map] = false - -- So, to not map "", just put - -- [""] = trouble.open_with_trouble, - -- [""] = false, - -- [""] = actions.close, - -- Otherwise, just set the mapping to the function that you want it to be. - -- [""] = actions.select_horizontal, - -- Add up multiple actions - -- You can perform as many actions in a row as you like - -- [""] = actions.select_default + actions.center + my_cool_custom_action, - }, - n = { - [""] = actions.move_selection_next, - [""] = actions.move_selection_previous, - [""] = actions.smart_send_to_qflist + actions.open_qflist, - -- [""] = trouble.open_with_trouble, - -- [""] = my_cool_custom_action, - }, - }, - }, - extensions = { - fzy_native = { - override_generic_sorter = false, - override_file_sorter = true, - }, - }, - }) -end - -function M.find_lunarvim_files(opts) - opts = opts or {} - local themes = require "telescope.themes" - local theme_opts = themes.get_ivy { - sorting_strategy = "ascending", - layout_strategy = "bottom_pane", - prompt_prefix = ">> ", - prompt_title = "~ LunarVim files ~", - cwd = utils.join_paths(get_runtime_dir(), "lvim"), - find_command = { "git", "ls-files" }, - } - opts = vim.tbl_deep_extend("force", theme_opts, opts) - require("telescope.builtin").find_files(opts) -end - -function M.grep_lunarvim_files(opts) - opts = opts or {} - local themes = require "telescope.themes" - local theme_opts = themes.get_ivy { - sorting_strategy = "ascending", - layout_strategy = "bottom_pane", - prompt_prefix = ">> ", - prompt_title = "~ search LunarVim ~", - cwd = utils.join_paths(get_runtime_dir(), "lvim"), - } - opts = vim.tbl_deep_extend("force", theme_opts, opts) - require("telescope.builtin").live_grep(opts) -end - -function M.view_lunarvim_changelog() - local finders = require "telescope.finders" - local make_entry = require "telescope.make_entry" - local pickers = require "telescope.pickers" - local previewers = require "telescope.previewers" - local actions = require "telescope.actions" - local opts = {} - - local conf = require("telescope.config").values - opts.entry_maker = make_entry.gen_from_git_commits(opts) - - pickers.new(opts, { - prompt_title = "LunarVim changelog", - - finder = finders.new_oneshot_job( - vim.tbl_flatten { - "git", - "log", - "--pretty=oneline", - "--abbrev-commit", - "--", - ".", - }, - opts - ), - previewer = { - previewers.git_commit_diff_to_parent.new(opts), - previewers.git_commit_diff_to_head.new(opts), - previewers.git_commit_diff_as_was.new(opts), - previewers.git_commit_message.new(opts), - }, - - --TODO: consider opening a diff view when pressing enter - attach_mappings = function(_, map) - map("i", "", actions._close) - map("n", "", actions._close) - map("i", "", actions._close) - map("n", "", actions._close) - map("n", "q", actions._close) - return true - end, - sorter = conf.file_sorter(opts), - }):find() -end - -function M.code_actions() - local opts = { - winblend = 15, - layout_config = { - prompt_position = "top", - width = 80, - height = 12, - }, - borderchars = { - prompt = { "─", "│", " ", "│", "╭", "╮", "│", "│" }, - results = { "─", "│", "─", "│", "├", "┤", "╯", "╰" }, - preview = { "─", "│", "─", "│", "╭", "╮", "╯", "╰" }, - }, - border = {}, - previewer = false, - shorten_path = false, - } - require("telescope.builtin").lsp_code_actions(require("telescope.themes").get_dropdown(opts)) -end - -function M.setup() - local telescope = require "telescope" - - telescope.setup(lvim.builtin.telescope) - if lvim.builtin.project.active then - telescope.load_extension "projects" - end - - if lvim.builtin.telescope.on_config_done then - lvim.builtin.telescope.on_config_done(telescope) - end -end - -return M diff --git a/lua/core/terminal.lua b/lua/core/terminal.lua deleted file mode 100644 index 3a0c6e46..00000000 --- a/lua/core/terminal.lua +++ /dev/null @@ -1,114 +0,0 @@ -local M = {} -local Log = require "core.log" - -M.config = function() - lvim.builtin["terminal"] = { - on_config_done = nil, - -- size can be a number or function which is passed the current terminal - size = 20, - -- open_mapping = [[]], - open_mapping = [[]], - hide_numbers = true, -- hide the number column in toggleterm buffers - shade_filetypes = {}, - shade_terminals = true, - shading_factor = 2, -- the degree by which to darken to terminal colour, default: 1 for dark backgrounds, 3 for light - start_in_insert = true, - insert_mappings = true, -- whether or not the open mapping applies in insert mode - persist_size = false, - -- direction = 'vertical' | 'horizontal' | 'window' | 'float', - direction = "float", - close_on_exit = true, -- close the terminal window when the process exits - shell = vim.o.shell, -- change the default shell - -- This field is only relevant if direction is set to 'float' - float_opts = { - -- The border key is *almost* the same as 'nvim_win_open' - -- see :h nvim_win_open for details on borders however - -- the 'curved' border is a custom border type - -- not natively supported but implemented in this plugin. - -- border = 'single' | 'double' | 'shadow' | 'curved' | ... other options supported by win open - border = "curved", - -- width = , - -- height = , - winblend = 0, - highlights = { - border = "Normal", - background = "Normal", - }, - }, - -- Add executables on the config.lua - -- { exec, keymap, name} - -- lvim.builtin.terminal.execs = {{}} to overwrite - -- lvim.builtin.terminal.execs[#lvim.builtin.terminal.execs+1] = {"gdb", "tg", "GNU Debugger"} - execs = { - { "lazygit", "gg", "LazyGit" }, - }, - } -end - -M.setup = function() - local terminal = require "toggleterm" - for _, exec in pairs(lvim.builtin.terminal.execs) do - require("core.terminal").add_exec(exec[1], exec[2], exec[3]) - end - terminal.setup(lvim.builtin.terminal) - - if lvim.builtin.terminal.on_config_done then - lvim.builtin.terminal.on_config_done(terminal) - end -end - -M.add_exec = function(exec, keymap, name) - vim.api.nvim_set_keymap( - "n", - "" .. keymap, - "lua require('core.terminal')._exec_toggle('" .. exec .. "')", - { noremap = true, silent = true } - ) - lvim.builtin.which_key.mappings[keymap] = name -end - -M._split = function(inputstr, sep) - if sep == nil then - sep = "%s" - end - local t = {} - for str in string.gmatch(inputstr, "([^" .. sep .. "]+)") do - table.insert(t, str) - end - return t -end - -M._exec_toggle = function(exec) - local binary = M._split(exec)[1] - if vim.fn.executable(binary) ~= 1 then - Log:error("Unable to run executable " .. binary .. ". Please make sure it is installed properly.") - return - end - local Terminal = require("toggleterm.terminal").Terminal - local exec_term = Terminal:new { cmd = exec, hidden = true } - exec_term:toggle() -end - ----Toggles a log viewer according to log.viewer.layout_config ----@param logfile string the fullpath to the logfile -M.toggle_log_view = function(logfile) - local log_viewer = lvim.log.viewer.cmd - if vim.fn.executable(log_viewer) ~= 1 then - log_viewer = "less +F" - end - log_viewer = log_viewer .. " " .. logfile - local term_opts = vim.tbl_deep_extend("force", lvim.builtin.terminal, { - cmd = log_viewer, - open_mapping = lvim.log.viewer.layout_config.open_mapping, - direction = lvim.log.viewer.layout_config.direction, - -- TODO: this might not be working as expected - size = lvim.log.viewer.layout_config.size, - float_opts = lvim.log.viewer.layout_config.float_opts, - }) - - local Terminal = require("toggleterm.terminal").Terminal - local log_view = Terminal:new(term_opts) - log_view:toggle() -end - -return M diff --git a/lua/core/treesitter.lua b/lua/core/treesitter.lua deleted file mode 100644 index d63024e6..00000000 --- a/lua/core/treesitter.lua +++ /dev/null @@ -1,81 +0,0 @@ -local M = {} -local Log = require "core.log" - -M.config = function() - lvim.builtin.treesitter = { - on_config_done = nil, - ensure_installed = {}, -- one of "all", "maintained" (parsers with maintainers), or a list of languages - ignore_install = {}, - matchup = { - enable = false, -- mandatory, false will disable the whole extension - -- disable = { "c", "ruby" }, -- optional, list of language that will be disabled - }, - highlight = { - enable = true, -- false will disable the whole extension - additional_vim_regex_highlighting = true, - disable = { "latex" }, - }, - context_commentstring = { - enable = false, - config = { css = "// %s" }, - }, - -- indent = {enable = true, disable = {"python", "html", "javascript"}}, - -- TODO seems to be broken - indent = { enable = true, disable = { "yaml" } }, - autotag = { enable = false }, - textobjects = { - swap = { - enable = false, - -- swap_next = textobj_swap_keymaps, - }, - -- move = textobj_move_keymaps, - select = { - enable = false, - -- keymaps = textobj_sel_keymaps, - }, - }, - textsubjects = { - enable = false, - keymaps = { ["."] = "textsubjects-smart", [";"] = "textsubjects-big" }, - }, - playground = { - enable = false, - disable = {}, - updatetime = 25, -- Debounced time for highlighting nodes in the playground from source code - persist_queries = false, -- Whether the query persists across vim sessions - keybindings = { - toggle_query_editor = "o", - toggle_hl_groups = "i", - toggle_injected_languages = "t", - toggle_anonymous_nodes = "a", - toggle_language_display = "I", - focus_language = "f", - unfocus_language = "F", - update = "R", - goto_node = "", - show_help = "?", - }, - }, - rainbow = { - enable = false, - extended_mode = true, -- Highlight also non-parentheses delimiters, boolean or table: lang -> boolean - max_file_lines = 1000, -- Do not enable for files with more than 1000 lines, int - }, - } -end - -M.setup = function() - local status_ok, treesitter_configs = pcall(require, "nvim-treesitter.configs") - if not status_ok then - Log:get_default().error "Failed to load nvim-treesitter.configs" - return - end - - treesitter_configs.setup(lvim.builtin.treesitter) - - if lvim.builtin.treesitter.on_config_done then - lvim.builtin.treesitter.on_config_done(treesitter_configs) - end -end - -return M diff --git a/lua/core/which-key.lua b/lua/core/which-key.lua deleted file mode 100644 index c9e9b2f4..00000000 --- a/lua/core/which-key.lua +++ /dev/null @@ -1,267 +0,0 @@ -local M = {} - -M.config = function() - lvim.builtin.which_key = { - ---@usage disable which-key completely [not recommeded] - active = true, - on_config_done = nil, - setup = { - plugins = { - marks = true, -- shows a list of your marks on ' and ` - registers = true, -- shows your registers on " in NORMAL or in INSERT mode - -- the presets plugin, adds help for a bunch of default keybindings in Neovim - -- No actual key bindings are created - presets = { - 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 - 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 - }, - spelling = { enabled = true, suggestions = 20 }, -- use which-key for spelling hints - }, - icons = { - breadcrumb = "»", -- symbol used in the command line area that shows your active key combo - separator = "➜", -- symbol used between a key and it's label - group = "+", -- symbol prepended to a group - }, - 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] - }, - 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 - }, - hidden = { "", "", "", "", "call", "lua", "^:", "^ " }, -- hide mapping boilerplate - show_help = true, -- show help message on the command line when the popup is visible - }, - - opts = { - mode = "n", -- NORMAL mode - prefix = "", - buffer = nil, -- Global mappings. Specify a buffer number for buffer local mappings - silent = true, -- use `silent` when creating keymaps - noremap = true, -- use `noremap` when creating keymaps - nowait = true, -- use `nowait` when creating keymaps - }, - vopts = { - mode = "v", -- VISUAL mode - prefix = "", - buffer = nil, -- Global mappings. Specify a buffer number for buffer local mappings - silent = true, -- use `silent` when creating keymaps - noremap = true, -- use `noremap` when creating keymaps - nowait = true, -- use `nowait` when creating keymaps - }, - -- NOTE: Prefer using : over as the latter avoids going back in normal-mode. - -- see https://neovim.io/doc/user/map.html#:map-cmd - vmappings = { - ["/"] = { ":CommentToggle", "Comment" }, - }, - mappings = { - ["w"] = { "w!", "Save" }, - ["q"] = { "q!", "Quit" }, - ["/"] = { "CommentToggle", "Comment" }, - ["c"] = { "BufferClose!", "Close Buffer" }, - ["f"] = { "Telescope find_files", "Find File" }, - ["h"] = { "nohlsearch", "No Highlight" }, - b = { - name = "Buffers", - j = { "BufferPick", "Jump" }, - f = { "Telescope buffers", "Find" }, - b = { "b#", "Previous" }, - w = { "BufferWipeout", "Wipeout" }, - e = { - "BufferCloseAllButCurrent", - "Close all but current", - }, - h = { "BufferCloseBuffersLeft", "Close all to the left" }, - l = { - "BufferCloseBuffersRight", - "Close all to the right", - }, - D = { - "BufferOrderByDirectory", - "Sort by directory", - }, - L = { - "BufferOrderByLanguage", - "Sort by language", - }, - }, - p = { - name = "Packer", - c = { "PackerCompile", "Compile" }, - i = { "PackerInstall", "Install" }, - r = { "lua require('utils').reload_lv_config()", "Reload" }, - s = { "PackerSync", "Sync" }, - S = { "PackerStatus", "Status" }, - u = { "PackerUpdate", "Update" }, - }, - - -- " Available Debug Adapters: - -- " https://microsoft.github.io/debug-adapter-protocol/implementors/adapters/ - -- " Adapter configuration and installation instructions: - -- " https://github.com/mfussenegger/nvim-dap/wiki/Debug-Adapter-installation - -- " Debug Adapter protocol: - -- " https://microsoft.github.io/debug-adapter-protocol/ - -- " Debugging - g = { - name = "Git", - j = { "lua require 'gitsigns'.next_hunk()", "Next Hunk" }, - k = { "lua require 'gitsigns'.prev_hunk()", "Prev Hunk" }, - l = { "lua require 'gitsigns'.blame_line()", "Blame" }, - p = { "lua require 'gitsigns'.preview_hunk()", "Preview Hunk" }, - r = { "lua require 'gitsigns'.reset_hunk()", "Reset Hunk" }, - R = { "lua require 'gitsigns'.reset_buffer()", "Reset Buffer" }, - s = { "lua require 'gitsigns'.stage_hunk()", "Stage Hunk" }, - u = { - "lua require 'gitsigns'.undo_stage_hunk()", - "Undo Stage Hunk", - }, - o = { "Telescope git_status", "Open changed file" }, - b = { "Telescope git_branches", "Checkout branch" }, - c = { "Telescope git_commits", "Checkout commit" }, - C = { - "Telescope git_bcommits", - "Checkout commit(for current file)", - }, - d = { - "Gitsigns diffthis HEAD", - "Git Diff", - }, - }, - - l = { - name = "LSP", - a = { "lua require('core.telescope').code_actions()", "Code Action" }, - d = { - "Telescope lsp_document_diagnostics", - "Document Diagnostics", - }, - w = { - "Telescope lsp_workspace_diagnostics", - "Workspace Diagnostics", - }, - f = { "lua vim.lsp.buf.formatting()", "Format" }, - i = { "LspInfo", "Info" }, - I = { "LspInstallInfo", "Installer Info" }, - j = { - "lua vim.lsp.diagnostic.goto_next({popup_opts = {border = lvim.lsp.popup_border}})", - "Next Diagnostic", - }, - k = { - "lua vim.lsp.diagnostic.goto_prev({popup_opts = {border = lvim.lsp.popup_border}})", - "Prev Diagnostic", - }, - l = { "lua vim.lsp.codelens.run()", "CodeLens Action" }, - p = { - name = "Peek", - d = { "lua require('lsp.peek').Peek('definition')", "Definition" }, - t = { "lua require('lsp.peek').Peek('typeDefinition')", "Type Definition" }, - i = { "lua require('lsp.peek').Peek('implementation')", "Implementation" }, - }, - q = { "lua vim.lsp.diagnostic.set_loclist()", "Quickfix" }, - r = { "lua vim.lsp.buf.rename()", "Rename" }, - s = { "Telescope lsp_document_symbols", "Document Symbols" }, - S = { - "Telescope lsp_dynamic_workspace_symbols", - "Workspace Symbols", - }, - }, - L = { - name = "+LunarVim", - c = { - "edit" .. get_config_dir() .. "/config.lua", - "Edit config.lua", - }, - f = { - "lua require('core.telescope').find_lunarvim_files()", - "Find LunarVim files", - }, - g = { - "lua require('core.telescope').grep_lunarvim_files()", - "Grep LunarVim files", - }, - k = { "lua require('keymappings').print()", "View LunarVim's default keymappings" }, - i = { - "lua require('core.info').toggle_popup(vim.bo.filetype)", - "Toggle LunarVim Info", - }, - I = { - "lua require('core.telescope').view_lunarvim_changelog()", - "View LunarVim's changelog", - }, - l = { - name = "+logs", - d = { - "lua require('core.terminal').toggle_log_view(require('core.log').get_path())", - "view default log", - }, - D = { "lua vim.fn.execute('edit ' .. require('core.log').get_path())", "Open the default logfile" }, - l = { "lua require('core.terminal').toggle_log_view(vim.lsp.get_log_path())", "view lsp log" }, - L = { "lua vim.fn.execute('edit ' .. vim.lsp.get_log_path())", "Open the LSP logfile" }, - n = { - "lua require('core.terminal').toggle_log_view(os.getenv('NVIM_LOG_FILE'))", - "view neovim log", - }, - N = { "edit $NVIM_LOG_FILE", "Open the Neovim logfile" }, - p = { - "lua require('core.terminal').toggle_log_view('packer.nvim')", - "view packer log", - }, - P = { "exe 'edit '.stdpath('cache').'/packer.nvim.log'", "Open the Packer logfile" }, - }, - r = { "lua require('utils').reload_lv_config()", "Reload configurations" }, - u = { "LvimUpdate", "Update LunarVim" }, - }, - s = { - name = "Search", - b = { "Telescope git_branches", "Checkout branch" }, - c = { "Telescope colorscheme", "Colorscheme" }, - f = { "Telescope find_files", "Find File" }, - h = { "Telescope help_tags", "Find Help" }, - M = { "Telescope man_pages", "Man Pages" }, - r = { "Telescope oldfiles", "Open Recent File" }, - R = { "Telescope registers", "Registers" }, - t = { "Telescope live_grep", "Text" }, - k = { "Telescope keymaps", "Keymaps" }, - C = { "Telescope commands", "Commands" }, - p = { - "lua require('telescope.builtin.internal').colorscheme({enable_preview = true})", - "Colorscheme with Preview", - }, - }, - T = { - name = "Treesitter", - i = { ":TSConfigInfo", "Info" }, - }, - }, - } -end - -M.setup = function() - local which_key = require "which-key" - - which_key.setup(lvim.builtin.which_key.setup) - - local opts = lvim.builtin.which_key.opts - local vopts = lvim.builtin.which_key.vopts - - local mappings = lvim.builtin.which_key.mappings - local vmappings = lvim.builtin.which_key.vmappings - - which_key.register(mappings, opts) - which_key.register(vmappings, vopts) - - if lvim.builtin.which_key.on_config_done then - lvim.builtin.which_key.on_config_done(which_key) - end -end - -return M diff --git a/lua/impatient.lua b/lua/impatient.lua deleted file mode 100644 index d438851c..00000000 --- a/lua/impatient.lua +++ /dev/null @@ -1,360 +0,0 @@ --- modified version from https://github.com/lewis6991/impatient.nvim - -local vim = vim -local uv = vim.loop -local impatient_load_start = uv.hrtime() -local api = vim.api -local ffi = require "ffi" - -local get_option, set_option = api.nvim_get_option, api.nvim_set_option -local get_runtime_file = api.nvim_get_runtime_file - -local impatient_dur - -local M = { - cache = {}, - profile = nil, - dirty = false, - path = nil, - log = {}, -} - -_G.__luacache = M - ---{{{ -local cachepack = {} - --- using double for packing/unpacking numbers has no conversion overhead --- 32-bit ARM causes a bus error when casting to double, so use int there -local number_t = jit.arch ~= "arm" and "double" or "int" -ffi.cdef("typedef " .. number_t .. " number_t;") - -local c_number_t = ffi.typeof "number_t[1]" -local c_sizeof_number_t = ffi.sizeof "number_t" - -local out_buf = {} - -function out_buf.write_number(buf, num) - buf[#buf + 1] = ffi.string(c_number_t(num), c_sizeof_number_t) -end - -function out_buf.write_string(buf, str) - out_buf.write_number(buf, #str) - buf[#buf + 1] = str -end - -function out_buf.to_string(buf) - return table.concat(buf) -end - -local in_buf = {} - -function in_buf.read_number(buf) - if buf.size < buf.pos then - error "buffer access violation" - end - local res = ffi.cast("number_t*", buf.ptr + buf.pos)[0] - buf.pos = buf.pos + c_sizeof_number_t - return res -end - -function in_buf.read_string(buf) - local len = in_buf.read_number(buf) - local res = ffi.string(buf.ptr + buf.pos, len) - buf.pos = buf.pos + len - - return res -end - -function cachepack.pack(cache) - local total_keys = vim.tbl_count(cache) - local buf = {} - - out_buf.write_number(buf, total_keys) - for k, v in pairs(cache) do - out_buf.write_string(buf, k) - out_buf.write_string(buf, v[1] or "") - out_buf.write_number(buf, v[2] or 0) - out_buf.write_string(buf, v[3] or "") - end - - return out_buf.to_string(buf) -end - -function cachepack.unpack(str, raw_buf_size) - if raw_buf_size == 0 or str == nil or (raw_buf_size == nil and #str == 0) then - return {} - end - - local buf = { - ptr = raw_buf_size and str or ffi.new("const char[?]", #str, str), - pos = 0, - size = raw_buf_size or #str, - } - local cache = {} - - local total_keys = in_buf.read_number(buf) - for _ = 1, total_keys do - local k = in_buf.read_string(buf) - local v = { - in_buf.read_string(buf), - in_buf.read_number(buf), - in_buf.read_string(buf), - } - cache[k] = v - end - - return cache -end ---}}} - -local function log(...) - M.log[#M.log + 1] = table.concat({ string.format(...) }, " ") -end - -function M.print_log() - for _, l in ipairs(M.log) do - print(l) - end -end - -function M.enable_profile() - M.profile = {} - M.print_profile = function() - M.profile["impatient"] = { - resolve = 0, - load = impatient_dur, - loader = "standard", - } - require("impatient.profile").print_profile(M.profile) - end - vim.cmd [[command! LuaCacheProfile lua _G.__luacache.print_profile()]] -end - -local function is_cacheable(path) - -- Don't cache files in /tmp since they are not likely to persist. - -- Note: Appimage versions of Neovim mount $VIMRUNTIME in /tmp in a unique - -- directory on each launch. - return not vim.startswith(path, "/tmp/") -end - -local function hash(modpath) - local stat = uv.fs_stat(modpath) - if stat then - return stat.mtime.sec - end -end - -local function hrtime() - if M.profile then - return uv.hrtime() - end -end - -local function load_package_with_cache(name, loader) - local resolve_start = hrtime() - - local basename = name:gsub("%.", "/") - local paths = { "lua/" .. basename .. ".lua", "lua/" .. basename .. "/init.lua" } - - for _, path in ipairs(paths) do - local modpath = get_runtime_file(path, false)[1] - if modpath then - local load_start = hrtime() - local chunk, err = loadfile(modpath) - - if M.profile then - M.profile[name] = { - resolve = load_start - resolve_start, - load = hrtime() - load_start, - loader = loader or "standard", - } - end - - if chunk == nil then - return err - end - - if is_cacheable(modpath) then - log("Creating cache for module %s", name) - M.cache[name] = { modpath, hash(modpath), string.dump(chunk) } - M.dirty = true - else - log("Unable to cache module %s", name) - end - - return chunk - end - end - return nil -end - -local reduced_rtp - --- Speed up non-cached loads by reducing the rtp path during requires -function M.update_reduced_rtp() - local luadirs = get_runtime_file("lua/", true) - - for i = 1, #luadirs do - luadirs[i] = luadirs[i]:sub(1, -6) - end - - reduced_rtp = table.concat(luadirs, ",") -end - -local function load_package_with_cache_reduced_rtp(name) - local orig_rtp = get_option "runtimepath" - local orig_ei = get_option "eventignore" - - if not reduced_rtp then - M.update_reduced_rtp() - end - - set_option("eventignore", "all") - set_option("rtp", reduced_rtp) - - local found = load_package_with_cache(name, "reduced") - - set_option("rtp", orig_rtp) - set_option("eventignore", orig_ei) - - return found -end - -local function load_from_cache(name) - local resolve_start = hrtime() - if M.cache[name] == nil then - log("No cache for module %s", name) - return "No cache entry" - end - - local modpath, mhash, codes = unpack(M.cache[name]) - - if mhash ~= hash(modpath) then - log("Stale cache for module %s", name) - M.cache[name] = nil - M.dirty = true - return "Stale cache" - end - - local load_start = hrtime() - local chunk = loadstring(codes) - - if M.profile then - M.profile[name] = { - resolve = load_start - resolve_start, - load = hrtime() - load_start, - loader = "cache", - } - end - - if not chunk then - M.cache[name] = nil - M.dirty = true - log("Error loading cache for module. Invalidating", name) - return "Cache error" - end - - return chunk -end - -function M.save_cache() - if M.dirty then - log("Updating cache file: %s", M.path) - local f = io.open(M.path, "w+b") - f:write(cachepack.pack(M.cache)) - f:flush() - M.dirty = false - end -end - -function M.clear_cache() - M.cache = {} - os.remove(M.path) -end - -impatient_dur = uv.hrtime() - impatient_load_start - -function M.setup(opts) - opts = opts or {} - M.path = opts.path or vim.fn.stdpath "cache" .. "/lvim_cache" - - if opts.enable_profiling then - M.enable_profile() - end - - local impatient_setup_start = uv.hrtime() - local stat = uv.fs_stat(M.path) - if stat then - log("Loading cache file %s", M.path) - local ok - -- Linux/macOS lets us easily mmap the cache file for faster reads without passing to Lua - if jit.os == "Linux" or jit.os == "OSX" then - local size = stat.size - - local C = ffi.C - local O_RDONLY = 0x00 - local PROT_READ = 0x01 - local MAP_PRIVATE = 0x02 - - ffi.cdef [[ - int open(const char *pathname, int flags); - int close(int fd); - void *mmap(void *addr, size_t length, int prot, int flags, int fd, long int offset); - int munmap(void *addr, size_t length); - ]] - local f = C.open(M.path, O_RDONLY) - - local addr = C.mmap(nil, size, PROT_READ, MAP_PRIVATE, f, 0) - ok = ffi.cast("intptr_t", addr) ~= -1 - - if ok then - M.cache = cachepack.unpack(ffi.cast("char *", addr), size) - C.munmap(addr, size) - end - - C.close(f) - else - local f = io.open(M.path, "rb") - ok, M.cache = pcall(function() - return cachepack.unpack(f:read "*a") - end) - end - - if not ok then - log("Corrupted cache file, %s. Invalidating...", M.path) - os.remove(M.path) - M.cache = {} - end - M.dirty = not ok - end - - local insert = table.insert - local package = package - - -- Fix the position of the preloader. This also makes loading modules like 'ffi' - -- and 'bit' quicker - if package.loaders[1] == vim._load_package then - -- Move vim._load_package to the second position - local vim_load = table.remove(package.loaders, 1) - insert(package.loaders, 2, vim_load) - end - - insert(package.loaders, 2, load_from_cache) - insert(package.loaders, 3, load_package_with_cache_reduced_rtp) - insert(package.loaders, 4, load_package_with_cache) - - vim.cmd [[ - augroup impatient - autocmd VimEnter,VimLeave * lua _G.__luacache.save_cache() - autocmd OptionSet runtimepath lua _G.__luacache.update_reduced_rtp(true) - augroup END - - command! LuaCacheClear lua _G.__luacache.clear_cache() - command! LuaCacheLog lua _G.__luacache.print_log() - ]] - - impatient_dur = impatient_dur + (uv.hrtime() - impatient_setup_start) -end - -return M diff --git a/lua/impatient/profile.lua b/lua/impatient/profile.lua deleted file mode 100644 index 0f4f8236..00000000 --- a/lua/impatient/profile.lua +++ /dev/null @@ -1,145 +0,0 @@ -local M = {} - -local api = vim.api - -function M.print_profile(profile) - if not profile then - print "Error: profiling was not enabled" - return - end - - local total_resolve = 0 - local total_load = 0 - local name_pad = 0 - local modules = {} - local plugins = {} - - for module, p in pairs(profile) do - p.resolve = p.resolve / 1000000 - p.load = p.load / 1000000 - p.total = p.resolve + p.load - p.module = module:gsub("/", ".") - - local plugin = p.module:match "([^.]+)" - if plugin then - if not plugins[plugin] then - plugins[plugin] = { - module = plugin, - resolve = 0, - load = 0, - total = 0, - } - end - local r = plugins[plugin] - - r.resolve = r.resolve + p.resolve - r.load = r.load + p.load - r.total = r.total + p.total - - if not r.loader then - r.loader = p.loader - elseif r.loader ~= p.loader then - r.loader = "mixed" - end - end - - total_resolve = total_resolve + p.resolve - total_load = total_load + p.load - - if #module > name_pad then - name_pad = #module - end - - modules[#modules + 1] = p - end - - table.sort(modules, function(a, b) - return a.module > b.module - end) - - do - local plugins_a = {} - for _, v in pairs(plugins) do - plugins_a[#plugins_a + 1] = v - end - plugins = plugins_a - end - - table.sort(plugins, function(a, b) - return a.total > b.total - end) - - local lines = {} - local function add(...) - lines[#lines + 1] = string.format(...) - end - - local l = string.rep("─", name_pad + 1) - - add( - "%s┬───────────┬────────────┬────────────┬────────────┐", - l - ) - add("%-" .. name_pad .. "s │ Loader │ Resolve │ Load │ Total │", "") - add( - "%s┼───────────┼────────────┼────────────┼────────────┤", - l - ) - add( - "%-" .. name_pad .. "s │ │ %8.4fms │ %8.4fms │ %8.4fms │", - "Total", - total_resolve, - total_load, - total_resolve + total_load - ) - add( - "%s┴───────────┴────────────┴────────────┴────────────┤", - l - ) - add("%-" .. name_pad .. "s │", "By Plugin") - add( - "%s┬───────────┬────────────┬────────────┬────────────┤", - l - ) - for _, p in ipairs(plugins) do - add( - "%-" .. name_pad .. "s │ %9s │ %8.4fms │ %8.4fms │ %8.4fms │", - p.module, - p.loader, - p.resolve, - p.load, - p.total - ) - end - add( - "%s┴───────────┴────────────┴────────────┴────────────┤", - l - ) - add("%-" .. name_pad .. "s │", "By Module") - add( - "%s┬───────────┬────────────┬────────────┬────────────┤", - l - ) - for _, p in pairs(modules) do - add( - "%-" .. name_pad .. "s │ %9s │ %8.4fms │ %8.4fms │ %8.4fms │", - p.module, - p.loader, - p.resolve, - p.load, - p.total - ) - end - add( - "%s┴───────────┴────────────┴────────────┴────────────┘", - l - ) - - local bufnr = api.nvim_create_buf(false, false) - api.nvim_buf_set_lines(bufnr, 0, 0, false, lines) - api.nvim_buf_set_option(bufnr, "buftype", "nofile") - api.nvim_buf_set_name(bufnr, "Impatient Profile Report") - api.nvim_set_current_buf(bufnr) -end - -return M diff --git a/lua/interface/popup.lua b/lua/interface/popup.lua deleted file mode 100644 index b628125c..00000000 --- a/lua/interface/popup.lua +++ /dev/null @@ -1,62 +0,0 @@ -local Popup = {} - ---- Create a new floating window --- @param config The configuration passed to vim.api.nvim_open_win --- @param win_opts The options registered with vim.api.nvim_win_set_option --- @param buf_opts The options registered with vim.api.nvim_buf_set_option --- @return A new popup -function Popup:new(opts) - opts = opts or {} - opts.layout = opts.layout or {} - opts.win_opts = opts.win_opts or {} - opts.buf_opts = opts.buf_opts or {} - - Popup.__index = Popup - - local editor_layout = { - height = vim.o.lines - vim.o.cmdheight - 2, -- Add margin for status and buffer line - width = vim.o.columns, - } - local popup_layout = { - relative = "editor", - height = math.floor(editor_layout.height * 0.9), - width = math.floor(editor_layout.width * 0.8), - style = "minimal", - border = "rounded", - } - popup_layout.row = math.floor((editor_layout.height - popup_layout.height) / 2) - popup_layout.col = math.floor((editor_layout.width - popup_layout.width) / 2) - - local obj = { - buffer = vim.api.nvim_create_buf(false, true), - layout = vim.tbl_deep_extend("force", popup_layout, opts.layout), - win_opts = opts.win_opts, - buf_opts = opts.buf_opts, - } - - setmetatable(obj, Popup) - - return obj -end - ---- Display the popup with the provided content --- @param content_provider A function accepting the popup's layout and returning the content to display -function Popup:display(content_provider) - self.win_id = vim.api.nvim_open_win(self.buffer, true, self.layout) - vim.lsp.util.close_preview_autocmd({ "BufHidden", "BufLeave" }, self.win_id) - - local lines = content_provider(self.layout) - vim.api.nvim_buf_set_lines(self.bufnr, 0, -1, false, lines) - - -- window options - for key, value in pairs(self.win_opts) do - vim.api.nvim_win_set_option(self.win_id, key, value) - end - - -- buffer options - for key, value in pairs(self.buf_opts) do - vim.api.nvim_buf_set_option(self.buffer, key, value) - end -end - -return Popup diff --git a/lua/interface/text.lua b/lua/interface/text.lua deleted file mode 100644 index 6bf280e8..00000000 --- a/lua/interface/text.lua +++ /dev/null @@ -1,95 +0,0 @@ -local M = {} - -local function max_len_line(lines) - local max_len = 0 - - for _, line in ipairs(lines) do - local line_len = line:len() - if line_len > max_len then - max_len = line_len - end - end - - return max_len -end - ---- Left align lines relatively to the parent container --- @param container The container where lines will be displayed --- @param lines The text to align --- @param alignment The alignment value, range: [0-1] -function M.align_left(container, lines, alignment) - local max_len = max_len_line(lines) - local indent_amount = math.ceil(math.max(container.width - max_len, 0) * alignment) - return M.shift_right(lines, indent_amount) -end - ---- Center align lines relatively to the parent container --- @param container The container where lines will be displayed --- @param lines The text to align --- @param alignment The alignment value, range: [0-1] -function M.align_center(container, lines, alignment) - local output = {} - local max_len = max_len_line(lines) - - for _, line in ipairs(lines) do - local padding = string.rep(" ", (math.max(container.width, max_len) - line:len()) * alignment) - table.insert(output, padding .. line) - end - - return output -end - ---- Shift lines by a given amount --- @params lines The lines the shift --- @param amount The amount of spaces to add -function M.shift_right(lines, amount) - local output = {} - local padding = string.rep(" ", amount) - - for _, line in ipairs(lines) do - table.insert(output, padding .. line) - end - - return output -end - ---- Pretty format tables --- @param entries The table to format --- @param col_count The number of column to span the table on --- @param col_sep The separator between each colummn, default: " " -function M.format_table(entries, col_count, col_sep) - col_sep = col_sep or " " - - local col_rows = math.ceil(vim.tbl_count(entries) / col_count) - local cols = {} - local count = 0 - - for i, entry in ipairs(entries) do - if ((i - 1) % col_rows) == 0 then - table.insert(cols, {}) - count = count + 1 - end - table.insert(cols[count], entry) - end - - local col_max_len = {} - for _, col in ipairs(cols) do - table.insert(col_max_len, max_len_line(col)) - end - - local output = {} - for i, col in ipairs(cols) do - for j, entry in ipairs(col) do - if not output[j] then - output[j] = entry - else - local padding = string.rep(" ", col_max_len[i - 1] - cols[i - 1][j]:len()) - output[j] = output[j] .. padding .. col_sep .. entry - end - end - end - - return output -end - -return M diff --git a/lua/keymappings.lua b/lua/keymappings.lua deleted file mode 100644 index 027ca83f..00000000 --- a/lua/keymappings.lua +++ /dev/null @@ -1,180 +0,0 @@ -local M = {} -local Log = require "core.log" - -local generic_opts_any = { noremap = true, silent = true } - -local generic_opts = { - insert_mode = generic_opts_any, - normal_mode = generic_opts_any, - visual_mode = generic_opts_any, - visual_block_mode = generic_opts_any, - command_mode = generic_opts_any, - term_mode = { silent = true }, -} - -local mode_adapters = { - insert_mode = "i", - normal_mode = "n", - term_mode = "t", - visual_mode = "v", - visual_block_mode = "x", - command_mode = "c", -} - --- Append key mappings to lunarvim's defaults for a given mode --- @param keymaps The table of key mappings containing a list per mode (normal_mode, insert_mode, ..) -function M.append_to_defaults(keymaps) - for mode, mappings in pairs(keymaps) do - for k, v in ipairs(mappings) do - lvim.keys[mode][k] = v - end - end -end - --- Set key mappings individually --- @param mode The keymap mode, can be one of the keys of mode_adapters --- @param key The key of keymap --- @param val Can be form as a mapping or tuple of mapping and user defined opt -function M.set_keymaps(mode, key, val) - local opt = generic_opts[mode] and generic_opts[mode] or generic_opts_any - if type(val) == "table" then - opt = val[2] - val = val[1] - end - vim.api.nvim_set_keymap(mode, key, val, opt) -end - --- Load key mappings for a given mode --- @param mode The keymap mode, can be one of the keys of mode_adapters --- @param keymaps The list of key mappings -function M.load_mode(mode, keymaps) - mode = mode_adapters[mode] and mode_adapters[mode] or mode - for k, v in pairs(keymaps) do - M.set_keymaps(mode, k, v) - end -end - --- Load key mappings for all provided modes --- @param keymaps A list of key mappings for each mode -function M.load(keymaps) - for mode, mapping in pairs(keymaps) do - M.load_mode(mode, mapping) - end -end - -function M.config() - lvim.keys = { - ---@usage change or add keymappings for insert mode - insert_mode = { - -- 'jk' for quitting insert mode - ["jk"] = "", - -- 'kj' for quitting insert mode - ["kj"] = "", - -- 'jj' for quitting insert mode - ["jj"] = "", - -- Move current line / block with Alt-j/k ala vscode. - [""] = ":m .+1==gi", - -- Move current line / block with Alt-j/k ala vscode. - [""] = ":m .-2==gi", - -- navigation - [""] = "k", - [""] = "j", - [""] = "h", - [""] = "l", - -- navigate tab completion with and - -- runs conditionally - [""] = { 'pumvisible() ? "\\" : "\\"', { expr = true, noremap = true } }, - [""] = { 'pumvisible() ? "\\" : "\\"', { expr = true, noremap = true } }, - }, - - ---@usage change or add keymappings for normal mode - normal_mode = { - -- Better window movement - [""] = "h", - [""] = "j", - [""] = "k", - [""] = "l", - - -- Resize with arrows - [""] = ":resize -2", - [""] = ":resize +2", - [""] = ":vertical resize -2", - [""] = ":vertical resize +2", - - -- Tab switch buffer - [""] = ":BufferNext", - [""] = ":BufferPrevious", - - -- Move current line / block with Alt-j/k a la vscode. - [""] = ":m .+1==", - [""] = ":m .-2==", - - -- QuickFix - ["]q"] = ":cnext", - ["[q"] = ":cprev", - [""] = ":call QuickFixToggle()", - }, - - ---@usage change or add keymappings for terminal mode - term_mode = { - -- Terminal window navigation - [""] = "h", - [""] = "j", - [""] = "k", - [""] = "l", - }, - - ---@usage change or add keymappings for visual mode - visual_mode = { - -- Better indenting - ["<"] = ""] = ">gv", - - -- ["p"] = '"0p', - -- ["P"] = '"0P', - }, - - ---@usage change or add keymappings for visual block mode - visual_block_mode = { - -- Move selected line / block of text in visual mode - ["K"] = ":move '<-2gv-gv", - ["J"] = ":move '>+1gv-gv", - - -- Move current line / block with Alt-j/k ala vscode. - [""] = ":m '>+1gv-gv", - [""] = ":m '<-2gv-gv", - }, - - ---@usage change or add keymappings for command mode - command_mode = { - -- navigate tab completion with and - -- runs conditionally - [""] = { 'pumvisible() ? "\\" : "\\"', { expr = true, noremap = true } }, - [""] = { 'pumvisible() ? "\\" : "\\"', { expr = true, noremap = true } }, - }, - } - - if vim.fn.has "mac" == 1 then - lvim.keys.normal_mode[""] = lvim.keys.normal_mode[""] - lvim.keys.normal_mode[""] = lvim.keys.normal_mode[""] - lvim.keys.normal_mode[""] = lvim.keys.normal_mode[""] - lvim.keys.normal_mode[""] = lvim.keys.normal_mode[""] - Log:debug "Activated mac keymappings" - end -end - -function M.print(mode) - print "List of LunarVim's default keymappings (not including which-key)" - if mode then - print(vim.inspect(lvim.keys[mode])) - else - print(vim.inspect(lvim.keys)) - end -end - -function M.setup() - vim.g.mapleader = (lvim.leader == "space" and " ") or lvim.leader - M.load(lvim.keys) -end - -return M diff --git a/lua/lsp/config.lua b/lua/lsp/config.lua deleted file mode 100644 index f13d9659..00000000 --- a/lua/lsp/config.lua +++ /dev/null @@ -1,45 +0,0 @@ -return { - templates_dir = join_paths(get_runtime_dir(), "site", "after", "ftplugin"), - diagnostics = { - signs = { - active = true, - values = { - { name = "LspDiagnosticsSignError", text = "" }, - { name = "LspDiagnosticsSignWarning", text = "" }, - { name = "LspDiagnosticsSignHint", text = "" }, - { name = "LspDiagnosticsSignInformation", text = "" }, - }, - }, - virtual_text = true, - update_in_insert = false, - underline = true, - severity_sort = true, - }, - override = {}, - document_highlight = true, - code_lens_refresh = true, - popup_border = "single", - on_attach_callback = nil, - on_init_callback = nil, - automatic_servers_installation = true, - buffer_mappings = { - normal_mode = { - ["K"] = { "lua vim.lsp.buf.hover()", "Show hover" }, - ["gd"] = { "lua vim.lsp.buf.definition()", "Goto Definition" }, - ["gD"] = { "lua vim.lsp.buf.declaration()", "Goto declaration" }, - ["gr"] = { "lua vim.lsp.buf.references()", "Goto references" }, - ["gI"] = { "lua vim.lsp.buf.implementation()", "Goto Implementation" }, - ["gs"] = { "lua vim.lsp.buf.signature_help()", "show signature help" }, - ["gp"] = { "lua require'lsp.peek'.Peek('definition')", "Peek definition" }, - ["gl"] = { - "lua require'lsp.handlers'.show_line_diagnostics()", - "Show line diagnostics", - }, - }, - insert_mode = {}, - visual_mode = {}, - }, - null_ls = { - setup = {}, - }, -} diff --git a/lua/lsp/handlers.lua b/lua/lsp/handlers.lua deleted file mode 100644 index ffb7564a..00000000 --- a/lua/lsp/handlers.lua +++ /dev/null @@ -1,169 +0,0 @@ --- Set Default Prefix. --- Note: You can set a prefix per lsp server in the lv-globals.lua file -local M = {} - -function M.setup() - local config = { -- your config - virtual_text = lvim.lsp.diagnostics.virtual_text, - signs = lvim.lsp.diagnostics.signs, - underline = lvim.lsp.diagnostics.underline, - update_in_insert = lvim.lsp.diagnostics.update_in_insert, - severity_sort = lvim.lsp.diagnostics.severity_sort, - } - if vim.fn.has "nvim-0.5.1" > 0 then - vim.lsp.handlers["textDocument/publishDiagnostics"] = function(_, result, ctx, _) - local uri = result.uri - local bufnr = vim.uri_to_bufnr(uri) - if not bufnr then - return - end - - local diagnostics = result.diagnostics - local ok, vim_diag = pcall(require, "vim.diagnostic") - if ok then - -- FIX: why can't we just use vim.diagnostic.get(buf_id)? - config.signs = true - for i, diagnostic in ipairs(diagnostics) do - local rng = diagnostic.range - diagnostics[i].lnum = rng["start"].line - diagnostics[i].end_lnum = rng["end"].line - diagnostics[i].col = rng["start"].character - diagnostics[i].end_col = rng["end"].character - end - local namespace = vim.lsp.diagnostic.get_namespace(ctx.client_id) - - vim_diag.set(namespace, bufnr, diagnostics, config) - if not vim.api.nvim_buf_is_loaded(bufnr) then - return - end - - local sign_names = { - "DiagnosticSignError", - "DiagnosticSignWarn", - "DiagnosticSignInfo", - "DiagnosticSignHint", - } - for i, sign in ipairs(lvim.lsp.diagnostics.signs.values) do - vim.fn.sign_define(sign_names[i], { texthl = sign_names[i], text = sign.text, numhl = "" }) - end - vim_diag.show(namespace, bufnr, diagnostics, config) - else - vim.lsp.diagnostic.save(diagnostics, bufnr, ctx.client_id) - if not vim.api.nvim_buf_is_loaded(bufnr) then - return - end - vim.lsp.diagnostic.display(diagnostics, bufnr, ctx.client_id, config) - end - end - else - vim.lsp.handlers["textDocument/publishDiagnostics"] = function(_, _, params, client_id, _) - local uri = params.uri - local bufnr = vim.uri_to_bufnr(uri) - if not bufnr then - return - end - - local diagnostics = params.diagnostics - vim.lsp.diagnostic.save(diagnostics, bufnr, client_id) - if not vim.api.nvim_buf_is_loaded(bufnr) then - return - end - vim.lsp.diagnostic.display(diagnostics, bufnr, client_id, config) - end - end - - vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { - border = lvim.lsp.popup_border, - }) - - vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, { - border = lvim.lsp.popup_border, - }) -end - -local function split_by_chunk(text, chunkSize) - local s = {} - for i = 1, #text, chunkSize do - s[#s + 1] = text:sub(i, i + chunkSize - 1) - end - return s -end - -function M.show_line_diagnostics() - -- TODO: replace all this with vim.diagnostic.show_position_diagnostics() - local diagnostics = vim.lsp.diagnostic.get_line_diagnostics() - local severity_highlight = { - "LspDiagnosticsFloatingError", - "LspDiagnosticsFloatingWarning", - "LspDiagnosticsFloatingInformation", - "LspDiagnosticsFloatingHint", - } - local ok, vim_diag = pcall(require, "vim.diagnostic") - if ok then - local buf_id = vim.api.nvim_win_get_buf(0) - local win_id = vim.api.nvim_get_current_win() - local cursor_position = vim.api.nvim_win_get_cursor(win_id) - severity_highlight = { - "DiagnosticFloatingError", - "DiagnosticFloatingWarn", - "DiagnosticFloatingInfo", - "DiagnosticFloatingHint", - } - diagnostics = vim_diag.get(buf_id, { lnum = cursor_position[1] - 1 }) - end - local lines = {} - local max_width = vim.fn.winwidth(0) - 5 - local height = #diagnostics - local width = 0 - local opts = {} - local close_events = { "CursorMoved", "CursorMovedI", "BufHidden", "InsertCharPre" } - if height == 0 then - return - end - local bufnr = vim.api.nvim_create_buf(false, true) - local diag_message - table.sort(diagnostics, function(a, b) - return a.severity < b.severity - end) - for i, diagnostic in ipairs(diagnostics) do - local source = diagnostic.source - diag_message = diagnostic.message:gsub("[\n\r]", " ") - if source then - if string.find(source, "/") then - source = string.sub(diagnostic.source, string.find(diagnostic.source, "([%w-_]+)$")) - end - diag_message = string.format("%d. %s: %s", i, source, diag_message) - else - diag_message = string.format("%d. %s", i, diag_message) - end - if diagnostic.code then - diag_message = string.format("%s [%s]", diag_message, diagnostic.code) - end - local msgs = split_by_chunk(diag_message, max_width) - for _, diag in ipairs(msgs) do - table.insert(lines, { message = diag, severity = diagnostic.severity }) - width = math.max(diag:len(), width) - end - end - height = #lines - opts = vim.lsp.util.make_floating_popup_options(width, height, opts) - opts["style"] = "minimal" - opts["border"] = "rounded" - opts["focusable"] = true - - vim.api.nvim_buf_set_option(bufnr, "bufhidden", "wipe") - local winnr = vim.api.nvim_open_win(bufnr, false, opts) - vim.api.nvim_win_set_option(winnr, "winblend", 0) - vim.api.nvim_buf_set_var(bufnr, "lsp_floating_window", winnr) - for i, diag in ipairs(lines) do - vim.api.nvim_buf_set_lines(bufnr, i - 1, i - 1, 0, { diag.message }) - vim.api.nvim_buf_add_highlight(bufnr, -1, severity_highlight[diag.severity], i - 1, 0, diag.message:len()) - end - - vim.api.nvim_command( - "autocmd QuitPre ++nested ++once lua pcall(vim.api.nvim_win_close, " .. winnr .. ", true)" - ) - vim.lsp.util.close_preview_autocmd(close_events, winnr) -end - -return M diff --git a/lua/lsp/init.lua b/lua/lsp/init.lua deleted file mode 100644 index 88111005..00000000 --- a/lua/lsp/init.lua +++ /dev/null @@ -1,165 +0,0 @@ -local M = {} -local Log = require "core.log" -local utils = require "utils" - -local function lsp_highlight_document(client) - if lvim.lsp.document_highlight == false then - return -- we don't need further - end - -- Set autocommands conditional on server_capabilities - if client.resolved_capabilities.document_highlight then - vim.api.nvim_exec( - [[ - augroup lsp_document_highlight - autocmd! * - autocmd CursorHold lua vim.lsp.buf.document_highlight() - autocmd CursorMoved lua vim.lsp.buf.clear_references() - augroup END - ]], - false - ) - end -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 - vim.api.nvim_exec( - [[ - augroup lsp_code_lens_refresh - autocmd! * - autocmd InsertLeave lua vim.lsp.codelens.refresh() - autocmd InsertLeave lua vim.lsp.codelens.display() - augroup END - ]], - false - ) - end -end - -local function add_lsp_buffer_keybindings(bufnr) - local mappings = { - normal_mode = "n", - insert_mode = "i", - visual_mode = "v", - } - - if lvim.builtin.which_key.active then - -- Remap using which_key - local status_ok, wk = pcall(require, "which-key") - if not status_ok then - return - end - for mode_name, mode_char in pairs(mappings) do - wk.register(lvim.lsp.buffer_mappings[mode_name], { mode = mode_char, buffer = bufnr }) - end - else - -- Remap using nvim api - for mode_name, mode_char in pairs(mappings) do - for key, remap in pairs(lvim.lsp.buffer_mappings[mode_name]) do - vim.api.nvim_buf_set_keymap(bufnr, mode_char, key, remap[1], { noremap = true, silent = true }) - end - end - end -end - -function M.common_capabilities() - local capabilities = vim.lsp.protocol.make_client_capabilities() - capabilities.textDocument.completion.completionItem.snippetSupport = true - capabilities.textDocument.completion.completionItem.resolveSupport = { - properties = { - "documentation", - "detail", - "additionalTextEdits", - }, - } - - local status_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") - if status_ok then - capabilities = cmp_nvim_lsp.update_capabilities(capabilities) - end - - return capabilities -end - -local function select_default_formater(client) - local client_formatting = client.resolved_capabilities.document_formatting - or client.resolved_capabilities.document_range_formatting - if client.name == "null-ls" or not client_formatting then - return - end - Log:debug("Checking for formatter overriding for " .. client.name) - local client_filetypes = client.config.filetypes or {} - for _, filetype in ipairs(client_filetypes) do - if lvim.lang[filetype] and #vim.tbl_keys(lvim.lang[filetype].formatters) > 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_init(client, bufnr) - if lvim.lsp.on_init_callback then - lvim.lsp.on_init_callback(client, bufnr) - Log:debug "Called lsp.on_init_callback" - return - end - select_default_formater(client) -end - -function M.common_on_attach(client, bufnr) - if lvim.lsp.on_attach_callback then - lvim.lsp.on_attach_callback(client, bufnr) - Log:debug "Called lsp.on_attach_callback" - end - lsp_highlight_document(client) - lsp_code_lens_refresh(client) - add_lsp_buffer_keybindings(bufnr) -end - -local function bootstrap_nlsp(opts) - opts = opts or {} - local lsp_settings_status_ok, lsp_settings = pcall(require, "nlspsettings") - if lsp_settings_status_ok then - lsp_settings.setup(opts) - end -end - -function M.get_common_opts() - return { - on_attach = M.common_on_attach, - on_init = M.common_on_init, - capabilities = M.common_capabilities(), - } -end - -function M.setup() - Log:debug "Setting up LSP support" - - local lsp_status_ok, _ = pcall(require, "lspconfig") - if not lsp_status_ok then - 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 }) - end - - require("lsp.handlers").setup() - - if not utils.is_directory(lvim.lsp.templates_dir) then - require("lsp.templates").generate_templates() - end - - bootstrap_nlsp { config_home = utils.join_paths(get_config_dir(), "lsp-settings") } - - require("lsp.null-ls").setup() - - require("utils").toggle_autoformat() -end - -return M diff --git a/lua/lsp/manager.lua b/lua/lsp/manager.lua deleted file mode 100644 index 9cb81910..00000000 --- a/lua/lsp/manager.lua +++ /dev/null @@ -1,86 +0,0 @@ -local M = {} - -local Log = require "core.log" -local lsp_utils = require "lsp.utils" - -function M.init_defaults(languages) - for _, entry in ipairs(languages) do - if not lvim.lang[entry] then - lvim.lang[entry] = { - formatters = {}, - linters = {}, - lsp = {}, - } - end - end -end - -local function is_overridden(server) - local overrides = lvim.lsp.override - if type(overrides) == "table" then - if vim.tbl_contains(overrides, server) then - return true - end - end -end - ----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/" .. name) - if status_ok then - 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 - ----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 - - 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 - - if server_available and ensure_installed(requested_server) then - requested_server:setup(config) - else - require("lspconfig")[server_name].setup(config) - end -end - -return M diff --git a/lua/lsp/null-ls/formatters.lua b/lua/lsp/null-ls/formatters.lua deleted file mode 100644 index 4728b908..00000000 --- a/lua/lsp/null-ls/formatters.lua +++ /dev/null @@ -1,66 +0,0 @@ -local M = {} - -local null_ls = require "null-ls" -local services = require "lsp.null-ls.services" -local Log = require "core.log" - -function M.list_supported_names(filetype) - local null_ls_methods = require "null-ls.methods" - local formatter_method = null_ls_methods.internal["FORMATTING"] - local registered_providers = services.list_registered_providers_names(filetype) - return registered_providers[formatter_method] or {} -end - -function M.list_available(filetype) - local formatters = {} - local tbl = require "utils.table" - for _, provider in pairs(null_ls.builtins.formatting) do - if tbl.contains(provider.filetypes or {}, function(ft) - return ft == "*" or ft == filetype - end) then - table.insert(formatters, provider.name) - end - end - - return formatters -end - -function M.list_configured(formatter_configs) - local formatters, errors = {}, {} - - for _, fmt_config in ipairs(formatter_configs) do - local formatter_name = fmt_config.exe:gsub("-", "_") - local formatter = null_ls.builtins.formatting[formatter_name] - - if not formatter then - Log:error("Not a valid formatter: " .. fmt_config.exe) - errors[fmt_config.exe] = {} -- Add data here when necessary - else - local formatter_cmd = services.find_command(formatter._opts.command) - if not formatter_cmd then - Log:warn("Not found: " .. formatter._opts.command) - errors[fmt_config.exe] = {} -- Add data here when necessary - else - Log:debug("Using formatter: " .. formatter_cmd) - formatters[fmt_config.exe] = formatter.with { - command = formatter_cmd, - extra_args = fmt_config.args, - filetypes = fmt_config.filetypes, - } - end - end - end - - return { supported = formatters, unsupported = errors } -end - -function M.setup(formatter_configs) - if vim.tbl_isempty(formatter_configs) then - return - end - - local formatters_by_ft = M.list_configured(formatter_configs) - null_ls.register { sources = formatters_by_ft.supported } -end - -return M diff --git a/lua/lsp/null-ls/init.lua b/lua/lsp/null-ls/init.lua deleted file mode 100644 index 0d030c22..00000000 --- a/lua/lsp/null-ls/init.lua +++ /dev/null @@ -1,32 +0,0 @@ -local M = {} - -local Log = require "core.log" -local formatters = require "lsp.null-ls.formatters" -local linters = require "lsp.null-ls.linters" - -function M:setup() - local status_ok, null_ls = pcall(require, "null-ls") - if not status_ok then - Log:error "Missing null-ls dependency" - return - end - - null_ls.config() - require("lspconfig")["null-ls"].setup(lvim.lsp.null_ls.setup) - for filetype, config in pairs(lvim.lang) do - if not vim.tbl_isempty(config.formatters) then - vim.tbl_map(function(c) - c.filetypes = { filetype } - end, config.formatters) - formatters.setup(config.formatters) - end - if not vim.tbl_isempty(config.linters) then - vim.tbl_map(function(c) - c.filetypes = { filetype } - end, config.formatters) - linters.setup(config.linters) - end - end -end - -return M diff --git a/lua/lsp/null-ls/linters.lua b/lua/lsp/null-ls/linters.lua deleted file mode 100644 index 549c6cdd..00000000 --- a/lua/lsp/null-ls/linters.lua +++ /dev/null @@ -1,66 +0,0 @@ -local M = {} - -local null_ls = require "null-ls" -local services = require "lsp.null-ls.services" -local Log = require "core.log" - -function M.list_supported_names(filetype) - local null_ls_methods = require "null-ls.methods" - local linter_method = null_ls_methods.internal["DIAGNOSTICS"] - local registered_providers = services.list_registered_providers_names(filetype) - return registered_providers[linter_method] or {} -end - -function M.list_available(filetype) - local linters = {} - local tbl = require "utils.table" - for _, provider in pairs(null_ls.builtins.diagnostics) do - if tbl.contains(provider.filetypes or {}, function(ft) - return ft == "*" or ft == filetype - end) then - table.insert(linters, provider.name) - end - end - - return linters -end - -function M.list_configured(linter_configs) - local linters, errors = {}, {} - - for _, lnt_config in pairs(linter_configs) do - local linter_name = lnt_config.exe:gsub("-", "_") - local linter = null_ls.builtins.diagnostics[linter_name] - - if not linter then - Log:error("Not a valid linter: " .. lnt_config.exe) - errors[lnt_config.exe] = {} -- Add data here when necessary - else - local linter_cmd = services.find_command(linter._opts.command) - if not linter_cmd then - Log:warn("Not found: " .. linter._opts.command) - errors[lnt_config.exe] = {} -- Add data here when necessary - else - Log:debug("Using linter: " .. linter_cmd) - linters[lnt_config.exe] = linter.with { - command = linter_cmd, - extra_args = lnt_config.args, - filetypes = lnt_config.filetypes, - } - end - end - end - - return { supported = linters, unsupported = errors } -end - -function M.setup(linter_configs) - if vim.tbl_isempty(linter_configs) then - return - end - - local linters = M.list_configured(linter_configs) - null_ls.register { sources = linters.supported } -end - -return M diff --git a/lua/lsp/null-ls/services.lua b/lua/lsp/null-ls/services.lua deleted file mode 100644 index ef9e7d22..00000000 --- a/lua/lsp/null-ls/services.lua +++ /dev/null @@ -1,63 +0,0 @@ -local M = {} - -local function find_root_dir() - local util = require "lspconfig/util" - local lsp_utils = require "lsp.utils" - - local ts_client = lsp_utils.is_client_active "typescript" - if ts_client then - return ts_client.config.root_dir - end - local dirname = vim.fn.expand "%:p:h" - return util.root_pattern "package.json"(dirname) -end - -local function from_node_modules(command) - local root_dir = find_root_dir() - - if not root_dir then - return nil - end - - return root_dir .. "/node_modules/.bin/" .. command -end - -local local_providers = { - prettier = { find = from_node_modules }, - prettierd = { find = from_node_modules }, - prettier_d_slim = { find = from_node_modules }, - eslint_d = { find = from_node_modules }, - eslint = { find = from_node_modules }, - stylelint = { find = from_node_modules }, -} - -function M.find_command(command) - if local_providers[command] then - local local_command = local_providers[command].find(command) - if local_command and vim.fn.executable(local_command) == 1 then - return local_command - end - end - - if vim.fn.executable(command) == 1 then - return command - end - return nil -end - -function M.list_registered_providers_names(filetype) - local u = require "null-ls.utils" - local c = require "null-ls.config" - local registered = {} - for method, source in pairs(c.get()._methods) do - for name, filetypes in pairs(source) do - if u.filetype_matches(filetypes, filetype) then - registered[method] = registered[method] or {} - table.insert(registered[method], name) - end - end - end - return registered -end - -return M diff --git a/lua/lsp/peek.lua b/lua/lsp/peek.lua deleted file mode 100644 index cb00488e..00000000 --- a/lua/lsp/peek.lua +++ /dev/null @@ -1,152 +0,0 @@ -local M = { - floating_buf = nil, - floating_win = nil, - prev_result = nil, -} - -local function create_floating_file(location, opts) - vim.validate { - location = { location, "t" }, - opts = { opts, "t", true }, - } - - -- Set some defaults - opts = opts or {} - local close_events = opts.close_events or { "CursorMoved", "CursorMovedI", "BufHidden", "InsertCharPre" } - - -- location may be LocationLink or Location - local uri = location.targetUri or location.uri - if uri == nil then - return - end - local bufnr = vim.uri_to_bufnr(uri) - if not vim.api.nvim_buf_is_loaded(bufnr) then - vim.fn.bufload(bufnr) - end - - local range = location.targetRange or location.range - - local contents = vim.api.nvim_buf_get_lines( - bufnr, - range.start.line, - math.min(range["end"].line + 1 + (opts.context or 10), range.start.line + (opts.max_height or 15)), -- Don't let the window be more that 15 lines long(height) - false - ) - local width, height = vim.lsp.util._make_floating_popup_size(contents, opts) - opts = vim.lsp.util.make_floating_popup_options(width, height, opts) - -- Don't make it minimal as it is meant to be fully featured - opts["style"] = nil - - vim.api.nvim_buf_set_option(bufnr, "bufhidden", "wipe") - - local winnr = vim.api.nvim_open_win(bufnr, false, opts) - vim.api.nvim_win_set_option(winnr, "winblend", 0) - - vim.api.nvim_win_set_cursor(winnr, { range.start.line + 1, range.start.character }) - vim.api.nvim_buf_set_var(bufnr, "lsp_floating_window", winnr) - - -- Set some autocmds to close the window - vim.api.nvim_command( - "autocmd QuitPre ++nested ++once lua pcall(vim.api.nvim_win_close, " .. winnr .. ", true)" - ) - vim.lsp.util.close_preview_autocmd(close_events, winnr) - - return bufnr, winnr -end - -local function preview_location_callback(result) - if result == nil or vim.tbl_isempty(result) then - return nil - end - - local opts = { - border = "rounded", - context = 10, - } - - if vim.tbl_islist(result) then - M.prev_result = result[1] - M.floating_buf, M.floating_win = create_floating_file(result[1], opts) - else - M.prev_result = result - M.floating_buf, M.floating_win = create_floating_file(result, opts) - end -end - -local function preview_location_callback_old_signature(_, _, result) - return preview_location_callback(result) -end - -local function preview_location_callback_new_signature(_, result) - return preview_location_callback(result) -end - -function M.open_file() - -- Get the file currently open in the floating window - local filepath = vim.fn.expand "%:." - - if not filepath then - print "peek: Unable to open the file!" - return - end - - -- Close the floating window - pcall(vim.api.nvim_win_close, M.floating_win, true) - - -- Edit the file - vim.cmd("edit " .. filepath) - - local winnr = vim.api.nvim_get_current_win() - - -- Set the cursor at the right position - M.set_cursor_to_prev_pos(winnr) -end - -function M.set_cursor_to_prev_pos(winnr) - -- Get position of the thing to peek at - local location = M.prev_result - local range = location.targetRange or location.range - local cursor_pos = { range.start.line + 1, range.start.character } - - -- Set the winnr to the floating window if none was passed in - winnr = winnr or M.floating_win - -- Set the cursor at the correct position in the floating window - vim.api.nvim_win_set_cursor(winnr, cursor_pos) -end - -function M.Peek(what) - -- If a window already exists, focus it at the right position! - if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then - local success_1, _ = pcall(vim.api.nvim_set_current_win, M.floating_win) - if not success_1 then - print "peek: You cannot edit the current file in a preview!" - return - end - - -- Set the cursor at the correct position in the floating window - M.set_cursor_to_prev_pos() - - vim.api.nvim_buf_set_keymap( - M.floating_buf, - "n", - "", - ":lua require('lsp.peek').open_file()", - { noremap = true, silent = true } - ) - else - -- Make a new request and then create the new window in the callback - local params = vim.lsp.util.make_position_params() - local preview_callback = preview_location_callback_old_signature - if vim.fn.has "nvim-0.5.1" > 0 then - preview_callback = preview_location_callback_new_signature - end - local success, _ = pcall(vim.lsp.buf_request, 0, "textDocument/" .. what, params, preview_callback) - if not success then - print( - 'peek: Error calling LSP method "textDocument/' .. what .. '". The current language lsp might not support it.' - ) - end - end -end - -return M diff --git a/lua/lsp/providers/jsonls.lua b/lua/lsp/providers/jsonls.lua deleted file mode 100644 index 1fffa686..00000000 --- a/lua/lsp/providers/jsonls.lua +++ /dev/null @@ -1,197 +0,0 @@ -local default_schemas = nil -local status_ok, jsonls_settings = pcall(require, "nlspsettings.jsonls") -if status_ok then - default_schemas = jsonls_settings.get_default_schemas() -end - -local schemas = { - { - description = "TypeScript compiler configuration file", - fileMatch = { - "tsconfig.json", - "tsconfig.*.json", - }, - url = "https://json.schemastore.org/tsconfig.json", - }, - { - description = "Lerna config", - fileMatch = { "lerna.json" }, - url = "https://json.schemastore.org/lerna.json", - }, - { - description = "Babel configuration", - fileMatch = { - ".babelrc.json", - ".babelrc", - "babel.config.json", - }, - url = "https://json.schemastore.org/babelrc.json", - }, - { - description = "ESLint config", - fileMatch = { - ".eslintrc.json", - ".eslintrc", - }, - url = "https://json.schemastore.org/eslintrc.json", - }, - { - description = "Bucklescript config", - fileMatch = { "bsconfig.json" }, - url = "https://raw.githubusercontent.com/rescript-lang/rescript-compiler/8.2.0/docs/docson/build-schema.json", - }, - { - description = "Prettier config", - fileMatch = { - ".prettierrc", - ".prettierrc.json", - "prettier.config.json", - }, - url = "https://json.schemastore.org/prettierrc", - }, - { - description = "Vercel Now config", - fileMatch = { "now.json" }, - url = "https://json.schemastore.org/now", - }, - { - description = "Stylelint config", - fileMatch = { - ".stylelintrc", - ".stylelintrc.json", - "stylelint.config.json", - }, - url = "https://json.schemastore.org/stylelintrc", - }, - { - description = "A JSON schema for the ASP.NET LaunchSettings.json files", - fileMatch = { "launchsettings.json" }, - url = "https://json.schemastore.org/launchsettings.json", - }, - { - description = "Schema for CMake Presets", - fileMatch = { - "CMakePresets.json", - "CMakeUserPresets.json", - }, - url = "https://raw.githubusercontent.com/Kitware/CMake/master/Help/manual/presets/schema.json", - }, - { - description = "Configuration file as an alternative for configuring your repository in the settings page.", - fileMatch = { - ".codeclimate.json", - }, - url = "https://json.schemastore.org/codeclimate.json", - }, - { - description = "LLVM compilation database", - fileMatch = { - "compile_commands.json", - }, - url = "https://json.schemastore.org/compile-commands.json", - }, - { - description = "Config file for Command Task Runner", - fileMatch = { - "commands.json", - }, - url = "https://json.schemastore.org/commands.json", - }, - { - description = "AWS CloudFormation provides a common language for you to describe and provision all the infrastructure resources in your cloud environment.", - fileMatch = { - "*.cf.json", - "cloudformation.json", - }, - url = "https://raw.githubusercontent.com/awslabs/goformation/v5.2.9/schema/cloudformation.schema.json", - }, - { - description = "The AWS Serverless Application Model (AWS SAM, previously known as Project Flourish) extends AWS CloudFormation to provide a simplified way of defining the Amazon API Gateway APIs, AWS Lambda functions, and Amazon DynamoDB tables needed by your serverless application.", - fileMatch = { - "serverless.template", - "*.sam.json", - "sam.json", - }, - url = "https://raw.githubusercontent.com/awslabs/goformation/v5.2.9/schema/sam.schema.json", - }, - { - description = "Json schema for properties json file for a GitHub Workflow template", - fileMatch = { - ".github/workflow-templates/**.properties.json", - }, - url = "https://json.schemastore.org/github-workflow-template-properties.json", - }, - { - description = "golangci-lint configuration file", - fileMatch = { - ".golangci.toml", - ".golangci.json", - }, - url = "https://json.schemastore.org/golangci-lint.json", - }, - { - description = "JSON schema for the JSON Feed format", - fileMatch = { - "feed.json", - }, - url = "https://json.schemastore.org/feed.json", - versions = { - ["1"] = "https://json.schemastore.org/feed-1.json", - ["1.1"] = "https://json.schemastore.org/feed.json", - }, - }, - { - description = "Packer template JSON configuration", - fileMatch = { - "packer.json", - }, - url = "https://json.schemastore.org/packer.json", - }, - { - description = "NPM configuration file", - fileMatch = { - "package.json", - }, - url = "https://json.schemastore.org/package.json", - }, - { - description = "JSON schema for Visual Studio component configuration files", - fileMatch = { - "*.vsconfig", - }, - url = "https://json.schemastore.org/vsconfig.json", - }, - { - description = "Resume json", - fileMatch = { "resume.json" }, - url = "https://raw.githubusercontent.com/jsonresume/resume-schema/v1.0.0/schema.json", - }, -} - -local function extend(tab1, tab2) - for _, value in ipairs(tab2) do - table.insert(tab1, value) - end - return tab1 -end - -local extended_schemas = extend(schemas, default_schemas) - -local opts = { - settings = { - json = { - schemas = extended_schemas, - }, - }, - setup = { - commands = { - Format = { - function() - vim.lsp.buf.range_formatting({}, { 0, 0 }, { vim.fn.line "$", 0 }) - end, - }, - }, - }, -} - -return opts diff --git a/lua/lsp/providers/sumneko_lua.lua b/lua/lsp/providers/sumneko_lua.lua deleted file mode 100644 index 4fee1fd1..00000000 --- a/lua/lsp/providers/sumneko_lua.lua +++ /dev/null @@ -1,19 +0,0 @@ -local opts = { - settings = { - Lua = { - diagnostics = { - globals = { "vim", "lvim" }, - }, - workspace = { - library = { - [require("utils").join_paths(get_runtime_dir(), "lvim", "lua")] = true, - [vim.fn.expand "$VIMRUNTIME/lua"] = true, - [vim.fn.expand "$VIMRUNTIME/lua/vim/lsp"] = true, - }, - maxPreload = 100000, - preloadFileSize = 10000, - }, - }, - }, -} -return opts diff --git a/lua/lsp/providers/vuels.lua b/lua/lsp/providers/vuels.lua deleted file mode 100644 index 3f44275d..00000000 --- a/lua/lsp/providers/vuels.lua +++ /dev/null @@ -1,26 +0,0 @@ -local opts = { - setup = { - root_dir = function(fname) - local util = require "lspconfig/util" - return util.root_pattern "package.json"(fname) or util.root_pattern "vue.config.js"(fname) or vim.fn.getcwd() - end, - init_options = { - config = { - vetur = { - completion = { - autoImport = true, - tagCasing = "kebab", - useScaffoldSnippets = true, - }, - useWorkspaceDependencies = true, - validation = { - script = true, - style = true, - template = true, - }, - }, - }, - }, - }, -} -return opts diff --git a/lua/lsp/providers/yamlls.lua b/lua/lsp/providers/yamlls.lua deleted file mode 100644 index 156a35b0..00000000 --- a/lua/lsp/providers/yamlls.lua +++ /dev/null @@ -1,30 +0,0 @@ -local opts = { - settings = { - yaml = { - hover = true, - completion = true, - validate = true, - schemaStore = { - enable = true, - url = "https://www.schemastore.org/api/json/catalog.json", - }, - schemas = { - kubernetes = { - "daemon.{yml,yaml}", - "manager.{yml,yaml}", - "restapi.{yml,yaml}", - "role.{yml,yaml}", - "role_binding.{yml,yaml}", - "*onfigma*.{yml,yaml}", - "*ngres*.{yml,yaml}", - "*ecre*.{yml,yaml}", - "*eployment*.{yml,yaml}", - "*ervic*.{yml,yaml}", - "kubectl-edit*.yaml", - }, - }, - }, - }, -} - -return opts diff --git a/lua/lsp/templates.lua b/lua/lsp/templates.lua deleted file mode 100644 index fbbc37f6..00000000 --- a/lua/lsp/templates.lua +++ /dev/null @@ -1,98 +0,0 @@ -local M = {} - -local Log = require "core.log" -local utils = require "utils" -local get_supported_filetypes = require("lsp.utils").get_supported_filetypes - -local ftplugin_dir = lvim.lsp.templates_dir - -local join_paths = _G.join_paths - -function M.remove_template_files() - -- remove any outdated files - for _, file in ipairs(vim.fn.glob(ftplugin_dir .. "/*.lua", 1, 1)) do - vim.fn.delete(file) - end -end - ----Checks if a server is ignored by default because of a conflict ----Only TSServer is enabled by default for the javascript-family ----@param server_name string -function M.is_ignored(server_name, filetypes) - --TODO: this is easy to be made configurable once stable - filetypes = filetypes or get_supported_filetypes(server_name) - - if vim.tbl_contains(filetypes, "javascript") then - if server_name == "tsserver" then - return false - else - return true - end - end - - local blacklist = { - "jedi_language_server", - "pylsp", - "sqlls", - "sqls", - "angularls", - "ansiblels", - } - return vim.tbl_contains(blacklist, server_name) -end - ----Generates an ftplugin file based on the server_name in the selected directory ----@param server_name string name of a valid language server, e.g. pyright, gopls, tsserver, etc. ----@param dir string the full path to the desired directory -function M.generate_ftplugin(server_name, dir) - -- we need to go through lspconfig to get the corresponding filetypes currently - local filetypes = get_supported_filetypes(server_name) or {} - if not filetypes then - return - end - - if M.is_ignored(server_name, filetypes) then - return - end - - -- print("got associated filetypes: " .. vim.inspect(filetypes)) - - for _, filetype in ipairs(filetypes) do - local filename = join_paths(dir, filetype .. ".lua") - local setup_cmd = string.format([[require("lsp.manager").setup(%q)]], server_name) - -- print("using setup_cmd: " .. setup_cmd) - -- overwrite the file completely - utils.write_file(filename, setup_cmd .. "\n", "a") - end -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 -function M.generate_templates(servers_names) - servers_names = servers_names or {} - - 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) - 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") - end - - for _, server in ipairs(servers_names) do - M.generate_ftplugin(server, ftplugin_dir) - end - Log:debug "Templates installation is complete" -end - -return M diff --git a/lua/lsp/utils.lua b/lua/lsp/utils.lua deleted file mode 100644 index 59003406..00000000 --- a/lua/lsp/utils.lua +++ /dev/null @@ -1,62 +0,0 @@ -local M = {} - -local tbl = require "utils.table" - -function M.is_client_active(name) - local clients = vim.lsp.get_active_clients() - return tbl.find_first(clients, function(client) - return client.name == name - end) -end - -function M.get_active_clients_by_ft(filetype) - local matches = {} - local clients = vim.lsp.get_active_clients() - for _, client in pairs(clients) do - local supported_filetypes = client.config.filetypes or {} - if client.name ~= "null-ls" and vim.tbl_contains(supported_filetypes, filetype) then - table.insert(matches, client) - end - end - return matches -end - -function M.get_client_capabilities(client_id) - if not client_id then - local buf_clients = vim.lsp.buf_get_clients() - for _, buf_client in ipairs(buf_clients) do - if buf_client.name ~= "null-ls" then - client_id = buf_client.id - break - end - end - end - if not client_id then - error "Unable to determine client_id" - return - end - - local client = vim.lsp.get_client_by_id(tonumber(client_id)) - - local enabled_caps = {} - for capability, status in pairs(client.resolved_capabilities) do - if status == true then - table.insert(enabled_caps, capability) - end - end - - return enabled_caps -end - -function M.get_supported_filetypes(server_name) - -- print("got filetypes query request for: " .. server_name) - local configs = require "lspconfig/configs" - pcall(require, ("lspconfig/" .. server_name)) - for _, config in pairs(configs) do - if config.name == server_name then - return config.document_config.default_config.filetypes or {} - end - end -end - -return M diff --git a/lua/lualine/themes/onedarker.lua b/lua/lualine/themes/onedarker.lua deleted file mode 100644 index 396657bb..00000000 --- a/lua/lualine/themes/onedarker.lua +++ /dev/null @@ -1,35 +0,0 @@ --- Copyright (c) 2020-2021 shadmansaleh --- MIT license, see LICENSE for more details. --- Credit: Zoltan Dalmadi(lightline) --- LuaFormatter off -local colors = { - blue = "#61afef", - green = "#98c379", - purple = "#c678dd", - red1 = "#e06c75", - red2 = "#be5046", - yellow = "#e5c07b", - orange = "#D19A66", - fg = "#abb2bf", - bg = "#282c34", - gray1 = "#5c6370", - gray2 = "#2c323d", - gray3 = "#3e4452", -} --- LuaFormatter on -return { - normal = { - a = { fg = colors.fg, bg = colors.blue, gui = "bold" }, - b = { fg = colors.fg, bg = colors.bg }, - c = { fg = colors.fg, bg = colors.bg }, - }, - insert = { a = { fg = colors.fg, bg = colors.green, gui = "bold" } }, - visual = { a = { fg = colors.fg, bg = colors.purple, gui = "bold" } }, - command = { a = { fg = colors.fg, bg = colors.yellow, gui = "bold" } }, - replace = { a = { fg = colors.fg, bg = colors.red1, gui = "bold" } }, - inactive = { - a = { fg = colors.gray1, bg = colors.bg, gui = "bold" }, - b = { fg = colors.gray1, bg = colors.bg }, - c = { fg = colors.gray1, bg = colors.bg }, - }, -} diff --git a/lua/lvim/bootstrap.lua b/lua/lvim/bootstrap.lua new file mode 100644 index 00000000..46c044ae --- /dev/null +++ b/lua/lvim/bootstrap.lua @@ -0,0 +1,196 @@ +local M = {} + +package.loaded["lvim.utils.hooks"] = nil +local _, hooks = pcall(require, "lvim.utils.hooks") + +---Join path segments that were passed as input +---@return string +function _G.join_paths(...) + local uv = vim.loop + local path_sep = uv.os_uname().version:match "Windows" and "\\" or "/" + local result = table.concat({ ... }, path_sep) + return result +end + +---Get the full path to `$LUNARVIM_RUNTIME_DIR` +---@return string +function _G.get_runtime_dir() + 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 lvim_runtime_dir +end + +---Get the full path to `$LUNARVIM_CONFIG_DIR` +---@return string +function _G.get_config_dir() + local lvim_config_dir = os.getenv "LUNARVIM_CONFIG_DIR" + if not lvim_config_dir then + return vim.fn.stdpath "config" + end + return lvim_config_dir +end + +---Get the full path to `$LUNARVIM_CACHE_DIR` +---@return string +function _G.get_cache_dir() + local lvim_cache_dir = os.getenv "LUNARVIM_CACHE_DIR" + if not lvim_cache_dir then + return vim.fn.stdpath "cache" + end + 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_install_path() .. " describe --tags") + + if string.match(lvim_full_ver, "%d") == nil then + return nil + end + if type == "short" then + return vim.fn.split(lvim_full_ver, "-")[1] + else + return string.sub(lvim_full_ver, 1, #lvim_full_ver - 1) + end +end + +---Initialize the `&runtimepath` variables and prepare for startup +---@return table +function M:init() + self.runtime_dir = get_runtime_dir() + self.config_dir = get_config_dir() + self.cache_path = get_cache_dir() + 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") + self.packer_cache_path = join_paths(self.config_dir, "plugin", "packer_compiled.lua") + + if os.getenv "LUNARVIM_RUNTIME_DIR" then + vim.opt.rtp:remove(join_paths(vim.fn.stdpath "data", "site")) + vim.opt.rtp:remove(join_paths(vim.fn.stdpath "data", "site", "after")) + vim.opt.rtp:prepend(join_paths(self.runtime_dir, "site")) + vim.opt.rtp:append(join_paths(self.runtime_dir, "site", "after")) + + vim.opt.rtp:remove(vim.fn.stdpath "config") + vim.opt.rtp:remove(join_paths(vim.fn.stdpath "config", "after")) + vim.opt.rtp:prepend(self.config_dir) + vim.opt.rtp:append(join_paths(self.config_dir, "after")) + -- TODO: we need something like this: vim.opt.packpath = vim.opt.rtp + + vim.cmd [[let &packpath = &runtimepath]] + vim.cmd("set spellfile=" .. join_paths(self.config_dir, "spell", "en.utf-8.add")) + end + + vim.fn.mkdir(get_cache_dir(), "p") + + -- FIXME: currently unreliable in unit-tests + if not os.getenv "LVIM_TEST_ENV" then + require("lvim.impatient").setup { + path = vim.fn.stdpath "cache" .. "/lvim_cache", + enable_profiling = true, + } + end + + require("lvim.config"):init { + config_dir = self.config_dir, + } + local config = require "lvim.config" + config:init { + user_config = join_paths(self.config_dir, "config.lua"), + } + + require("lvim.plugin-loader"):init { + package_root = self.pack_dir, + install_path = self.packer_install_dir, + } + + return self +end + +---Update LunarVim +---pulls the latest changes from github and, resets the startup cache +function M:update() + hooks.run_pre_update() + M:update_repo() + hooks.run_post_update() +end + +local function git_cmd(subcmd) + local Job = require "plenary.job" + local Log = require "lvim.core.log" + local args = { "-C", get_install_path() } + vim.list_extend(args, subcmd) + + local stderr = {} + local stdout, ret = Job + :new({ + command = "git", + args = args, + cwd = get_install_path(), + on_stderr = function(_, data) + table.insert(stderr, data) + end, + }) + :sync() + + if not vim.tbl_isempty(stderr) then + Log:debug(stderr) + end + + if not vim.tbl_isempty(stdout) then + Log:debug(stdout) + end + + return ret +end + +---pulls the latest changes from github +function M:update_repo() + local Log = require "lvim.core.log" + local sub_commands = { + fetch = { "fetch" }, + diff = { "diff", "--quiet", "@{upstream}" }, + merge = { "merge", "--ff-only", "--progress" }, + } + Log:info "Checking for updates" + + local ret = git_cmd(sub_commands.fetch) + if ret ~= 0 then + Log:error "Update failed! Check the log for further information" + return + end + + ret = git_cmd(sub_commands.diff) + + if ret == 0 then + Log:info "LunarVim is already up-to-date" + return + end + + ret = git_cmd(sub_commands.merge) + + if ret ~= 0 then + Log:error "Update failed! Please pull the changes manually instead." + return + end +end + +return M diff --git a/lua/lvim/config/defaults.lua b/lua/lvim/config/defaults.lua new file mode 100644 index 00000000..ffbb2e1b --- /dev/null +++ b/lua/lvim/config/defaults.lua @@ -0,0 +1,32 @@ +return { + leader = "space", + colorscheme = "onedarker", + line_wrap_cursor_movement = true, + transparent_window = false, + format_on_save = true, + keys = {}, + + builtin = {}, + + log = { + ---@usage can be { "trace", "debug", "info", "warn", "error", "fatal" }, + level = "warn", + viewer = { + ---@usage this will fallback on "less +F" if not found + cmd = "lnav", + layout_config = { + ---@usage direction = 'vertical' | 'horizontal' | 'window' | 'float', + direction = "horizontal", + open_mapping = "", + size = 40, + float_opts = {}, + }, + }, + }, + plugins = { + -- use config.lua for this not put here + }, + + autocommands = {}, + lang = {}, +} diff --git a/lua/lvim/config/init.lua b/lua/lvim/config/init.lua new file mode 100644 index 00000000..d7877f1e --- /dev/null +++ b/lua/lvim/config/init.lua @@ -0,0 +1,202 @@ +local utils = require "lvim.utils" +local Log = require "lvim.core.log" + +local M = {} + +local user_config_dir = get_config_dir() +local user_config_file = utils.join_paths(user_config_dir, "config.lua") + +-- Fallback config.lua to lv-config.lua +if not utils.is_file(user_config_file) then + local lv_config = utils.join_paths(user_config_dir, "lv-config.lua") + Log:warn(string.format("[%s] not found, falling back to [%s]", user_config_file, lv_config)) + user_config_file = lv_config +end + +function M:get_user_config_path() + return user_config_file +end + +--- Initialize lvim default configuration +-- Define lvim global variable +function M:init() + if vim.tbl_isempty(lvim or {}) then + lvim = require "lvim.config.defaults" + local home_dir = vim.loop.os_homedir() + lvim.vsnip_dir = utils.join_paths(home_dir, ".config", "snippets") + lvim.database = { save_location = utils.join_paths(home_dir, ".config", "lunarvim_db"), auto_execute = 1 } + end + + local builtins = require "lvim.core.builtins" + builtins.config { user_config_file = user_config_file } + + local settings = require "lvim.config.settings" + settings.load_options() + + local lvim_lsp_config = require "lvim.lsp.config" + lvim.lsp = vim.deepcopy(lvim_lsp_config) + + local supported_languages = { + "asm", + "bash", + "beancount", + "bibtex", + "bicep", + "c", + "c_sharp", + "clojure", + "cmake", + "comment", + "commonlisp", + "cpp", + "crystal", + "cs", + "css", + "cuda", + "d", + "dart", + "dockerfile", + "dot", + "elixir", + "elm", + "emmet", + "erlang", + "fennel", + "fish", + "fortran", + "gdscript", + "glimmer", + "go", + "gomod", + "graphql", + "haskell", + "hcl", + "heex", + "html", + "java", + "javascript", + "javascriptreact", + "jsdoc", + "json", + "json5", + "jsonc", + "julia", + "kotlin", + "latex", + "ledger", + "less", + "lua", + "markdown", + "nginx", + "nix", + "ocaml", + "ocaml_interface", + "perl", + "php", + "pioasm", + "ps1", + "puppet", + "python", + "ql", + "query", + "r", + "regex", + "rst", + "ruby", + "rust", + "scala", + "scss", + "sh", + "solidity", + "sparql", + "sql", + "supercollider", + "surface", + "svelte", + "swift", + "tailwindcss", + "terraform", + "tex", + "tlaplus", + "toml", + "tsx", + "turtle", + "typescript", + "typescriptreact", + "verilog", + "vim", + "vue", + "yaml", + "yang", + "zig", + } + + require("lvim.lsp.manager").init_defaults(supported_languages) +end + +local function deprecation_notice() + local in_headless = #vim.api.nvim_list_uis() == 0 + if in_headless then + return + end + + for lang, entry in pairs(lvim.lang) do + local deprecated_config = entry["lvim.lsp"] or {} + if not vim.tbl_isempty(deprecated_config) then + local msg = string.format( + "Deprecation notice: [lvim.lang.%s.lsp] setting is no longer supported. See https://github.com/LunarVim/LunarVim#breaking-changes", + lang + ) + vim.schedule(function() + vim.notify(msg, vim.log.levels.WARN) + end) + end + end +end + +--- Override the configuration with a user provided one +-- @param config_path The path to the configuration overrides +function M:load(config_path) + config_path = config_path or self.get_user_config_path() + local ok, _ = pcall(dofile, config_path) + if not ok then + Log:warn("Invalid configuration: " .. config_path) + end + + deprecation_notice() + + local autocmds = require "lvim.core.autocmds" + autocmds.define_augroups(lvim.autocommands) + + local settings = require "lvim.config.settings" + settings.load_commands() +end + +--- Override the configuration with a user provided one +-- @param config_path The path to the configuration overrides +function M:reload() + local lvim_modules = {} + for module, _ in pairs(package.loaded) do + if module:match "lvim" then + package.loaded.module = nil + table.insert(lvim_modules, module) + end + end + + M:init() + M:load() + + require("lvim.keymappings").setup() -- this should be done before loading the plugins + local plugins = require "lvim.plugins" + utils.toggle_autoformat() + local plugin_loader = require "lvim.plugin-loader" + plugin_loader:cache_reset() + plugin_loader:load { plugins, lvim.plugins } + vim.cmd ":PackerInstall" + vim.cmd ":PackerCompile" + -- vim.cmd ":PackerClean" + require("lvim.lsp").setup() + Log:info "Reloaded configuration" +end + +return M diff --git a/lua/lvim/config/settings.lua b/lua/lvim/config/settings.lua new file mode 100644 index 00000000..b86e1a18 --- /dev/null +++ b/lua/lvim/config/settings.lua @@ -0,0 +1,76 @@ +local M = {} +local utils = require "lvim.utils" +M.load_options = function() + local default_options = { + backup = false, -- creates a backup file + clipboard = "unnamedplus", -- allows neovim to access the system clipboard + cmdheight = 2, -- more space in the neovim command line for displaying messages + colorcolumn = "99999", -- fixes indentline for now + completeopt = { "menuone", "noselect" }, + conceallevel = 0, -- so that `` is visible in markdown files + fileencoding = "utf-8", -- the encoding written to a file + foldmethod = "manual", -- folding, set to "expr" for treesitter based folding + foldexpr = "", -- set to "nvim_treesitter#foldexpr()" for treesitter based folding + guifont = "monospace:h17", -- the font used in graphical neovim applications + hidden = true, -- required to keep multiple buffers and open multiple buffers + hlsearch = true, -- highlight all matches on previous search pattern + ignorecase = true, -- ignore case in search patterns + mouse = "a", -- allow the mouse to be used in neovim + pumheight = 10, -- pop up menu height + showmode = false, -- we don't need to see things like -- INSERT -- anymore + showtabline = 2, -- always show tabs + smartcase = true, -- smart case + smartindent = true, -- make indenting smarter again + splitbelow = true, -- force all horizontal splits to go below current window + splitright = true, -- force all vertical splits to go to the right of current window + swapfile = false, -- creates a swapfile + termguicolors = true, -- set term gui colors (most terminals support this) + timeoutlen = 100, -- time to wait for a mapped sequence to complete (in milliseconds) + title = true, -- set the title of window to the value of the titlestring + -- opt.titlestring = "%<%F%=%l/%L - nvim" -- what the title of the window will be set to + undodir = utils.join_paths(get_cache_dir(), "undo"), -- set an undo directory + undofile = true, -- enable persistent undo + updatetime = 300, -- faster completion + writebackup = false, -- if a file is being edited by another program (or was written to file while editing with another program), it is not allowed to be edited + expandtab = true, -- convert tabs to spaces + shiftwidth = 2, -- the number of spaces inserted for each indentation + tabstop = 2, -- insert 2 spaces for a tab + cursorline = true, -- highlight the current line + number = true, -- set numbered lines + relativenumber = false, -- set relative numbered lines + numberwidth = 4, -- set number column width to 2 {default 4} + signcolumn = "yes", -- always show the sign column, otherwise it would shift the text each time + wrap = false, -- display lines as one long line + spell = false, + spelllang = "en", + scrolloff = 8, -- is one of my fav + sidescrolloff = 8, + } + + --- SETTINGS --- + + vim.opt.shortmess:append "c" + + for k, v in pairs(default_options) do + vim.opt[k] = v + end +end + +M.load_commands = function() + local cmd = vim.cmd + if lvim.line_wrap_cursor_movement then + cmd "set whichwrap+=<,>,[,],h,l" + end + + if lvim.transparent_window then + cmd "au ColorScheme * hi Normal ctermbg=none guibg=none" + cmd "au ColorScheme * hi SignColumn ctermbg=none guibg=none" + cmd "au ColorScheme * hi NormalNC ctermbg=none guibg=none" + cmd "au ColorScheme * hi MsgArea ctermbg=none guibg=none" + cmd "au ColorScheme * hi TelescopeBorder ctermbg=none guibg=none" + cmd "au ColorScheme * hi NvimTreeNormal ctermbg=none guibg=none" + cmd "let &fcs='eob: '" + end +end + +return M diff --git a/lua/lvim/core/autocmds.lua b/lua/lvim/core/autocmds.lua new file mode 100644 index 00000000..4f29f0e1 --- /dev/null +++ b/lua/lvim/core/autocmds.lua @@ -0,0 +1,129 @@ +local autocommands = {} +local user_config_file = require("lvim.config"):get_user_config_path() + +lvim.autocommands = { + _general_settings = { + { + "Filetype", + "*", + "lua require('lvim.utils.ft').do_filetype(vim.fn.expand(\"\"))", + }, + { + "FileType", + "qf", + "nnoremap q :q", + }, + { + "FileType", + "lsp-installer", + "nnoremap q :q", + }, + { + "TextYankPost", + "*", + "lua require('vim.highlight').on_yank({higroup = 'Search', timeout = 200})", + }, + { + "BufWinEnter", + "*", + "setlocal formatoptions-=c formatoptions-=r formatoptions-=o", + }, + { + "BufWinEnter", + "dashboard", + "setlocal cursorline signcolumn=yes cursorcolumn number", + }, + { + "BufRead", + "*", + "setlocal formatoptions-=c formatoptions-=r formatoptions-=o", + }, + { + "BufNewFile", + "*", + "setlocal formatoptions-=c formatoptions-=r formatoptions-=o", + }, + { "BufWritePost", user_config_file, "lua require('lvim.config'):reload()" }, + { + "FileType", + "qf", + "set nobuflisted", + }, + -- { "VimLeavePre", "*", "set title set titleold=" }, + }, + _filetypechanges = { + { "BufWinEnter", ".tf", "setlocal filetype=terraform" }, + { "BufRead", "*.tf", "setlocal filetype=terraform" }, + { "BufNewFile", "*.tf", "setlocal filetype=terraform" }, + { "BufWinEnter", ".zsh", "setlocal filetype=sh" }, + { "BufRead", "*.zsh", "setlocal filetype=sh" }, + { "BufNewFile", "*.zsh", "setlocal filetype=sh" }, + }, + -- _solidity = { + -- {'BufWinEnter', '.sol', 'setlocal filetype=solidity'}, {'BufRead', '*.sol', 'setlocal filetype=solidity'}, + -- {'BufNewFile', '*.sol', 'setlocal filetype=solidity'} + -- }, + -- _gemini = { + -- {'BufWinEnter', '.gmi', 'setlocal filetype=markdown'}, {'BufRead', '*.gmi', 'setlocal filetype=markdown'}, + -- {'BufNewFile', '*.gmi', 'setlocal filetype=markdown'} + -- }, + _git = { + { "FileType", "gitcommit", "setlocal wrap" }, + { "FileType", "gitcommit", "setlocal spell" }, + }, + _markdown = { + { "FileType", "markdown", "setlocal wrap" }, + { "FileType", "markdown", "setlocal spell" }, + }, + _buffer_bindings = { + { "FileType", "floaterm", "nnoremap q :q" }, + }, + _auto_resize = { + -- will cause split windows to be resized evenly if main window is resized + { "VimResized", "*", "wincmd =" }, + }, + _packer_compile = { + -- will run PackerCompile after writing plugins.lua + { "BufWritePost", "plugins.lua", "PackerCompile" }, + }, + _general_lsp = { + { "FileType", "lspinfo", "nnoremap q :q" }, + }, + + -- _fterm_lazygit = { + -- -- will cause esc key to exit lazy git + -- {"TermEnter", "*", "call LazyGitNativation()"} + -- }, + -- _mode_switching = { + -- -- will switch between absolute and relative line numbers depending on mode + -- {'InsertEnter', '*', 'if &relativenumber | let g:ms_relativenumberoff = 1 | setlocal number norelativenumber | endif'}, + -- {'InsertLeave', '*', 'if exists("g:ms_relativenumberoff") | setlocal relativenumber | endif'}, + -- {'InsertEnter', '*', 'if &cursorline | let g:ms_cursorlineoff = 1 | setlocal nocursorline | endif'}, + -- {'InsertLeave', '*', 'if exists("g:ms_cursorlineoff") | setlocal cursorline | endif'}, + -- }, + custom_groups = {}, +} + +function autocommands.define_augroups(definitions) -- {{{1 + -- Create autocommand groups based on the passed definitions + -- + -- The key will be the name of the group, and each definition + -- within the group should have: + -- 1. Trigger + -- 2. Pattern + -- 3. Text + -- just like how they would normally be defined from Vim itself + for group_name, definition in pairs(definitions) do + vim.cmd("augroup " .. group_name) + vim.cmd "autocmd!" + + for _, def in pairs(definition) do + local command = table.concat(vim.tbl_flatten { "autocmd", def }, " ") + vim.cmd(command) + end + + vim.cmd "augroup END" + end +end + +return autocommands diff --git a/lua/lvim/core/autopairs.lua b/lua/lvim/core/autopairs.lua new file mode 100644 index 00000000..eb080fb1 --- /dev/null +++ b/lua/lvim/core/autopairs.lua @@ -0,0 +1,81 @@ +local M = {} + +function M.config() + lvim.builtin.autopairs = { + active = true, + on_config_done = nil, + ---@usage auto insert after select function or method item + map_complete = true, + ---@usage -- modifies the function or method delimiter by filetypes + map_char = { + all = "(", + tex = "{", + }, + ---@usage check treesitter + check_ts = true, + ts_config = { + lua = { "string" }, + javascript = { "template_string" }, + java = false, + }, + } +end + +M.setup = function() + local autopairs = require "nvim-autopairs" + local Rule = require "nvim-autopairs.rule" + local cond = require "nvim-autopairs.conds" + + autopairs.setup { + check_ts = lvim.builtin.autopairs.check_ts, + ts_config = lvim.builtin.autopairs.ts_config, + } + + -- vim.g.completion_confirm_key = "" + + autopairs.add_rule(Rule("$$", "$$", "tex")) + autopairs.add_rules { + Rule("$", "$", { "tex", "latex" }) -- don't add a pair if the next character is % + :with_pair(cond.not_after_regex_check "%%") -- don't add a pair if the previous character is xxx + :with_pair(cond.not_before_regex_check("xxx", 3)) -- don't move right when repeat character + :with_move(cond.none()) -- don't delete if the next character is xx + :with_del(cond.not_after_regex_check "xx") -- disable add newline when press + :with_cr(cond.none()), + } + autopairs.add_rules { + Rule("$$", "$$", "tex"):with_pair(function(opts) + print(vim.inspect(opts)) + if opts.line == "aa $$" then + -- don't add pair on that line + return false + end + end), + } + + if package.loaded["cmp"] then + require("nvim-autopairs.completion.cmp").setup { + map_cr = false, + map_complete = lvim.builtin.autopairs.map_complete, + map_char = lvim.builtin.autopairs.map_char, + } + -- we map CR explicitly in cmp.lua but we still need to setup the autopairs CR keymap + vim.api.nvim_set_keymap("i", "", "v:lua.MPairs.autopairs_cr()", { expr = true, noremap = true }) + end + + require("nvim-treesitter.configs").setup { autopairs = { enable = true } } + + local ts_conds = require "nvim-autopairs.ts-conds" + + -- TODO: can these rules be safely added from "config.lua" ? + -- press % => %% is only inside comment or string + autopairs.add_rules { + Rule("%", "%", "lua"):with_pair(ts_conds.is_ts_node { "string", "comment" }), + Rule("$", "$", "lua"):with_pair(ts_conds.is_not_ts_node { "function" }), + } + + if lvim.builtin.autopairs.on_config_done then + lvim.builtin.autopairs.on_config_done(autopairs) + end +end + +return M diff --git a/lua/lvim/core/bufferline.lua b/lua/lvim/core/bufferline.lua new file mode 100644 index 00000000..ae6542d1 --- /dev/null +++ b/lua/lvim/core/bufferline.lua @@ -0,0 +1,25 @@ +local M = {} + +M.config = function() + lvim.builtin.bufferline = { + active = true, + on_config_done = nil, + keymap = { + normal_mode = { + [""] = ":BufferNext", + [""] = ":BufferPrevious", + }, + }, + } +end + +M.setup = function() + local keymap = require "lvim.keymappings" + keymap.append_to_defaults(lvim.builtin.bufferline.keymap) + + if lvim.builtin.bufferline.on_config_done then + lvim.builtin.bufferline.on_config_done() + end +end + +return M diff --git a/lua/lvim/core/builtins/init.lua b/lua/lvim/core/builtins/init.lua new file mode 100644 index 00000000..8f83072e --- /dev/null +++ b/lua/lvim/core/builtins/init.lua @@ -0,0 +1,28 @@ +local M = {} + +local builtins = { + "lvim.keymappings", + "lvim.core.which-key", + "lvim.core.gitsigns", + "lvim.core.cmp", + "lvim.core.dashboard", + "lvim.core.dap", + "lvim.core.terminal", + "lvim.core.telescope", + "lvim.core.treesitter", + "lvim.core.nvimtree", + "lvim.core.project", + "lvim.core.bufferline", + "lvim.core.autopairs", + "lvim.core.comment", + "lvim.core.lualine", +} + +function M.config(config) + for _, builtin_path in ipairs(builtins) do + local builtin = require(builtin_path) + builtin.config(config) + end +end + +return M diff --git a/lua/lvim/core/cmp.lua b/lua/lvim/core/cmp.lua new file mode 100644 index 00000000..ad06a360 --- /dev/null +++ b/lua/lvim/core/cmp.lua @@ -0,0 +1,265 @@ +local M = {} + +local check_backspace = function() + local col = vim.fn.col "." - 1 + return col == 0 or vim.fn.getline("."):sub(col, col):match "%s" +end + +local function T(str) + return vim.api.nvim_replace_termcodes(str, true, true, true) +end + +local is_emmet_active = function() + local clients = vim.lsp.buf_get_clients() + + for _, client in pairs(clients) do + if client.name == "emmet_ls" then + return true + end + end + return false +end + +M.config = function() + local status_cmp_ok, cmp = pcall(require, "cmp") + if not status_cmp_ok then + return + end + local status_luasnip_ok, luasnip = pcall(require, "luasnip") + if not status_luasnip_ok then + return + 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() + -- 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 + end + + local snippet = node.parent.snippet + local exit_node = snippet.insert_nodes[0] + + -- exit early if we're past the exit node + if exit_node then + local exit_pos_end = exit_node.mark:pos_end() + if (pos[1] > exit_pos_end[1]) or (pos[1] == exit_pos_end[1] and pos[2] > exit_pos_end[2]) then + snippet:remove_from_jumplist() + luasnip.session.current_nodes[get_current_buf()] = nil + + return false + end + end + + node = snippet.inner_first:jump_into(1, true) + while node ~= nil and node.next ~= nil and node ~= snippet do + local n_next = node.next + local next_pos = n_next and n_next.mark:pos_begin() + local candidate = n_next ~= snippet and next_pos and (pos[1] < next_pos[1]) + or (pos[1] == next_pos[1] and pos[2] < next_pos[2]) + + -- Past unmarked exit node, exit early + if n_next == nil or n_next == snippet.next then + snippet:remove_from_jumplist() + luasnip.session.current_nodes[get_current_buf()] = nil + + return false + end + + if candidate then + luasnip.session.current_nodes[get_current_buf()] = node + return true + end + + local ok + ok, node = pcall(node.jump_from, node, 1, true) -- no_move until last stop + if not ok then + snippet:remove_from_jumplist() + luasnip.session.current_nodes[get_current_buf()] = nil + + return false + end + end + + -- No candidate, but have an exit node + if exit_node then + -- to jump to the exit node, seek to snippet + luasnip.session.current_nodes[get_current_buf()] = snippet + return true + end + + -- No exit node, exit from snippet + snippet:remove_from_jumplist() + luasnip.session.current_nodes[get_current_buf()] = nil + return false + end + + lvim.builtin.cmp = { + confirm_opts = { + behavior = cmp.ConfirmBehavior.Replace, + select = false, + }, + experimental = { + ghost_text = true, + native_menu = false, + }, + formatting = { + kind_icons = { + Class = " ", + Color = " ", + Constant = "ﲀ ", + Constructor = " ", + Enum = "練", + EnumMember = " ", + Event = " ", + Field = " ", + File = "", + Folder = " ", + Function = " ", + Interface = "ﰮ ", + Keyword = " ", + Method = " ", + Module = " ", + Operator = "", + Property = " ", + Reference = " ", + Snippet = " ", + Struct = " ", + Text = " ", + TypeParameter = " ", + Unit = "塞", + Value = " ", + Variable = " ", + }, + source_names = { + nvim_lsp = "(LSP)", + emoji = "(Emoji)", + path = "(Path)", + calc = "(Calc)", + cmp_tabnine = "(Tabnine)", + vsnip = "(Snippet)", + luasnip = "(Snippet)", + buffer = "(Buffer)", + }, + duplicates = { + buffer = 1, + path = 1, + nvim_lsp = 0, + luasnip = 1, + }, + duplicates_default = 0, + format = function(entry, vim_item) + vim_item.kind = lvim.builtin.cmp.formatting.kind_icons[vim_item.kind] + 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 + return vim_item + end, + }, + snippet = { + expand = function(args) + require("luasnip").lsp_expand(args.body) + end, + }, + documentation = { + border = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, + }, + sources = { + { name = "nvim_lsp" }, + { name = "path" }, + { name = "luasnip" }, + { name = "cmp_tabnine" }, + { name = "nvim_lua" }, + { name = "buffer" }, + { name = "calc" }, + { name = "emoji" }, + { name = "treesitter" }, + { name = "crates" }, + }, + mapping = { + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + -- TODO: potentially fix emmet nonsense + [""] = cmp.mapping(function() + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expandable() then + luasnip.expand() + elseif inside_snippet() and seek_luasnip_cursor_node() and luasnip.jumpable() then + luasnip.jump(1) + elseif check_backspace() then + vim.fn.feedkeys(T "", "n") + elseif is_emmet_active() then + return vim.fn["cmp#complete"]() + else + vim.fn.feedkeys(T "", "n") + end + end, { + "i", + "s", + }), + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif inside_snippet() and luasnip.jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, { + "i", + "s", + }), + + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.close(), + [""] = cmp.mapping(function(fallback) + if cmp.visible() and cmp.confirm(lvim.builtin.cmp.confirm_opts) then + return + end + + if inside_snippet() and seek_luasnip_cursor_node() and luasnip.jumpable() then + if not luasnip.jump(1) then + fallback() + end + else + fallback() + end + end), + }, + } +end + +M.setup = function() + require("luasnip/loaders/from_vscode").lazy_load() + require("cmp").setup(lvim.builtin.cmp) +end + +return M diff --git a/lua/lvim/core/commands.lua b/lua/lvim/core/commands.lua new file mode 100644 index 00000000..b750f12b --- /dev/null +++ b/lua/lvim/core/commands.lua @@ -0,0 +1,25 @@ +local M = {} + +M.defaults = { + [[ + function! QuickFixToggle() + if empty(filter(getwininfo(), 'v:val.quickfix')) + copen + else + cclose + endif + endfunction + ]], + -- :LvimInfo + [[ command! LvimInfo lua require('lvim.core.info').toggle_popup(vim.bo.filetype) ]], + [[ command! LvimCacheReset lua require('lvim.utils.hooks').reset_cache() ]], + [[ command! LvimUpdate lua require('lvim.bootstrap').update() ]], +} + +M.load = function(commands) + for _, command in ipairs(commands) do + vim.cmd(command) + end +end + +return M diff --git a/lua/lvim/core/comment.lua b/lua/lvim/core/comment.lua new file mode 100644 index 00000000..b98410ab --- /dev/null +++ b/lua/lvim/core/comment.lua @@ -0,0 +1,31 @@ +local M = {} + +function M.config() + lvim.builtin.comment = { + active = true, + on_config_done = nil, + -- Linters prefer comment and line to have a space in between markers + marker_padding = true, + -- should comment out empty or whitespace only lines + comment_empty = false, + -- Should key mappings be created + create_mappings = true, + -- Normal mode mapping left hand side + line_mapping = "gcc", + -- Visual/Operator mapping left hand side + operator_mapping = "gc", + -- Hook function to call before commenting takes place + hook = nil, + } +end + +function M.setup() + local nvim_comment = require "nvim_comment" + + nvim_comment.setup(lvim.builtin.comment) + if lvim.builtin.comment.on_config_done then + lvim.builtin.comment.on_config_done(nvim_comment) + end +end + +return M diff --git a/lua/lvim/core/dap.lua b/lua/lvim/core/dap.lua new file mode 100644 index 00000000..d9b59641 --- /dev/null +++ b/lua/lvim/core/dap.lua @@ -0,0 +1,76 @@ +local M = {} + +M.config = function() + lvim.builtin.dap = { + active = false, + on_config_done = nil, + breakpoint = { + text = "", + texthl = "LspDiagnosticsSignError", + linehl = "", + numhl = "", + }, + breakpoint_rejected = { + text = "", + texthl = "LspDiagnosticsSignHint", + linehl = "", + numhl = "", + }, + stopped = { + text = "", + texthl = "LspDiagnosticsSignInformation", + linehl = "DiagnosticUnderlineInfo", + numhl = "LspDiagnosticsSignInformation", + }, + } +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) + + dap.defaults.fallback.terminal_win_cmd = "50vsplit new" + + lvim.builtin.which_key.mappings["d"] = { + name = "Debug", + t = { "lua require'dap'.toggle_breakpoint()", "Toggle Breakpoint" }, + b = { "lua require'dap'.step_back()", "Step Back" }, + c = { "lua require'dap'.continue()", "Continue" }, + C = { "lua require'dap'.run_to_cursor()", "Run To Cursor" }, + d = { "lua require'dap'.disconnect()", "Disconnect" }, + g = { "lua require'dap'.session()", "Get Session" }, + i = { "lua require'dap'.step_into()", "Step Into" }, + o = { "lua require'dap'.step_over()", "Step Over" }, + u = { "lua require'dap'.step_out()", "Step Out" }, + p = { "lua require'dap'.pause.toggle()", "Pause" }, + r = { "lua require'dap'.repl.toggle()", "Toggle Repl" }, + s = { "lua require'dap'.continue()", "Start" }, + q = { "lua require'dap'.close()", "Quit" }, + } + + if lvim.builtin.dap.on_config_done then + lvim.builtin.dap.on_config_done(dap) + end +end + +-- TODO put this up there ^^^ call in ftplugin + +-- M.dap = function() +-- if lvim.plugin.dap.active then +-- local dap_install = require "dap-install" +-- dap_install.config("python_dbg", {}) +-- end +-- end +-- +-- M.dap = function() +-- -- gem install readapt ruby-debug-ide +-- if lvim.plugin.dap.active then +-- local dap_install = require "dap-install" +-- dap_install.config("ruby_vsc_dbg", {}) +-- end +-- end + +return M diff --git a/lua/lvim/core/dashboard.lua b/lua/lvim/core/dashboard.lua new file mode 100644 index 00000000..38d9d226 --- /dev/null +++ b/lua/lvim/core/dashboard.lua @@ -0,0 +1,112 @@ +local M = {} +local utils = require "lvim.utils" + +M.config = function(config) + lvim.builtin.dashboard = { + active = false, + on_config_done = nil, + search_handler = "telescope", + disable_at_vim_enter = 0, + session_directory = utils.join_paths(get_cache_dir(), "sessions"), + custom_header = { + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⣶⣾⠿⠿⠟⠛⠛⠛⠛⠿⠿⣿⣷⣤⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + " ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣾⡿⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠿⣷⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣤⡿⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⢿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠒⠂⠉⠉⠉⠉⢩⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠸⡀⠀⠀⠀⠀⠀⢰⣿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⠠⡀⠀⠀⢀⣾⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢⢀⣸⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡧⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡇⠀⠈⠁⠒⠤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣇⠀⠀⠀⠀⠀⠀⠉⠢⠤⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⡟⠈⠑⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠑⠒⠤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⡇⠀⠀⢀⣣⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠀⠀⠒⠢⠤⠄⣀⣀⠀⠀⠀⢠⣿⡟⠀⠀⠀⣺⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⣿⠇⠀⠀⠀⠀⠀⣤⡄⠀⠀⢠⣤⡄⠀⢨⣭⣠⣤⣤⣤⡀⠀⠀⢀⣤⣤⣤⣤⡄⠀⠀⠀⣤⣄⣤⣤⣤⠀⠀⣿⣯⠉⠉⣿⡟⠀⠈⢩⣭⣤⣤⠀⠀⠀⠀⣠⣤⣤⣤⣄⣤⣤", + "⢠⣿⠀⠀⠀⠀⠀⠀⣿⠃⠀⠀⣸⣿⠁⠀⣿⣿⠉⠀⠈⣿⡇⠀⠀⠛⠋⠀⠀⢹⣿⠀⠀⠀⣿⠏⠀⠸⠿⠃⠀⣿⣿⠀⣰⡟⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⣿⡟⢸⣿⡇⢀⣿", + "⣸⡇⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⣿⡟⠀⢠⣿⡇⠀⠀⢰⣿⡇⠀⣰⣾⠟⠛⠛⣻⡇⠀⠀⢸⡿⠀⠀⠀⠀⠀⠀⢻⣿⢰⣿⠀⠀⠀⠀⠀⠀⣾⡇⠀⠀⠀⢸⣿⠇⢸⣿⠀⢸⡏", + "⣿⣧⣤⣤⣤⡄⠀⠘⣿⣤⣤⡤⣿⠇⠀⢸⣿⠁⠀⠀⣼⣿⠀⠀⢿⣿⣤⣤⠔⣿⠃⠀⠀⣾⡇⠀⠀⠀⠀⠀⠀⢸⣿⣿⠋⠀⠀⠀⢠⣤⣤⣿⣥⣤⡄⠀⣼⣿⠀⣸⡏⠀⣿⠃", + "⠉⠉⠉⠉⠉⠁⠀⠀⠈⠉⠉⠀⠉⠀⠀⠈⠉⠀⠀⠀⠉⠉⠀⠀⠀⠉⠉⠁⠈⠉⠀⠀⠀⠉⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠀⠀⠀⠀⠈⠉⠉⠉⠉⠉⠁⠀⠉⠁⠀⠉⠁⠀⠉⠀", + }, + + custom_section = { + a = { + description = { " Find File " }, + command = "Telescope find_files", + }, + b = { + description = { " Recent Projects " }, + command = "Telescope projects", + }, + c = { + description = { " Recently Used Files" }, + command = "Telescope oldfiles", + }, + d = { + description = { " Find Word " }, + command = "Telescope live_grep", + }, + e = { + description = { " Configuration " }, + command = ":e " .. config.user_config_file, + }, + }, + + footer = { "lunarvim.org" }, + } +end + +M.setup = function() + vim.g.dashboard_disable_at_vimenter = lvim.builtin.dashboard.disable_at_vim_enter + + vim.g.dashboard_custom_header = lvim.builtin.dashboard.custom_header + + vim.g.dashboard_default_executive = lvim.builtin.dashboard.search_handler + + vim.g.dashboard_custom_section = lvim.builtin.dashboard.custom_section + + lvim.builtin.which_key.mappings[";"] = { "Dashboard", "Dashboard" } + + vim.g.dashboard_session_directory = lvim.builtin.dashboard.session_directory + + local lvim_site = "lunarvim.org" + local lvim_version = get_version "short" + local num_plugins_loaded = #vim.fn.globpath(get_runtime_dir() .. "/site/pack/packer/start", "*", 0, 1) + + local footer = { + "LunarVim loaded " .. num_plugins_loaded .. " plugins ", + "", + lvim_site, + } + + if lvim_version then + table.insert(footer, 2, "") + table.insert(footer, 3, "v" .. lvim_version) + end + + local text = require "lvim.interface.text" + vim.g.dashboard_custom_footer = text.align_center({ width = 0 }, footer, 0.49) -- Use 0.49 as  counts for 2 characters + + require("lvim.core.autocmds").define_augroups { + _dashboard = { + -- seems to be nobuflisted that makes my stuff disappear will do more testing + { + "FileType", + "dashboard", + "setlocal nocursorline noswapfile synmaxcol& signcolumn=no norelativenumber nocursorcolumn nospell nolist nonumber bufhidden=wipe colorcolumn= foldcolumn=0 matchpairs= ", + }, + { + "FileType", + "dashboard", + "set showtabline=0 | autocmd BufLeave set showtabline=" .. vim.opt.showtabline._value, + }, + { "FileType", "dashboard", "nnoremap q :q" }, + }, + } + + if lvim.builtin.dashboard.on_config_done then + lvim.builtin.dashboard.on_config_done() + end +end + +return M diff --git a/lua/lvim/core/gitsigns.lua b/lua/lvim/core/gitsigns.lua new file mode 100644 index 00000000..cc6387dc --- /dev/null +++ b/lua/lvim/core/gitsigns.lua @@ -0,0 +1,64 @@ +local M = {} + +M.config = function() + lvim.builtin.gitsigns = { + active = true, + on_config_done = nil, + opts = { + signs = { + add = { + hl = "GitSignsAdd", + text = "▎", + numhl = "GitSignsAddNr", + linehl = "GitSignsAddLn", + }, + change = { + hl = "GitSignsChange", + text = "▎", + numhl = "GitSignsChangeNr", + linehl = "GitSignsChangeLn", + }, + delete = { + hl = "GitSignsDelete", + text = "契", + numhl = "GitSignsDeleteNr", + linehl = "GitSignsDeleteLn", + }, + topdelete = { + hl = "GitSignsDelete", + text = "契", + numhl = "GitSignsDeleteNr", + linehl = "GitSignsDeleteLn", + }, + changedelete = { + hl = "GitSignsChange", + text = "▎", + numhl = "GitSignsChangeNr", + linehl = "GitSignsChangeLn", + }, + }, + numhl = false, + linehl = false, + keymaps = { + -- Default keymap options + noremap = true, + buffer = true, + }, + watch_gitdir = { interval = 1000 }, + sign_priority = 6, + update_debounce = 200, + status_formatter = nil, -- Use default + }, + } +end + +M.setup = function() + local gitsigns = require "gitsigns" + + gitsigns.setup(lvim.builtin.gitsigns.opts) + if lvim.builtin.gitsigns.on_config_done then + lvim.builtin.gitsigns.on_config_done(gitsigns) + end +end + +return M diff --git a/lua/lvim/core/info.lua b/lua/lvim/core/info.lua new file mode 100644 index 00000000..7fdb665b --- /dev/null +++ b/lua/lvim/core/info.lua @@ -0,0 +1,174 @@ +local M = { + banner = { + "", + [[ __ _ ___ ]], + [[ / / __ ______ ____ _____| | / (_)___ ___ ]], + [[ / / / / / / __ \/ __ `/ ___/ | / / / __ `__ \]], + [[ / /___/ /_/ / / / / /_/ / / | |/ / / / / / / /]], + [[/_____/\__,_/_/ /_/\__,_/_/ |___/_/_/ /_/ /_/ ]], + }, +} + +local fmt = string.format +local text = require "lvim.interface.text" +local lsp_utils = require "lvim.lsp.utils" +local user_config_file = require("lvim.config"):get_user_config_path() + +local function str_list(list) + return fmt("[ %s ]", table.concat(list, ", ")) +end + +local function get_formatter_suggestion_msg(ft) + local null_formatters = require "lvim.lsp.null-ls.formatters" + local supported_formatters = null_formatters.list_available(ft) + local section = { + " HINT ", + "", + fmt("* List of supported formatters: %s", str_list(supported_formatters)), + } + + if not vim.tbl_isempty(supported_formatters) then + vim.list_extend(section, { + "* Configured formatter needs to be installed and executable.", + fmt("* Enable installed formatter(s) with following config in %s", user_config_file), + "", + fmt(" lvim.lang.%s.formatters = { { exe = '%s' } }", ft, table.concat(supported_formatters, "│")), + }) + end + + return section +end + +local function get_linter_suggestion_msg(ft) + local null_linters = require "lvim.lsp.null-ls.linters" + local supported_linters = null_linters.list_available(ft) + local section = { + " HINT ", + "", + fmt("* List of supported linters: %s", str_list(supported_linters)), + } + + if not vim.tbl_isempty(supported_linters) then + vim.list_extend(section, { + "* Configured linter needs to be installed and executable.", + fmt("* Enable installed linter(s) with following config in %s", user_config_file), + "", + fmt(" lvim.lang.%s.linters = { { exe = '%s' } }", ft, table.concat(supported_linters, "│")), + }) + end + + return section +end + +local function tbl_set_highlight(terms, highlight_group) + for _, v in pairs(terms) do + vim.cmd('let m=matchadd("' .. highlight_group .. '", "' .. v .. "[ ,│']\")") + end +end + +local function make_client_info(client) + local client_enabled_caps = lsp_utils.get_client_capabilities(client.id) + local name = client.name + local id = client.id + local document_formatting = client.resolved_capabilities.document_formatting + local client_info = { + fmt("* Name: %s", name), + fmt("* Id: %s", tostring(id)), + fmt("* Supports formatting: %s", tostring(document_formatting)), + } + if not vim.tbl_isempty(client_enabled_caps) then + local caps_text = "* Capabilities list: " + local caps_text_len = caps_text:len() + local enabled_caps = text.format_table(client_enabled_caps, 3, " | ") + enabled_caps = text.shift_right(enabled_caps, caps_text_len) + enabled_caps[1] = fmt("%s%s", caps_text, enabled_caps[1]:sub(caps_text_len + 1)) + vim.list_extend(client_info, enabled_caps) + end + + return client_info +end + +function M.toggle_popup(ft) + local clients = lsp_utils.get_active_clients_by_ft(ft) + local client_names = {} + + local header = { + fmt("Detected filetype: %s", ft), + fmt("Treesitter active: %s", tostring(next(vim.treesitter.highlighter.active) ~= nil)), + } + + local lsp_info = { + "Language Server Protocol (LSP) info", + fmt "* Associated server(s):", + } + + for _, client in pairs(clients) do + vim.list_extend(lsp_info, make_client_info(client)) + table.insert(client_names, client.name) + end + + local null_formatters = require "lvim.lsp.null-ls.formatters" + local null_linters = require "lvim.lsp.null-ls.linters" + local registered_formatters = null_formatters.list_supported_names(ft) + local registered_linters = null_linters.list_supported_names(ft) + local registered_providers = {} + vim.list_extend(registered_providers, registered_formatters) + vim.list_extend(registered_providers, registered_linters) + local registered_count = vim.tbl_count(registered_providers) + local null_ls_info = { + "Formatters and linters", + fmt( + "* Configured providers: %s%s", + table.concat(registered_providers, "  , "), + registered_count > 0 and "  " or "" + ), + } + + local content_provider = function(popup) + local content = {} + + for _, section in ipairs { + M.banner, + { "" }, + { "" }, + header, + { "" }, + lsp_info, + { "" }, + null_ls_info, + { "" }, + { "" }, + get_formatter_suggestion_msg(ft), + { "" }, + { "" }, + get_linter_suggestion_msg(ft), + } do + vim.list_extend(content, section) + end + + return text.align_left(popup, content, 0.5) + end + + local function set_syntax_hl() + vim.cmd [[highlight LvimInfoIdentifier gui=bold]] + vim.cmd [[highlight link LvimInfoHeader Type]] + vim.cmd [[let m=matchadd("LvimInfoHeader", "Language Server Protocol (LSP) info")]] + vim.cmd [[let m=matchadd("LvimInfoHeader", "Formatters and linters")]] + vim.cmd('let m=matchadd("LvimInfoIdentifier", " ' .. ft .. '$")') + vim.cmd 'let m=matchadd("string", "true")' + vim.cmd 'let m=matchadd("error", "false")' + tbl_set_highlight(registered_providers, "LvimInfoIdentifier") + -- tbl_set_highlight(require("lvim.lsp.null-ls.formatters").list_available(ft), "LvimInfoIdentifier") + -- tbl_set_highlight(require("lvim.lsp.null-ls.linters").list_available(ft), "LvimInfoIdentifier") + end + + local Popup = require("lvim.interface.popup"):new { + win_opts = { number = false }, + buf_opts = { modifiable = false, filetype = "lspinfo" }, + } + Popup:display(content_provider) + set_syntax_hl() + + return Popup +end +return M diff --git a/lua/lvim/core/log.lua b/lua/lvim/core/log.lua new file mode 100644 index 00000000..fca1fcb4 --- /dev/null +++ b/lua/lvim/core/log.lua @@ -0,0 +1,60 @@ +local Log = {} + +--- Adds a log entry using Plenary.log +---@param msg any +---@param level string [same as vim.log.log_levels] +function Log:add_entry(msg, level) + assert(type(level) == "string") + if self.__handle then + -- plenary uses lower-case log levels + self.__handle[level:lower()](msg) + return + end + local status_ok, plenary = pcall(require, "plenary") + if status_ok then + local default_opts = { plugin = "lunarvim", level = lvim.log.level } + local handle = plenary.log.new(default_opts) + handle[level:lower()](msg) + self.__handle = handle + end + -- don't do anything if plenary is not available +end + +---Retrieves the path of the logfile +---@return string path of the logfile +function Log:get_path() + return string.format("%s/%s.log", vim.fn.stdpath "cache", "lunarvim") +end + +---Add a log entry at TRACE level +---@param msg any +function Log:trace(msg) + self:add_entry(msg, "TRACE") +end + +---Add a log entry at DEBUG level +---@param msg any +function Log:debug(msg) + self:add_entry(msg, "DEBUG") +end + +---Add a log entry at INFO level +---@param msg any +function Log:info(msg) + self:add_entry(msg, "INFO") +end + +---Add a log entry at WARN level +---@param msg any +function Log:warn(msg) + self:add_entry(msg, "WARN") +end + +---Add a log entry at ERROR level +---@param msg any +function Log:error(msg) + self:add_entry(msg, "ERROR") +end + +setmetatable({}, Log) +return Log diff --git a/lua/lvim/core/lualine/colors.lua b/lua/lvim/core/lualine/colors.lua new file mode 100644 index 00000000..4984cd1f --- /dev/null +++ b/lua/lvim/core/lualine/colors.lua @@ -0,0 +1,16 @@ +local colors = { + bg = "#202328", + fg = "#bbc2cf", + yellow = "#ECBE7B", + cyan = "#008080", + darkblue = "#081633", + green = "#98be65", + orange = "#FF8800", + violet = "#a9a1e1", + magenta = "#c678dd", + purple = "#c678dd", + blue = "#51afef", + red = "#ec5f67", +} + +return colors diff --git a/lua/lvim/core/lualine/components.lua b/lua/lvim/core/lualine/components.lua new file mode 100644 index 00000000..5c0fb84b --- /dev/null +++ b/lua/lvim/core/lualine/components.lua @@ -0,0 +1,154 @@ +local conditions = require "lvim.core.lualine.conditions" +local colors = require "lvim.core.lualine.colors" + +local function diff_source() + local gitsigns = vim.b.gitsigns_status_dict + if gitsigns then + return { + added = gitsigns.added, + modified = gitsigns.changed, + removed = gitsigns.removed, + } + end +end + +return { + mode = { + function() + return " " + end, + padding = { left = 0, right = 0 }, + color = {}, + cond = nil, + }, + branch = { + "b:gitsigns_head", + icon = " ", + color = { gui = "bold" }, + cond = conditions.hide_in_width, + }, + filename = { + "filename", + color = {}, + cond = nil, + }, + diff = { + "diff", + source = diff_source, + symbols = { added = "  ", modified = "柳", removed = " " }, + diff_color = { + added = { fg = colors.green }, + modified = { fg = colors.yellow }, + removed = { fg = colors.red }, + }, + color = {}, + cond = nil, + }, + python_env = { + function() + local utils = require "lvim.core.lualine.utils" + if vim.bo.filetype == "python" then + local venv = os.getenv "CONDA_DEFAULT_ENV" + if venv then + return string.format("  (%s)", utils.env_cleanup(venv)) + end + venv = os.getenv "VIRTUAL_ENV" + if venv then + return string.format("  (%s)", utils.env_cleanup(venv)) + end + return "" + end + return "" + end, + color = { fg = colors.green }, + cond = conditions.hide_in_width, + }, + diagnostics = { + "diagnostics", + sources = { "nvim_lsp" }, + symbols = { error = " ", warn = " ", info = " ", hint = " " }, + color = {}, + cond = conditions.hide_in_width, + }, + treesitter = { + function() + local b = vim.api.nvim_get_current_buf() + if next(vim.treesitter.highlighter.active[b]) then + return "  " + end + return "" + end, + color = { fg = colors.green }, + cond = conditions.hide_in_width, + }, + lsp = { + function(msg) + msg = msg or "LS Inactive" + local buf_clients = vim.lsp.buf_get_clients() + if next(buf_clients) == nil then + -- TODO: clean up this if statement + if type(msg) == "boolean" or #msg == 0 then + return "LS Inactive" + end + return msg + end + local buf_ft = vim.bo.filetype + local buf_client_names = {} + + -- add client + for _, client in pairs(buf_clients) do + if client.name ~= "null-ls" then + table.insert(buf_client_names, client.name) + end + end + + -- add formatter + local formatters = require "lvim.lsp.null-ls.formatters" + local supported_formatters = formatters.list_supported_names(buf_ft) + vim.list_extend(buf_client_names, supported_formatters) + + -- add linter + local linters = require "lvim.lsp.null-ls.linters" + local supported_linters = linters.list_supported_names(buf_ft) + vim.list_extend(buf_client_names, supported_linters) + + return table.concat(buf_client_names, ", ") + end, + icon = " ", + color = { gui = "bold" }, + cond = conditions.hide_in_width, + }, + location = { "location", cond = conditions.hide_in_width, color = {} }, + progress = { "progress", cond = conditions.hide_in_width, color = {} }, + spaces = { + function() + local label = "Spaces: " + if not vim.api.nvim_buf_get_option(0, "expandtab") then + label = "Tab size: " + end + return label .. vim.api.nvim_buf_get_option(0, "shiftwidth") .. " " + end, + cond = conditions.hide_in_width, + color = {}, + }, + encoding = { + "o:encoding", + fmt = string.upper, + color = {}, + cond = conditions.hide_in_width, + }, + filetype = { "filetype", cond = conditions.hide_in_width, color = {} }, + scrollbar = { + function() + local current_line = vim.fn.line "." + local total_lines = vim.fn.line "$" + local chars = { "__", "▁▁", "▂▂", "▃▃", "▄▄", "▅▅", "▆▆", "▇▇", "██" } + local line_ratio = current_line / total_lines + local index = math.ceil(line_ratio * #chars) + return chars[index] + end, + padding = { left = 0, right = 0 }, + color = { fg = colors.yellow, bg = colors.bg }, + cond = nil, + }, +} diff --git a/lua/lvim/core/lualine/conditions.lua b/lua/lvim/core/lualine/conditions.lua new file mode 100644 index 00000000..3ee4fbb8 --- /dev/null +++ b/lua/lvim/core/lualine/conditions.lua @@ -0,0 +1,17 @@ +local window_width_limit = 80 + +local conditions = { + buffer_not_empty = function() + return vim.fn.empty(vim.fn.expand "%:t") ~= 1 + end, + hide_in_width = function() + return vim.fn.winwidth(0) > window_width_limit + end, + -- check_git_workspace = function() + -- local filepath = vim.fn.expand "%:p:h" + -- local gitdir = vim.fn.finddir(".git", filepath .. ";") + -- return gitdir and #gitdir > 0 and #gitdir < #filepath + -- end, +} + +return conditions diff --git a/lua/lvim/core/lualine/init.lua b/lua/lvim/core/lualine/init.lua new file mode 100644 index 00000000..c5d024c2 --- /dev/null +++ b/lua/lvim/core/lualine/init.lua @@ -0,0 +1,47 @@ +local M = {} +M.config = function() + lvim.builtin.lualine = { + active = true, + style = "lvim", + options = { + icons_enabled = nil, + component_separators = nil, + section_separators = nil, + theme = nil, + disabled_filetypes = nil, + }, + sections = { + lualine_a = nil, + lualine_b = nil, + lualine_c = nil, + lualine_x = nil, + lualine_y = nil, + lualine_z = nil, + }, + inactive_sections = { + lualine_a = nil, + lualine_b = nil, + lualine_c = nil, + lualine_x = nil, + lualine_y = nil, + lualine_z = nil, + }, + tabline = nil, + extensions = nil, + on_config_done = nil, + } +end + +M.setup = function() + require("lvim.core.lualine.styles").update() + require("lvim.core.lualine.utils").validate_theme() + + local lualine = require "lualine" + lualine.setup(lvim.builtin.lualine) + + if lvim.builtin.lualine.on_config_done then + lvim.builtin.lualine.on_config_done(lualine) + end +end + +return M diff --git a/lua/lvim/core/lualine/styles.lua b/lua/lvim/core/lualine/styles.lua new file mode 100644 index 00000000..0843aead --- /dev/null +++ b/lua/lvim/core/lualine/styles.lua @@ -0,0 +1,137 @@ +local M = {} +local components = require "lvim.core.lualine.components" + +local styles = { + lvim = nil, + default = nil, + none = nil, +} + +styles.none = { + style = "none", + options = { + icons_enabled = true, + component_separators = { left = "", right = "" }, + section_separators = { left = "", right = "" }, + disabled_filetypes = {}, + }, + sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = {}, + lualine_x = {}, + lualine_y = {}, + lualine_z = {}, + }, + inactive_sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = {}, + lualine_x = {}, + lualine_y = {}, + lualine_z = {}, + }, + tabline = {}, + extensions = {}, +} + +styles.default = { + style = "default", + options = { + icons_enabled = true, + component_separators = { left = "", right = "" }, + section_separators = { left = "", right = "" }, + disabled_filetypes = {}, + }, + sections = { + lualine_a = { "mode" }, + lualine_b = { "branch" }, + lualine_c = { "filename" }, + lualine_x = { "encoding", "fileformat", "filetype" }, + lualine_y = { "progress" }, + lualine_z = { "location" }, + }, + inactive_sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = { "filename" }, + lualine_x = { "location" }, + lualine_y = {}, + lualine_z = {}, + }, + tabline = {}, + extensions = {}, +} + +styles.lvim = { + style = "lvim", + options = { + icons_enabled = true, + component_separators = { left = "", right = "" }, + section_separators = { left = "", right = "" }, + disabled_filetypes = { "dashboard", "NvimTree", "Outline" }, + }, + sections = { + lualine_a = { + components.mode, + }, + lualine_b = { + components.branch, + components.filename, + }, + lualine_c = { + components.diff, + components.python_env, + }, + lualine_x = { + components.diagnostics, + components.treesitter, + components.lsp, + components.filetype, + }, + lualine_y = {}, + lualine_z = { + components.scrollbar, + }, + }, + inactive_sections = { + lualine_a = { + "filename", + }, + lualine_b = {}, + lualine_c = {}, + lualine_x = {}, + lualine_y = {}, + lualine_z = {}, + }, + tabline = {}, + extensions = { "nvim-tree" }, +} + +function M.get_style(style) + local style_keys = vim.tbl_keys(styles) + if not vim.tbl_contains(style_keys, style) then + local Log = require "lvim.core.log" + Log:error( + "Invalid lualine style", + string.format('"%s"', style), + "options are: ", + string.format('"%s"', table.concat(style_keys, '", "')) + ) + Log:debug '"lvim" style is applied.' + style = "lvim" + end + + return vim.deepcopy(styles[style]) +end + +function M.update() + local style = M.get_style(lvim.builtin.lualine.style) + if lvim.builtin.lualine.options.theme == nil then + lvim.builtin.lualine.options.theme = lvim.colorscheme + end + + lvim.builtin.lualine = vim.tbl_deep_extend("keep", lvim.builtin.lualine, style) +end + +return M diff --git a/lua/lvim/core/lualine/utils.lua b/lua/lvim/core/lualine/utils.lua new file mode 100644 index 00000000..cf80a99e --- /dev/null +++ b/lua/lvim/core/lualine/utils.lua @@ -0,0 +1,27 @@ +local M = {} + +function M.validate_theme() + local theme = lvim.builtin.lualine.options.theme + if type(theme) == "table" then + return + end + + local lualine_loader = require "lualine.utils.loader" + local ok = pcall(lualine_loader.load_theme, theme) + if not ok then + lvim.builtin.lualine.options.theme = "auto" + end +end + +function M.env_cleanup(venv) + if string.find(venv, "/") then + local final_venv = venv + for w in venv:gmatch "([^/]+)" do + final_venv = w + end + venv = final_venv + end + return venv +end + +return M diff --git a/lua/lvim/core/nvimtree.lua b/lua/lvim/core/nvimtree.lua new file mode 100644 index 00000000..d9e6fb5d --- /dev/null +++ b/lua/lvim/core/nvimtree.lua @@ -0,0 +1,141 @@ +local M = {} +local Log = require "lvim.core.log" + +function M.config() + lvim.builtin.nvimtree = { + active = true, + on_config_done = nil, + setup = { + open_on_setup = false, + auto_close = true, + open_on_tab = false, + update_focused_file = { + enable = true, + }, + diagnostics = { + enable = true, + icons = { + hint = "", + info = "", + warning = "", + error = "", + }, + }, + view = { + width = 30, + side = "left", + auto_resize = false, + mappings = { + custom_only = false, + }, + }, + }, + show_icons = { + git = 1, + folders = 1, + files = 1, + folder_arrows = 1, + tree_width = 30, + }, + ignore = { ".git", "node_modules", ".cache" }, + quit_on_open = 0, + hide_dotfiles = 1, + git_hl = 1, + root_folder_modifier = ":t", + allow_resize = 1, + auto_ignore_ft = { "startify", "dashboard" }, + icons = { + default = "", + symlink = "", + git = { + unstaged = "", + staged = "S", + unmerged = "", + renamed = "➜", + deleted = "", + untracked = "U", + ignored = "◌", + }, + folder = { + default = "", + open = "", + empty = "", + empty_open = "", + symlink = "", + }, + }, + } +end + +function M.setup() + local status_ok, nvim_tree_config = pcall(require, "nvim-tree.config") + if not status_ok then + Log:error "Failed to load nvim-tree.config" + return + end + local g = vim.g + + for opt, val in pairs(lvim.builtin.nvimtree) do + g["nvim_tree_" .. opt] = val + end + + -- Implicitly update nvim-tree when project module is active + if lvim.builtin.project.active then + lvim.builtin.nvimtree.respect_buf_cwd = 1 + lvim.builtin.nvimtree.setup.update_cwd = true + lvim.builtin.nvimtree.setup.disable_netrw = false + lvim.builtin.nvimtree.setup.hijack_netrw = false + vim.g.netrw_banner = false + end + + local tree_cb = nvim_tree_config.nvim_tree_callback + + if not lvim.builtin.nvimtree.setup.view.mappings.list then + lvim.builtin.nvimtree.setup.view.mappings.list = { + { key = { "l", "", "o" }, cb = tree_cb "edit" }, + { key = "h", cb = tree_cb "close_node" }, + { key = "v", cb = tree_cb "vsplit" }, + } + end + + lvim.builtin.which_key.mappings["e"] = { "NvimTreeToggle", "Explorer" } + + local tree_view = require "nvim-tree.view" + + -- Add nvim_tree open callback + local open = tree_view.open + tree_view.open = function() + M.on_open() + open() + end + + vim.cmd "au WinClosed * lua require('lvim.core.nvimtree').on_close()" + + if lvim.builtin.nvimtree.on_config_done then + lvim.builtin.nvimtree.on_config_done(nvim_tree_config) + end + require("nvim-tree").setup(lvim.builtin.nvimtree.setup) +end + +function M.on_open() + if package.loaded["bufferline.state"] and lvim.builtin.nvimtree.setup.view.side == "left" then + require("bufferline.state").set_offset(lvim.builtin.nvimtree.setup.view.width + 1, "") + end +end + +function M.on_close() + local buf = tonumber(vim.fn.expand "") + local ft = vim.api.nvim_buf_get_option(buf, "filetype") + if ft == "NvimTree" and package.loaded["bufferline.state"] then + require("bufferline.state").set_offset(0) + end +end + +function M.change_tree_dir(dir) + local lib_status_ok, lib = pcall(require, "nvim-tree.lib") + if lib_status_ok then + lib.change_dir(dir) + end +end + +return M diff --git a/lua/lvim/core/project.lua b/lua/lvim/core/project.lua new file mode 100644 index 00000000..e7527440 --- /dev/null +++ b/lua/lvim/core/project.lua @@ -0,0 +1,51 @@ +local M = {} + +function M.config() + lvim.builtin.project = { + ---@usage set to false to disable project.nvim. + --- This is on by default since it's currently the expected behavior. + active = true, + + on_config_done = nil, + + ---@usage set to true to disable setting the current-woriking directory + --- Manual mode doesn't automatically change your root directory, so you have + --- the option to manually do so using `:ProjectRoot` command. + manual_mode = false, + + ---@usage Methods of detecting the root directory + --- Allowed values: **"lsp"** uses the native neovim lsp + --- **"pattern"** uses vim-rooter like glob pattern matching. Here + --- order matters: if one is not detected, the other is used as fallback. You + --- can also delete or rearangne the detection methods. + detection_methods = { "lsp", "pattern" }, + + ---@usage patterns used to detect root dir, when **"pattern"** is in detection_methods + patterns = { ".git", "_darcs", ".hg", ".bzr", ".svn", "Makefile", "package.json" }, + + ---@ Show hidden files in telescope when searching for files in a project + show_hidden = false, + + ---@usage When set to false, you will get a message when project.nvim changes your directory. + -- When set to false, you will get a message when project.nvim changes your directory. + silent_chdir = true, + + ---@usage list of lsp client names to ignore when using **lsp** detection. eg: { "efm", ... } + ignore_lsp = {}, + + ---@type string + ---@usage path to store the project history for use in telescope + datapath = get_cache_dir(), + } +end + +function M.setup() + local project = require "project_nvim" + + project.setup(lvim.builtin.project) + if lvim.builtin.project.on_config_done then + lvim.builtin.project.on_config_done(project) + end +end + +return M diff --git a/lua/lvim/core/telescope.lua b/lua/lvim/core/telescope.lua new file mode 100644 index 00000000..35f6b4a2 --- /dev/null +++ b/lua/lvim/core/telescope.lua @@ -0,0 +1,193 @@ +local M = {} + +function M.config() + -- Define this minimal config so that it's available if telescope is not yet available. + lvim.builtin.telescope = { + ---@usage disable telescope completely [not recommeded] + active = true, + on_config_done = nil, + } + + local status_ok, actions = pcall(require, "telescope.actions") + if not status_ok then + return + end + + lvim.builtin.telescope = vim.tbl_extend("force", lvim.builtin.telescope, { + defaults = { + prompt_prefix = " ", + selection_caret = " ", + entry_prefix = " ", + initial_mode = "insert", + selection_strategy = "reset", + sorting_strategy = "descending", + layout_strategy = "horizontal", + layout_config = { + width = 0.75, + preview_cutoff = 120, + horizontal = { mirror = false }, + vertical = { mirror = false }, + }, + file_sorter = require("telescope.sorters").get_fzy_sorter, + file_ignore_patterns = {}, + generic_sorter = require("telescope.sorters").get_generic_fuzzy_sorter, + path_display = { shorten = 5 }, + winblend = 0, + border = {}, + borderchars = { "─", "│", "─", "│", "╭", "╮", "╯", "╰" }, + color_devicons = true, + use_less = true, + set_env = { ["COLORTERM"] = "truecolor" }, -- default = nil, + file_previewer = require("telescope.previewers").vim_buffer_cat.new, + grep_previewer = require("telescope.previewers").vim_buffer_vimgrep.new, + qflist_previewer = require("telescope.previewers").vim_buffer_qflist.new, + + -- Developer configurations: Not meant for general override + -- buffer_previewer_maker = require("telescope.previewers").buffer_previewer_maker, + mappings = { + i = { + [""] = actions.move_selection_next, + [""] = actions.move_selection_previous, + [""] = actions.close, + [""] = actions.cycle_history_next, + [""] = actions.cycle_history_prev, + [""] = actions.smart_send_to_qflist + actions.open_qflist, + [""] = actions.select_default + actions.center, + -- To disable a keymap, put [map] = false + -- So, to not map "", just put + -- [""] = trouble.open_with_trouble, + -- [""] = false, + -- [""] = actions.close, + -- Otherwise, just set the mapping to the function that you want it to be. + -- [""] = actions.select_horizontal, + -- Add up multiple actions + -- You can perform as many actions in a row as you like + -- [""] = actions.select_default + actions.center + my_cool_custom_action, + }, + n = { + [""] = actions.move_selection_next, + [""] = actions.move_selection_previous, + [""] = actions.smart_send_to_qflist + actions.open_qflist, + -- [""] = trouble.open_with_trouble, + -- [""] = my_cool_custom_action, + }, + }, + }, + extensions = { + fzy_native = { + override_generic_sorter = false, + override_file_sorter = true, + }, + }, + }) +end + +function M.find_lunarvim_files(opts) + opts = opts or {} + local themes = require "telescope.themes" + local theme_opts = themes.get_ivy { + sorting_strategy = "ascending", + layout_strategy = "bottom_pane", + prompt_prefix = ">> ", + prompt_title = "~ LunarVim files ~", + cwd = get_runtime_dir(), + search_dirs = { get_runtime_dir() .. "/lvim", lvim.lsp.templates_dir }, + } + opts = vim.tbl_deep_extend("force", theme_opts, opts) + require("telescope.builtin").find_files(opts) +end + +function M.grep_lunarvim_files(opts) + opts = opts or {} + local themes = require "telescope.themes" + local theme_opts = themes.get_ivy { + sorting_strategy = "ascending", + layout_strategy = "bottom_pane", + prompt_prefix = ">> ", + prompt_title = "~ search LunarVim ~", + cwd = get_runtime_dir(), + search_dirs = { get_runtime_dir() .. "/lvim", lvim.lsp.templates_dir }, + } + opts = vim.tbl_deep_extend("force", theme_opts, opts) + require("telescope.builtin").live_grep(opts) +end + +function M.view_lunarvim_changelog() + local finders = require "telescope.finders" + local make_entry = require "telescope.make_entry" + local pickers = require "telescope.pickers" + local previewers = require "telescope.previewers" + local actions = require "telescope.actions" + local opts = {} + + local conf = require("telescope.config").values + opts.entry_maker = make_entry.gen_from_git_commits(opts) + + pickers.new(opts, { + prompt_title = "LunarVim changelog", + + finder = finders.new_oneshot_job( + vim.tbl_flatten { + "git", + "log", + "--pretty=oneline", + "--abbrev-commit", + "--", + ".", + }, + opts + ), + previewer = { + previewers.git_commit_diff_to_parent.new(opts), + previewers.git_commit_diff_to_head.new(opts), + previewers.git_commit_diff_as_was.new(opts), + previewers.git_commit_message.new(opts), + }, + + --TODO: consider opening a diff view when pressing enter + attach_mappings = function(_, map) + map("i", "", actions._close) + map("n", "", actions._close) + map("i", "", actions._close) + map("n", "", actions._close) + map("n", "q", actions._close) + return true + end, + sorter = conf.file_sorter(opts), + }):find() +end + +function M.code_actions() + local opts = { + winblend = 15, + layout_config = { + prompt_position = "top", + width = 80, + height = 12, + }, + borderchars = { + prompt = { "─", "│", " ", "│", "╭", "╮", "│", "│" }, + results = { "─", "│", "─", "│", "├", "┤", "╯", "╰" }, + preview = { "─", "│", "─", "│", "╭", "╮", "╯", "╰" }, + }, + border = {}, + previewer = false, + shorten_path = false, + } + require("telescope.builtin").lsp_code_actions(require("telescope.themes").get_dropdown(opts)) +end + +function M.setup() + local telescope = require "telescope" + + telescope.setup(lvim.builtin.telescope) + if lvim.builtin.project.active then + telescope.load_extension "projects" + end + + if lvim.builtin.telescope.on_config_done then + lvim.builtin.telescope.on_config_done(telescope) + end +end + +return M diff --git a/lua/lvim/core/terminal.lua b/lua/lvim/core/terminal.lua new file mode 100644 index 00000000..aa6989ec --- /dev/null +++ b/lua/lvim/core/terminal.lua @@ -0,0 +1,114 @@ +local M = {} +local Log = require "lvim.core.log" + +M.config = function() + lvim.builtin["terminal"] = { + on_config_done = nil, + -- size can be a number or function which is passed the current terminal + size = 20, + -- open_mapping = [[]], + open_mapping = [[]], + hide_numbers = true, -- hide the number column in toggleterm buffers + shade_filetypes = {}, + shade_terminals = true, + shading_factor = 2, -- the degree by which to darken to terminal colour, default: 1 for dark backgrounds, 3 for light + start_in_insert = true, + insert_mappings = true, -- whether or not the open mapping applies in insert mode + persist_size = false, + -- direction = 'vertical' | 'horizontal' | 'window' | 'float', + direction = "float", + close_on_exit = true, -- close the terminal window when the process exits + shell = vim.o.shell, -- change the default shell + -- This field is only relevant if direction is set to 'float' + float_opts = { + -- The border key is *almost* the same as 'nvim_win_open' + -- see :h nvim_win_open for details on borders however + -- the 'curved' border is a custom border type + -- not natively supported but implemented in this plugin. + -- border = 'single' | 'double' | 'shadow' | 'curved' | ... other options supported by win open + border = "curved", + -- width = , + -- height = , + winblend = 0, + highlights = { + border = "Normal", + background = "Normal", + }, + }, + -- Add executables on the config.lua + -- { exec, keymap, name} + -- lvim.builtin.terminal.execs = {{}} to overwrite + -- lvim.builtin.terminal.execs[#lvim.builtin.terminal.execs+1] = {"gdb", "tg", "GNU Debugger"} + execs = { + { "lazygit", "gg", "LazyGit" }, + }, + } +end + +M.setup = function() + local terminal = require "toggleterm" + for _, exec in pairs(lvim.builtin.terminal.execs) do + require("lvim.core.terminal").add_exec(exec[1], exec[2], exec[3]) + end + terminal.setup(lvim.builtin.terminal) + + if lvim.builtin.terminal.on_config_done then + lvim.builtin.terminal.on_config_done(terminal) + end +end + +M.add_exec = function(exec, keymap, name) + vim.api.nvim_set_keymap( + "n", + "" .. keymap, + "lua require('lvim.core.terminal')._exec_toggle('" .. exec .. "')", + { noremap = true, silent = true } + ) + lvim.builtin.which_key.mappings[keymap] = name +end + +M._split = function(inputstr, sep) + if sep == nil then + sep = "%s" + end + local t = {} + for str in string.gmatch(inputstr, "([^" .. sep .. "]+)") do + table.insert(t, str) + end + return t +end + +M._exec_toggle = function(exec) + local binary = M._split(exec)[1] + if vim.fn.executable(binary) ~= 1 then + Log:error("Unable to run executable " .. binary .. ". Please make sure it is installed properly.") + return + end + local Terminal = require("toggleterm.terminal").Terminal + local exec_term = Terminal:new { cmd = exec, hidden = true } + exec_term:toggle() +end + +---Toggles a log viewer according to log.viewer.layout_config +---@param logfile string the fullpath to the logfile +M.toggle_log_view = function(logfile) + local log_viewer = lvim.log.viewer.cmd + if vim.fn.executable(log_viewer) ~= 1 then + log_viewer = "less +F" + end + log_viewer = log_viewer .. " " .. logfile + local term_opts = vim.tbl_deep_extend("force", lvim.builtin.terminal, { + cmd = log_viewer, + open_mapping = lvim.log.viewer.layout_config.open_mapping, + direction = lvim.log.viewer.layout_config.direction, + -- TODO: this might not be working as expected + size = lvim.log.viewer.layout_config.size, + float_opts = lvim.log.viewer.layout_config.float_opts, + }) + + local Terminal = require("toggleterm.terminal").Terminal + local log_view = Terminal:new(term_opts) + log_view:toggle() +end + +return M diff --git a/lua/lvim/core/treesitter.lua b/lua/lvim/core/treesitter.lua new file mode 100644 index 00000000..ce99deba --- /dev/null +++ b/lua/lvim/core/treesitter.lua @@ -0,0 +1,81 @@ +local M = {} +local Log = require "lvim.core.log" + +M.config = function() + lvim.builtin.treesitter = { + on_config_done = nil, + ensure_installed = {}, -- one of "all", "maintained" (parsers with maintainers), or a list of languages + ignore_install = {}, + matchup = { + enable = false, -- mandatory, false will disable the whole extension + -- disable = { "c", "ruby" }, -- optional, list of language that will be disabled + }, + highlight = { + enable = true, -- false will disable the whole extension + additional_vim_regex_highlighting = true, + disable = { "latex" }, + }, + context_commentstring = { + enable = false, + config = { css = "// %s" }, + }, + -- indent = {enable = true, disable = {"python", "html", "javascript"}}, + -- TODO seems to be broken + indent = { enable = true, disable = { "yaml" } }, + autotag = { enable = false }, + textobjects = { + swap = { + enable = false, + -- swap_next = textobj_swap_keymaps, + }, + -- move = textobj_move_keymaps, + select = { + enable = false, + -- keymaps = textobj_sel_keymaps, + }, + }, + textsubjects = { + enable = false, + keymaps = { ["."] = "textsubjects-smart", [";"] = "textsubjects-big" }, + }, + playground = { + enable = false, + disable = {}, + updatetime = 25, -- Debounced time for highlighting nodes in the playground from source code + persist_queries = false, -- Whether the query persists across vim sessions + keybindings = { + toggle_query_editor = "o", + toggle_hl_groups = "i", + toggle_injected_languages = "t", + toggle_anonymous_nodes = "a", + toggle_language_display = "I", + focus_language = "f", + unfocus_language = "F", + update = "R", + goto_node = "", + show_help = "?", + }, + }, + rainbow = { + enable = false, + extended_mode = true, -- Highlight also non-parentheses delimiters, boolean or table: lang -> boolean + max_file_lines = 1000, -- Do not enable for files with more than 1000 lines, int + }, + } +end + +M.setup = function() + local status_ok, treesitter_configs = pcall(require, "nvim-treesitter.configs") + if not status_ok then + Log:get_default().error "Failed to load nvim-treesitter.configs" + return + end + + treesitter_configs.setup(lvim.builtin.treesitter) + + if lvim.builtin.treesitter.on_config_done then + lvim.builtin.treesitter.on_config_done(treesitter_configs) + end +end + +return M diff --git a/lua/lvim/core/which-key.lua b/lua/lvim/core/which-key.lua new file mode 100644 index 00000000..15f63273 --- /dev/null +++ b/lua/lvim/core/which-key.lua @@ -0,0 +1,270 @@ +local M = {} + +M.config = function() + lvim.builtin.which_key = { + ---@usage disable which-key completely [not recommeded] + active = true, + on_config_done = nil, + setup = { + plugins = { + marks = true, -- shows a list of your marks on ' and ` + registers = true, -- shows your registers on " in NORMAL or in INSERT mode + -- the presets plugin, adds help for a bunch of default keybindings in Neovim + -- No actual key bindings are created + presets = { + 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 + 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 + }, + spelling = { enabled = true, suggestions = 20 }, -- use which-key for spelling hints + }, + icons = { + breadcrumb = "»", -- symbol used in the command line area that shows your active key combo + separator = "➜", -- symbol used between a key and it's label + group = "+", -- symbol prepended to a group + }, + 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] + }, + 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 + }, + hidden = { "", "", "", "", "call", "lua", "^:", "^ " }, -- hide mapping boilerplate + show_help = true, -- show help message on the command line when the popup is visible + }, + + opts = { + mode = "n", -- NORMAL mode + prefix = "", + buffer = nil, -- Global mappings. Specify a buffer number for buffer local mappings + silent = true, -- use `silent` when creating keymaps + noremap = true, -- use `noremap` when creating keymaps + nowait = true, -- use `nowait` when creating keymaps + }, + vopts = { + mode = "v", -- VISUAL mode + prefix = "", + buffer = nil, -- Global mappings. Specify a buffer number for buffer local mappings + silent = true, -- use `silent` when creating keymaps + noremap = true, -- use `noremap` when creating keymaps + nowait = true, -- use `nowait` when creating keymaps + }, + -- NOTE: Prefer using : over as the latter avoids going back in normal-mode. + -- see https://neovim.io/doc/user/map.html#:map-cmd + vmappings = { + ["/"] = { ":CommentToggle", "Comment" }, + }, + mappings = { + ["w"] = { "w!", "Save" }, + ["q"] = { "q!", "Quit" }, + ["/"] = { "CommentToggle", "Comment" }, + ["c"] = { "BufferClose!", "Close Buffer" }, + ["f"] = { "Telescope find_files", "Find File" }, + ["h"] = { "nohlsearch", "No Highlight" }, + b = { + name = "Buffers", + j = { "BufferPick", "Jump" }, + f = { "Telescope buffers", "Find" }, + b = { "b#", "Previous" }, + w = { "BufferWipeout", "Wipeout" }, + e = { + "BufferCloseAllButCurrent", + "Close all but current", + }, + h = { "BufferCloseBuffersLeft", "Close all to the left" }, + l = { + "BufferCloseBuffersRight", + "Close all to the right", + }, + D = { + "BufferOrderByDirectory", + "Sort by directory", + }, + L = { + "BufferOrderByLanguage", + "Sort by language", + }, + }, + p = { + name = "Packer", + c = { "PackerCompile", "Compile" }, + i = { "PackerInstall", "Install" }, + r = { "lua require('lvim.utils').reload_lv_config()", "Reload" }, + s = { "PackerSync", "Sync" }, + S = { "PackerStatus", "Status" }, + u = { "PackerUpdate", "Update" }, + }, + + -- " Available Debug Adapters: + -- " https://microsoft.github.io/debug-adapter-protocol/implementors/adapters/ + -- " Adapter configuration and installation instructions: + -- " https://github.com/mfussenegger/nvim-dap/wiki/Debug-Adapter-installation + -- " Debug Adapter protocol: + -- " https://microsoft.github.io/debug-adapter-protocol/ + -- " Debugging + g = { + name = "Git", + j = { "lua require 'gitsigns'.next_hunk()", "Next Hunk" }, + k = { "lua require 'gitsigns'.prev_hunk()", "Prev Hunk" }, + l = { "lua require 'gitsigns'.blame_line()", "Blame" }, + p = { "lua require 'gitsigns'.preview_hunk()", "Preview Hunk" }, + r = { "lua require 'gitsigns'.reset_hunk()", "Reset Hunk" }, + R = { "lua require 'gitsigns'.reset_buffer()", "Reset Buffer" }, + s = { "lua require 'gitsigns'.stage_hunk()", "Stage Hunk" }, + u = { + "lua require 'gitsigns'.undo_stage_hunk()", + "Undo Stage Hunk", + }, + o = { "Telescope git_status", "Open changed file" }, + b = { "Telescope git_branches", "Checkout branch" }, + c = { "Telescope git_commits", "Checkout commit" }, + C = { + "Telescope git_bcommits", + "Checkout commit(for current file)", + }, + d = { + "Gitsigns diffthis HEAD", + "Git Diff", + }, + }, + + l = { + name = "LSP", + a = { "lua require('core.telescope').code_actions()", "Code Action" }, + d = { + "Telescope lsp_document_diagnostics", + "Document Diagnostics", + }, + w = { + "Telescope lsp_workspace_diagnostics", + "Workspace Diagnostics", + }, + f = { "lua vim.lsp.buf.formatting()", "Format" }, + i = { "LspInfo", "Info" }, + I = { "LspInstallInfo", "Installer Info" }, + j = { + "lua vim.lsp.diagnostic.goto_next({popup_opts = {border = lvim.lsp.popup_border}})", + "Next Diagnostic", + }, + k = { + "lua vim.lsp.diagnostic.goto_prev({popup_opts = {border = lvim.lsp.popup_border}})", + "Prev Diagnostic", + }, + l = { "lua vim.lsp.codelens.run()", "CodeLens Action" }, + p = { + name = "Peek", + d = { "lua require('lvim.lsp.peek').Peek('definition')", "Definition" }, + t = { "lua require('lvim.lsp.peek').Peek('typeDefinition')", "Type Definition" }, + i = { "lua require('lvim.lsp.peek').Peek('implementation')", "Implementation" }, + }, + q = { "lua vim.lsp.diagnostic.set_loclist()", "Quickfix" }, + r = { "lua vim.lsp.buf.rename()", "Rename" }, + s = { "Telescope lsp_document_symbols", "Document Symbols" }, + S = { + "Telescope lsp_dynamic_workspace_symbols", + "Workspace Symbols", + }, + }, + L = { + name = "+LunarVim", + c = { + "edit" .. get_config_dir() .. "/config.lua", + "Edit config.lua", + }, + f = { + "lua require('lvim.core.telescope').find_lunarvim_files()", + "Find LunarVim files", + }, + g = { + "lua require('lvim.core.telescope').grep_lunarvim_files()", + "Grep LunarVim files", + }, + k = { "lua require('lvim.keymappings').print()", "View LunarVim's default keymappings" }, + i = { + "lua require('lvim.core.info').toggle_popup(vim.bo.filetype)", + "Toggle LunarVim Info", + }, + I = { + "lua require('lvim.core.telescope').view_lunarvim_changelog()", + "View LunarVim's changelog", + }, + l = { + name = "+logs", + d = { + "lua require('lvim.core.terminal').toggle_log_view(require('lvim.core.log').get_path())", + "view default log", + }, + D = { + "lua vim.fn.execute('edit ' .. require('lvim.core.log').get_path())", + "Open the default logfile", + }, + l = { "lua require('lvim.core.terminal').toggle_log_view(vim.lsp.get_log_path())", "view lsp log" }, + L = { "lua vim.fn.execute('edit ' .. vim.lsp.get_log_path())", "Open the LSP logfile" }, + n = { + "lua require('lvim.core.terminal').toggle_log_view(os.getenv('NVIM_LOG_FILE'))", + "view neovim log", + }, + N = { "edit $NVIM_LOG_FILE", "Open the Neovim logfile" }, + p = { + "lua require('lvim.core.terminal').toggle_log_view('packer.nvim')", + "view packer log", + }, + P = { "exe 'edit '.stdpath('cache').'/packer.nvim.log'", "Open the Packer logfile" }, + }, + r = { "lua require('lvim.utils').reload_lv_config()", "Reload configurations" }, + u = { "LvimUpdate", "Update LunarVim" }, + }, + s = { + name = "Search", + b = { "Telescope git_branches", "Checkout branch" }, + c = { "Telescope colorscheme", "Colorscheme" }, + f = { "Telescope find_files", "Find File" }, + h = { "Telescope help_tags", "Find Help" }, + M = { "Telescope man_pages", "Man Pages" }, + r = { "Telescope oldfiles", "Open Recent File" }, + R = { "Telescope registers", "Registers" }, + t = { "Telescope live_grep", "Text" }, + k = { "Telescope keymaps", "Keymaps" }, + C = { "Telescope commands", "Commands" }, + p = { + "lua require('telescope.builtin.internal').colorscheme({enable_preview = true})", + "Colorscheme with Preview", + }, + }, + T = { + name = "Treesitter", + i = { ":TSConfigInfo", "Info" }, + }, + }, + } +end + +M.setup = function() + local which_key = require "which-key" + + which_key.setup(lvim.builtin.which_key.setup) + + local opts = lvim.builtin.which_key.opts + local vopts = lvim.builtin.which_key.vopts + + local mappings = lvim.builtin.which_key.mappings + local vmappings = lvim.builtin.which_key.vmappings + + which_key.register(mappings, opts) + which_key.register(vmappings, vopts) + + if lvim.builtin.which_key.on_config_done then + lvim.builtin.which_key.on_config_done(which_key) + end +end + +return M diff --git a/lua/lvim/impatient.lua b/lua/lvim/impatient.lua new file mode 100644 index 00000000..4fdc0026 --- /dev/null +++ b/lua/lvim/impatient.lua @@ -0,0 +1,360 @@ +-- modified version from https://github.com/lewis6991/impatient.nvim + +local vim = vim +local uv = vim.loop +local impatient_load_start = uv.hrtime() +local api = vim.api +local ffi = require "ffi" + +local get_option, set_option = api.nvim_get_option, api.nvim_set_option +local get_runtime_file = api.nvim_get_runtime_file + +local impatient_dur + +local M = { + cache = {}, + profile = nil, + dirty = false, + path = nil, + log = {}, +} + +_G.__luacache = M + +--{{{ +local cachepack = {} + +-- using double for packing/unpacking numbers has no conversion overhead +-- 32-bit ARM causes a bus error when casting to double, so use int there +local number_t = jit.arch ~= "arm" and "double" or "int" +ffi.cdef("typedef " .. number_t .. " number_t;") + +local c_number_t = ffi.typeof "number_t[1]" +local c_sizeof_number_t = ffi.sizeof "number_t" + +local out_buf = {} + +function out_buf.write_number(buf, num) + buf[#buf + 1] = ffi.string(c_number_t(num), c_sizeof_number_t) +end + +function out_buf.write_string(buf, str) + out_buf.write_number(buf, #str) + buf[#buf + 1] = str +end + +function out_buf.to_string(buf) + return table.concat(buf) +end + +local in_buf = {} + +function in_buf.read_number(buf) + if buf.size < buf.pos then + error "buffer access violation" + end + local res = ffi.cast("number_t*", buf.ptr + buf.pos)[0] + buf.pos = buf.pos + c_sizeof_number_t + return res +end + +function in_buf.read_string(buf) + local len = in_buf.read_number(buf) + local res = ffi.string(buf.ptr + buf.pos, len) + buf.pos = buf.pos + len + + return res +end + +function cachepack.pack(cache) + local total_keys = vim.tbl_count(cache) + local buf = {} + + out_buf.write_number(buf, total_keys) + for k, v in pairs(cache) do + out_buf.write_string(buf, k) + out_buf.write_string(buf, v[1] or "") + out_buf.write_number(buf, v[2] or 0) + out_buf.write_string(buf, v[3] or "") + end + + return out_buf.to_string(buf) +end + +function cachepack.unpack(str, raw_buf_size) + if raw_buf_size == 0 or str == nil or (raw_buf_size == nil and #str == 0) then + return {} + end + + local buf = { + ptr = raw_buf_size and str or ffi.new("const char[?]", #str, str), + pos = 0, + size = raw_buf_size or #str, + } + local cache = {} + + local total_keys = in_buf.read_number(buf) + for _ = 1, total_keys do + local k = in_buf.read_string(buf) + local v = { + in_buf.read_string(buf), + in_buf.read_number(buf), + in_buf.read_string(buf), + } + cache[k] = v + end + + return cache +end +--}}} + +local function log(...) + M.log[#M.log + 1] = table.concat({ string.format(...) }, " ") +end + +function M.print_log() + for _, l in ipairs(M.log) do + print(l) + end +end + +function M.enable_profile() + M.profile = {} + M.print_profile = function() + M.profile["lvim.impatient"] = { + resolve = 0, + load = impatient_dur, + loader = "standard", + } + require("lvim.impatient.profile").print_profile(M.profile) + end + vim.cmd [[command! LuaCacheProfile lua _G.__luacache.print_profile()]] +end + +local function is_cacheable(path) + -- Don't cache files in /tmp since they are not likely to persist. + -- Note: Appimage versions of Neovim mount $VIMRUNTIME in /tmp in a unique + -- directory on each launch. + return not vim.startswith(path, "/tmp/") +end + +local function hash(modpath) + local stat = uv.fs_stat(modpath) + if stat then + return stat.mtime.sec + end +end + +local function hrtime() + if M.profile then + return uv.hrtime() + end +end + +local function load_package_with_cache(name, loader) + local resolve_start = hrtime() + + local basename = name:gsub("%.", "/") + local paths = { "lua/" .. basename .. ".lua", "lua/" .. basename .. "/init.lua" } + + for _, path in ipairs(paths) do + local modpath = get_runtime_file(path, false)[1] + if modpath then + local load_start = hrtime() + local chunk, err = loadfile(modpath) + + if M.profile then + M.profile[name] = { + resolve = load_start - resolve_start, + load = hrtime() - load_start, + loader = loader or "standard", + } + end + + if chunk == nil then + return err + end + + if is_cacheable(modpath) then + log("Creating cache for module %s", name) + M.cache[name] = { modpath, hash(modpath), string.dump(chunk) } + M.dirty = true + else + log("Unable to cache module %s", name) + end + + return chunk + end + end + return nil +end + +local reduced_rtp + +-- Speed up non-cached loads by reducing the rtp path during requires +function M.update_reduced_rtp() + local luadirs = get_runtime_file("lua/", true) + + for i = 1, #luadirs do + luadirs[i] = luadirs[i]:sub(1, -6) + end + + reduced_rtp = table.concat(luadirs, ",") +end + +local function load_package_with_cache_reduced_rtp(name) + local orig_rtp = get_option "runtimepath" + local orig_ei = get_option "eventignore" + + if not reduced_rtp then + M.update_reduced_rtp() + end + + set_option("eventignore", "all") + set_option("rtp", reduced_rtp) + + local found = load_package_with_cache(name, "reduced") + + set_option("rtp", orig_rtp) + set_option("eventignore", orig_ei) + + return found +end + +local function load_from_cache(name) + local resolve_start = hrtime() + if M.cache[name] == nil then + log("No cache for module %s", name) + return "No cache entry" + end + + local modpath, mhash, codes = unpack(M.cache[name]) + + if mhash ~= hash(modpath) then + log("Stale cache for module %s", name) + M.cache[name] = nil + M.dirty = true + return "Stale cache" + end + + local load_start = hrtime() + local chunk = loadstring(codes) + + if M.profile then + M.profile[name] = { + resolve = load_start - resolve_start, + load = hrtime() - load_start, + loader = "cache", + } + end + + if not chunk then + M.cache[name] = nil + M.dirty = true + log("Error loading cache for module. Invalidating", name) + return "Cache error" + end + + return chunk +end + +function M.save_cache() + if M.dirty then + log("Updating cache file: %s", M.path) + local f = io.open(M.path, "w+b") + f:write(cachepack.pack(M.cache)) + f:flush() + M.dirty = false + end +end + +function M.clear_cache() + M.cache = {} + os.remove(M.path) +end + +impatient_dur = uv.hrtime() - impatient_load_start + +function M.setup(opts) + opts = opts or {} + M.path = opts.path or vim.fn.stdpath "cache" .. "/lvim_cache" + + if opts.enable_profiling then + M.enable_profile() + end + + local impatient_setup_start = uv.hrtime() + local stat = uv.fs_stat(M.path) + if stat then + log("Loading cache file %s", M.path) + local ok + -- Linux/macOS lets us easily mmap the cache file for faster reads without passing to Lua + if jit.os == "Linux" or jit.os == "OSX" then + local size = stat.size + + local C = ffi.C + local O_RDONLY = 0x00 + local PROT_READ = 0x01 + local MAP_PRIVATE = 0x02 + + ffi.cdef [[ + int open(const char *pathname, int flags); + int close(int fd); + void *mmap(void *addr, size_t length, int prot, int flags, int fd, long int offset); + int munmap(void *addr, size_t length); + ]] + local f = C.open(M.path, O_RDONLY) + + local addr = C.mmap(nil, size, PROT_READ, MAP_PRIVATE, f, 0) + ok = ffi.cast("intptr_t", addr) ~= -1 + + if ok then + M.cache = cachepack.unpack(ffi.cast("char *", addr), size) + C.munmap(addr, size) + end + + C.close(f) + else + local f = io.open(M.path, "rb") + ok, M.cache = pcall(function() + return cachepack.unpack(f:read "*a") + end) + end + + if not ok then + log("Corrupted cache file, %s. Invalidating...", M.path) + os.remove(M.path) + M.cache = {} + end + M.dirty = not ok + end + + local insert = table.insert + local package = package + + -- Fix the position of the preloader. This also makes loading modules like 'ffi' + -- and 'bit' quicker + if package.loaders[1] == vim._load_package then + -- Move vim._load_package to the second position + local vim_load = table.remove(package.loaders, 1) + insert(package.loaders, 2, vim_load) + end + + insert(package.loaders, 2, load_from_cache) + insert(package.loaders, 3, load_package_with_cache_reduced_rtp) + insert(package.loaders, 4, load_package_with_cache) + + vim.cmd [[ + augroup impatient + autocmd VimEnter,VimLeave * lua _G.__luacache.save_cache() + autocmd OptionSet runtimepath lua _G.__luacache.update_reduced_rtp(true) + augroup END + + command! LuaCacheClear lua _G.__luacache.clear_cache() + command! LuaCacheLog lua _G.__luacache.print_log() + ]] + + impatient_dur = impatient_dur + (uv.hrtime() - impatient_setup_start) +end + +return M diff --git a/lua/lvim/impatient/profile.lua b/lua/lvim/impatient/profile.lua new file mode 100644 index 00000000..0f4f8236 --- /dev/null +++ b/lua/lvim/impatient/profile.lua @@ -0,0 +1,145 @@ +local M = {} + +local api = vim.api + +function M.print_profile(profile) + if not profile then + print "Error: profiling was not enabled" + return + end + + local total_resolve = 0 + local total_load = 0 + local name_pad = 0 + local modules = {} + local plugins = {} + + for module, p in pairs(profile) do + p.resolve = p.resolve / 1000000 + p.load = p.load / 1000000 + p.total = p.resolve + p.load + p.module = module:gsub("/", ".") + + local plugin = p.module:match "([^.]+)" + if plugin then + if not plugins[plugin] then + plugins[plugin] = { + module = plugin, + resolve = 0, + load = 0, + total = 0, + } + end + local r = plugins[plugin] + + r.resolve = r.resolve + p.resolve + r.load = r.load + p.load + r.total = r.total + p.total + + if not r.loader then + r.loader = p.loader + elseif r.loader ~= p.loader then + r.loader = "mixed" + end + end + + total_resolve = total_resolve + p.resolve + total_load = total_load + p.load + + if #module > name_pad then + name_pad = #module + end + + modules[#modules + 1] = p + end + + table.sort(modules, function(a, b) + return a.module > b.module + end) + + do + local plugins_a = {} + for _, v in pairs(plugins) do + plugins_a[#plugins_a + 1] = v + end + plugins = plugins_a + end + + table.sort(plugins, function(a, b) + return a.total > b.total + end) + + local lines = {} + local function add(...) + lines[#lines + 1] = string.format(...) + end + + local l = string.rep("─", name_pad + 1) + + add( + "%s┬───────────┬────────────┬────────────┬────────────┐", + l + ) + add("%-" .. name_pad .. "s │ Loader │ Resolve │ Load │ Total │", "") + add( + "%s┼───────────┼────────────┼────────────┼────────────┤", + l + ) + add( + "%-" .. name_pad .. "s │ │ %8.4fms │ %8.4fms │ %8.4fms │", + "Total", + total_resolve, + total_load, + total_resolve + total_load + ) + add( + "%s┴───────────┴────────────┴────────────┴────────────┤", + l + ) + add("%-" .. name_pad .. "s │", "By Plugin") + add( + "%s┬───────────┬────────────┬────────────┬────────────┤", + l + ) + for _, p in ipairs(plugins) do + add( + "%-" .. name_pad .. "s │ %9s │ %8.4fms │ %8.4fms │ %8.4fms │", + p.module, + p.loader, + p.resolve, + p.load, + p.total + ) + end + add( + "%s┴───────────┴────────────┴────────────┴────────────┤", + l + ) + add("%-" .. name_pad .. "s │", "By Module") + add( + "%s┬───────────┬────────────┬────────────┬────────────┤", + l + ) + for _, p in pairs(modules) do + add( + "%-" .. name_pad .. "s │ %9s │ %8.4fms │ %8.4fms │ %8.4fms │", + p.module, + p.loader, + p.resolve, + p.load, + p.total + ) + end + add( + "%s┴───────────┴────────────┴────────────┴────────────┘", + l + ) + + local bufnr = api.nvim_create_buf(false, false) + api.nvim_buf_set_lines(bufnr, 0, 0, false, lines) + api.nvim_buf_set_option(bufnr, "buftype", "nofile") + api.nvim_buf_set_name(bufnr, "Impatient Profile Report") + api.nvim_set_current_buf(bufnr) +end + +return M diff --git a/lua/lvim/interface/popup.lua b/lua/lvim/interface/popup.lua new file mode 100644 index 00000000..b628125c --- /dev/null +++ b/lua/lvim/interface/popup.lua @@ -0,0 +1,62 @@ +local Popup = {} + +--- Create a new floating window +-- @param config The configuration passed to vim.api.nvim_open_win +-- @param win_opts The options registered with vim.api.nvim_win_set_option +-- @param buf_opts The options registered with vim.api.nvim_buf_set_option +-- @return A new popup +function Popup:new(opts) + opts = opts or {} + opts.layout = opts.layout or {} + opts.win_opts = opts.win_opts or {} + opts.buf_opts = opts.buf_opts or {} + + Popup.__index = Popup + + local editor_layout = { + height = vim.o.lines - vim.o.cmdheight - 2, -- Add margin for status and buffer line + width = vim.o.columns, + } + local popup_layout = { + relative = "editor", + height = math.floor(editor_layout.height * 0.9), + width = math.floor(editor_layout.width * 0.8), + style = "minimal", + border = "rounded", + } + popup_layout.row = math.floor((editor_layout.height - popup_layout.height) / 2) + popup_layout.col = math.floor((editor_layout.width - popup_layout.width) / 2) + + local obj = { + buffer = vim.api.nvim_create_buf(false, true), + layout = vim.tbl_deep_extend("force", popup_layout, opts.layout), + win_opts = opts.win_opts, + buf_opts = opts.buf_opts, + } + + setmetatable(obj, Popup) + + return obj +end + +--- Display the popup with the provided content +-- @param content_provider A function accepting the popup's layout and returning the content to display +function Popup:display(content_provider) + self.win_id = vim.api.nvim_open_win(self.buffer, true, self.layout) + vim.lsp.util.close_preview_autocmd({ "BufHidden", "BufLeave" }, self.win_id) + + local lines = content_provider(self.layout) + vim.api.nvim_buf_set_lines(self.bufnr, 0, -1, false, lines) + + -- window options + for key, value in pairs(self.win_opts) do + vim.api.nvim_win_set_option(self.win_id, key, value) + end + + -- buffer options + for key, value in pairs(self.buf_opts) do + vim.api.nvim_buf_set_option(self.buffer, key, value) + end +end + +return Popup diff --git a/lua/lvim/interface/text.lua b/lua/lvim/interface/text.lua new file mode 100644 index 00000000..6bf280e8 --- /dev/null +++ b/lua/lvim/interface/text.lua @@ -0,0 +1,95 @@ +local M = {} + +local function max_len_line(lines) + local max_len = 0 + + for _, line in ipairs(lines) do + local line_len = line:len() + if line_len > max_len then + max_len = line_len + end + end + + return max_len +end + +--- Left align lines relatively to the parent container +-- @param container The container where lines will be displayed +-- @param lines The text to align +-- @param alignment The alignment value, range: [0-1] +function M.align_left(container, lines, alignment) + local max_len = max_len_line(lines) + local indent_amount = math.ceil(math.max(container.width - max_len, 0) * alignment) + return M.shift_right(lines, indent_amount) +end + +--- Center align lines relatively to the parent container +-- @param container The container where lines will be displayed +-- @param lines The text to align +-- @param alignment The alignment value, range: [0-1] +function M.align_center(container, lines, alignment) + local output = {} + local max_len = max_len_line(lines) + + for _, line in ipairs(lines) do + local padding = string.rep(" ", (math.max(container.width, max_len) - line:len()) * alignment) + table.insert(output, padding .. line) + end + + return output +end + +--- Shift lines by a given amount +-- @params lines The lines the shift +-- @param amount The amount of spaces to add +function M.shift_right(lines, amount) + local output = {} + local padding = string.rep(" ", amount) + + for _, line in ipairs(lines) do + table.insert(output, padding .. line) + end + + return output +end + +--- Pretty format tables +-- @param entries The table to format +-- @param col_count The number of column to span the table on +-- @param col_sep The separator between each colummn, default: " " +function M.format_table(entries, col_count, col_sep) + col_sep = col_sep or " " + + local col_rows = math.ceil(vim.tbl_count(entries) / col_count) + local cols = {} + local count = 0 + + for i, entry in ipairs(entries) do + if ((i - 1) % col_rows) == 0 then + table.insert(cols, {}) + count = count + 1 + end + table.insert(cols[count], entry) + end + + local col_max_len = {} + for _, col in ipairs(cols) do + table.insert(col_max_len, max_len_line(col)) + end + + local output = {} + for i, col in ipairs(cols) do + for j, entry in ipairs(col) do + if not output[j] then + output[j] = entry + else + local padding = string.rep(" ", col_max_len[i - 1] - cols[i - 1][j]:len()) + output[j] = output[j] .. padding .. col_sep .. entry + end + end + end + + return output +end + +return M diff --git a/lua/lvim/keymappings.lua b/lua/lvim/keymappings.lua new file mode 100644 index 00000000..68a49393 --- /dev/null +++ b/lua/lvim/keymappings.lua @@ -0,0 +1,180 @@ +local M = {} +local Log = require "lvim.core.log" + +local generic_opts_any = { noremap = true, silent = true } + +local generic_opts = { + insert_mode = generic_opts_any, + normal_mode = generic_opts_any, + visual_mode = generic_opts_any, + visual_block_mode = generic_opts_any, + command_mode = generic_opts_any, + term_mode = { silent = true }, +} + +local mode_adapters = { + insert_mode = "i", + normal_mode = "n", + term_mode = "t", + visual_mode = "v", + visual_block_mode = "x", + command_mode = "c", +} + +-- Append key mappings to lunarvim's defaults for a given mode +-- @param keymaps The table of key mappings containing a list per mode (normal_mode, insert_mode, ..) +function M.append_to_defaults(keymaps) + for mode, mappings in pairs(keymaps) do + for k, v in ipairs(mappings) do + lvim.keys[mode][k] = v + end + end +end + +-- Set key mappings individually +-- @param mode The keymap mode, can be one of the keys of mode_adapters +-- @param key The key of keymap +-- @param val Can be form as a mapping or tuple of mapping and user defined opt +function M.set_keymaps(mode, key, val) + local opt = generic_opts[mode] and generic_opts[mode] or generic_opts_any + if type(val) == "table" then + opt = val[2] + val = val[1] + end + vim.api.nvim_set_keymap(mode, key, val, opt) +end + +-- Load key mappings for a given mode +-- @param mode The keymap mode, can be one of the keys of mode_adapters +-- @param keymaps The list of key mappings +function M.load_mode(mode, keymaps) + mode = mode_adapters[mode] and mode_adapters[mode] or mode + for k, v in pairs(keymaps) do + M.set_keymaps(mode, k, v) + end +end + +-- Load key mappings for all provided modes +-- @param keymaps A list of key mappings for each mode +function M.load(keymaps) + for mode, mapping in pairs(keymaps) do + M.load_mode(mode, mapping) + end +end + +function M.config() + lvim.keys = { + ---@usage change or add keymappings for insert mode + insert_mode = { + -- 'jk' for quitting insert mode + ["jk"] = "", + -- 'kj' for quitting insert mode + ["kj"] = "", + -- 'jj' for quitting insert mode + ["jj"] = "", + -- Move current line / block with Alt-j/k ala vscode. + [""] = ":m .+1==gi", + -- Move current line / block with Alt-j/k ala vscode. + [""] = ":m .-2==gi", + -- navigation + [""] = "k", + [""] = "j", + [""] = "h", + [""] = "l", + -- navigate tab completion with and + -- runs conditionally + [""] = { 'pumvisible() ? "\\" : "\\"', { expr = true, noremap = true } }, + [""] = { 'pumvisible() ? "\\" : "\\"', { expr = true, noremap = true } }, + }, + + ---@usage change or add keymappings for normal mode + normal_mode = { + -- Better window movement + [""] = "h", + [""] = "j", + [""] = "k", + [""] = "l", + + -- Resize with arrows + [""] = ":resize -2", + [""] = ":resize +2", + [""] = ":vertical resize -2", + [""] = ":vertical resize +2", + + -- Tab switch buffer + [""] = ":BufferNext", + [""] = ":BufferPrevious", + + -- Move current line / block with Alt-j/k a la vscode. + [""] = ":m .+1==", + [""] = ":m .-2==", + + -- QuickFix + ["]q"] = ":cnext", + ["[q"] = ":cprev", + [""] = ":call QuickFixToggle()", + }, + + ---@usage change or add keymappings for terminal mode + term_mode = { + -- Terminal window navigation + [""] = "h", + [""] = "j", + [""] = "k", + [""] = "l", + }, + + ---@usage change or add keymappings for visual mode + visual_mode = { + -- Better indenting + ["<"] = ""] = ">gv", + + -- ["p"] = '"0p', + -- ["P"] = '"0P', + }, + + ---@usage change or add keymappings for visual block mode + visual_block_mode = { + -- Move selected line / block of text in visual mode + ["K"] = ":move '<-2gv-gv", + ["J"] = ":move '>+1gv-gv", + + -- Move current line / block with Alt-j/k ala vscode. + [""] = ":m '>+1gv-gv", + [""] = ":m '<-2gv-gv", + }, + + ---@usage change or add keymappings for command mode + command_mode = { + -- navigate tab completion with and + -- runs conditionally + [""] = { 'pumvisible() ? "\\" : "\\"', { expr = true, noremap = true } }, + [""] = { 'pumvisible() ? "\\" : "\\"', { expr = true, noremap = true } }, + }, + } + + if vim.fn.has "mac" == 1 then + lvim.keys.normal_mode[""] = lvim.keys.normal_mode[""] + lvim.keys.normal_mode[""] = lvim.keys.normal_mode[""] + lvim.keys.normal_mode[""] = lvim.keys.normal_mode[""] + lvim.keys.normal_mode[""] = lvim.keys.normal_mode[""] + Log:debug "Activated mac keymappings" + end +end + +function M.print(mode) + print "List of LunarVim's default keymappings (not including which-key)" + if mode then + print(vim.inspect(lvim.keys[mode])) + else + print(vim.inspect(lvim.keys)) + end +end + +function M.setup() + vim.g.mapleader = (lvim.leader == "space" and " ") or lvim.leader + M.load(lvim.keys) +end + +return M diff --git a/lua/lvim/lsp/config.lua b/lua/lvim/lsp/config.lua new file mode 100644 index 00000000..30336cc2 --- /dev/null +++ b/lua/lvim/lsp/config.lua @@ -0,0 +1,45 @@ +return { + templates_dir = join_paths(get_runtime_dir(), "site", "after", "ftplugin"), + diagnostics = { + signs = { + active = true, + values = { + { name = "LspDiagnosticsSignError", text = "" }, + { name = "LspDiagnosticsSignWarning", text = "" }, + { name = "LspDiagnosticsSignHint", text = "" }, + { name = "LspDiagnosticsSignInformation", text = "" }, + }, + }, + virtual_text = true, + update_in_insert = false, + underline = true, + severity_sort = true, + }, + override = {}, + document_highlight = true, + code_lens_refresh = true, + popup_border = "single", + on_attach_callback = nil, + on_init_callback = nil, + automatic_servers_installation = true, + buffer_mappings = { + normal_mode = { + ["K"] = { "lua vim.lsp.buf.hover()", "Show hover" }, + ["gd"] = { "lua vim.lsp.buf.definition()", "Goto Definition" }, + ["gD"] = { "lua vim.lsp.buf.declaration()", "Goto declaration" }, + ["gr"] = { "lua vim.lsp.buf.references()", "Goto references" }, + ["gI"] = { "lua vim.lsp.buf.implementation()", "Goto Implementation" }, + ["gs"] = { "lua vim.lsp.buf.signature_help()", "show signature help" }, + ["gp"] = { "lua require'lvim.lsp.peek'.Peek('definition')", "Peek definition" }, + ["gl"] = { + "lua require'lvim.lsp.handlers'.show_line_diagnostics()", + "Show line diagnostics", + }, + }, + insert_mode = {}, + visual_mode = {}, + }, + null_ls = { + setup = {}, + }, +} diff --git a/lua/lvim/lsp/handlers.lua b/lua/lvim/lsp/handlers.lua new file mode 100644 index 00000000..ffb7564a --- /dev/null +++ b/lua/lvim/lsp/handlers.lua @@ -0,0 +1,169 @@ +-- Set Default Prefix. +-- Note: You can set a prefix per lsp server in the lv-globals.lua file +local M = {} + +function M.setup() + local config = { -- your config + virtual_text = lvim.lsp.diagnostics.virtual_text, + signs = lvim.lsp.diagnostics.signs, + underline = lvim.lsp.diagnostics.underline, + update_in_insert = lvim.lsp.diagnostics.update_in_insert, + severity_sort = lvim.lsp.diagnostics.severity_sort, + } + if vim.fn.has "nvim-0.5.1" > 0 then + vim.lsp.handlers["textDocument/publishDiagnostics"] = function(_, result, ctx, _) + local uri = result.uri + local bufnr = vim.uri_to_bufnr(uri) + if not bufnr then + return + end + + local diagnostics = result.diagnostics + local ok, vim_diag = pcall(require, "vim.diagnostic") + if ok then + -- FIX: why can't we just use vim.diagnostic.get(buf_id)? + config.signs = true + for i, diagnostic in ipairs(diagnostics) do + local rng = diagnostic.range + diagnostics[i].lnum = rng["start"].line + diagnostics[i].end_lnum = rng["end"].line + diagnostics[i].col = rng["start"].character + diagnostics[i].end_col = rng["end"].character + end + local namespace = vim.lsp.diagnostic.get_namespace(ctx.client_id) + + vim_diag.set(namespace, bufnr, diagnostics, config) + if not vim.api.nvim_buf_is_loaded(bufnr) then + return + end + + local sign_names = { + "DiagnosticSignError", + "DiagnosticSignWarn", + "DiagnosticSignInfo", + "DiagnosticSignHint", + } + for i, sign in ipairs(lvim.lsp.diagnostics.signs.values) do + vim.fn.sign_define(sign_names[i], { texthl = sign_names[i], text = sign.text, numhl = "" }) + end + vim_diag.show(namespace, bufnr, diagnostics, config) + else + vim.lsp.diagnostic.save(diagnostics, bufnr, ctx.client_id) + if not vim.api.nvim_buf_is_loaded(bufnr) then + return + end + vim.lsp.diagnostic.display(diagnostics, bufnr, ctx.client_id, config) + end + end + else + vim.lsp.handlers["textDocument/publishDiagnostics"] = function(_, _, params, client_id, _) + local uri = params.uri + local bufnr = vim.uri_to_bufnr(uri) + if not bufnr then + return + end + + local diagnostics = params.diagnostics + vim.lsp.diagnostic.save(diagnostics, bufnr, client_id) + if not vim.api.nvim_buf_is_loaded(bufnr) then + return + end + vim.lsp.diagnostic.display(diagnostics, bufnr, client_id, config) + end + end + + vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { + border = lvim.lsp.popup_border, + }) + + vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, { + border = lvim.lsp.popup_border, + }) +end + +local function split_by_chunk(text, chunkSize) + local s = {} + for i = 1, #text, chunkSize do + s[#s + 1] = text:sub(i, i + chunkSize - 1) + end + return s +end + +function M.show_line_diagnostics() + -- TODO: replace all this with vim.diagnostic.show_position_diagnostics() + local diagnostics = vim.lsp.diagnostic.get_line_diagnostics() + local severity_highlight = { + "LspDiagnosticsFloatingError", + "LspDiagnosticsFloatingWarning", + "LspDiagnosticsFloatingInformation", + "LspDiagnosticsFloatingHint", + } + local ok, vim_diag = pcall(require, "vim.diagnostic") + if ok then + local buf_id = vim.api.nvim_win_get_buf(0) + local win_id = vim.api.nvim_get_current_win() + local cursor_position = vim.api.nvim_win_get_cursor(win_id) + severity_highlight = { + "DiagnosticFloatingError", + "DiagnosticFloatingWarn", + "DiagnosticFloatingInfo", + "DiagnosticFloatingHint", + } + diagnostics = vim_diag.get(buf_id, { lnum = cursor_position[1] - 1 }) + end + local lines = {} + local max_width = vim.fn.winwidth(0) - 5 + local height = #diagnostics + local width = 0 + local opts = {} + local close_events = { "CursorMoved", "CursorMovedI", "BufHidden", "InsertCharPre" } + if height == 0 then + return + end + local bufnr = vim.api.nvim_create_buf(false, true) + local diag_message + table.sort(diagnostics, function(a, b) + return a.severity < b.severity + end) + for i, diagnostic in ipairs(diagnostics) do + local source = diagnostic.source + diag_message = diagnostic.message:gsub("[\n\r]", " ") + if source then + if string.find(source, "/") then + source = string.sub(diagnostic.source, string.find(diagnostic.source, "([%w-_]+)$")) + end + diag_message = string.format("%d. %s: %s", i, source, diag_message) + else + diag_message = string.format("%d. %s", i, diag_message) + end + if diagnostic.code then + diag_message = string.format("%s [%s]", diag_message, diagnostic.code) + end + local msgs = split_by_chunk(diag_message, max_width) + for _, diag in ipairs(msgs) do + table.insert(lines, { message = diag, severity = diagnostic.severity }) + width = math.max(diag:len(), width) + end + end + height = #lines + opts = vim.lsp.util.make_floating_popup_options(width, height, opts) + opts["style"] = "minimal" + opts["border"] = "rounded" + opts["focusable"] = true + + vim.api.nvim_buf_set_option(bufnr, "bufhidden", "wipe") + local winnr = vim.api.nvim_open_win(bufnr, false, opts) + vim.api.nvim_win_set_option(winnr, "winblend", 0) + vim.api.nvim_buf_set_var(bufnr, "lsp_floating_window", winnr) + for i, diag in ipairs(lines) do + vim.api.nvim_buf_set_lines(bufnr, i - 1, i - 1, 0, { diag.message }) + vim.api.nvim_buf_add_highlight(bufnr, -1, severity_highlight[diag.severity], i - 1, 0, diag.message:len()) + end + + vim.api.nvim_command( + "autocmd QuitPre ++nested ++once lua pcall(vim.api.nvim_win_close, " .. winnr .. ", true)" + ) + vim.lsp.util.close_preview_autocmd(close_events, winnr) +end + +return M diff --git a/lua/lvim/lsp/init.lua b/lua/lvim/lsp/init.lua new file mode 100644 index 00000000..c8d583a9 --- /dev/null +++ b/lua/lvim/lsp/init.lua @@ -0,0 +1,165 @@ +local M = {} +local Log = require "lvim.core.log" +local utils = require "lvim.utils" + +local function lsp_highlight_document(client) + if lvim.lsp.document_highlight == false then + return -- we don't need further + end + -- Set autocommands conditional on server_capabilities + if client.resolved_capabilities.document_highlight then + vim.api.nvim_exec( + [[ + augroup lsp_document_highlight + autocmd! * + autocmd CursorHold lua vim.lsp.buf.document_highlight() + autocmd CursorMoved lua vim.lsp.buf.clear_references() + augroup END + ]], + false + ) + end +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 + vim.api.nvim_exec( + [[ + augroup lsp_code_lens_refresh + autocmd! * + autocmd InsertLeave lua vim.lsp.codelens.refresh() + autocmd InsertLeave lua vim.lsp.codelens.display() + augroup END + ]], + false + ) + end +end + +local function add_lsp_buffer_keybindings(bufnr) + local mappings = { + normal_mode = "n", + insert_mode = "i", + visual_mode = "v", + } + + if lvim.builtin.which_key.active then + -- Remap using which_key + local status_ok, wk = pcall(require, "which-key") + if not status_ok then + return + end + for mode_name, mode_char in pairs(mappings) do + wk.register(lvim.lsp.buffer_mappings[mode_name], { mode = mode_char, buffer = bufnr }) + end + else + -- Remap using nvim api + for mode_name, mode_char in pairs(mappings) do + for key, remap in pairs(lvim.lsp.buffer_mappings[mode_name]) do + vim.api.nvim_buf_set_keymap(bufnr, mode_char, key, remap[1], { noremap = true, silent = true }) + end + end + end +end + +function M.common_capabilities() + local capabilities = vim.lsp.protocol.make_client_capabilities() + capabilities.textDocument.completion.completionItem.snippetSupport = true + capabilities.textDocument.completion.completionItem.resolveSupport = { + properties = { + "documentation", + "detail", + "additionalTextEdits", + }, + } + + local status_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") + if status_ok then + capabilities = cmp_nvim_lsp.update_capabilities(capabilities) + end + + return capabilities +end + +local function select_default_formater(client) + local client_formatting = client.resolved_capabilities.document_formatting + or client.resolved_capabilities.document_range_formatting + if client.name == "null-ls" or not client_formatting then + return + end + Log:debug("Checking for formatter overriding for " .. client.name) + local client_filetypes = client.config.filetypes or {} + for _, filetype in ipairs(client_filetypes) do + if lvim.lang[filetype] and #vim.tbl_keys(lvim.lang[filetype].formatters) > 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_init(client, bufnr) + if lvim.lsp.on_init_callback then + lvim.lsp.on_init_callback(client, bufnr) + Log:debug "Called lsp.on_init_callback" + return + end + select_default_formater(client) +end + +function M.common_on_attach(client, bufnr) + if lvim.lsp.on_attach_callback then + lvim.lsp.on_attach_callback(client, bufnr) + Log:debug "Called lsp.on_attach_callback" + end + lsp_highlight_document(client) + lsp_code_lens_refresh(client) + add_lsp_buffer_keybindings(bufnr) +end + +local function bootstrap_nlsp(opts) + opts = opts or {} + local lsp_settings_status_ok, lsp_settings = pcall(require, "nlspsettings") + if lsp_settings_status_ok then + lsp_settings.setup(opts) + end +end + +function M.get_common_opts() + return { + on_attach = M.common_on_attach, + on_init = M.common_on_init, + capabilities = M.common_capabilities(), + } +end + +function M.setup() + Log:debug "Setting up LSP support" + + local lsp_status_ok, _ = pcall(require, "lspconfig") + if not lsp_status_ok then + 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 }) + end + + require("lvim.lsp.handlers").setup() + + if not utils.is_directory(lvim.lsp.templates_dir) then + require("lvim.lsp.templates").generate_templates() + end + + bootstrap_nlsp { config_home = utils.join_paths(get_config_dir(), "lsp-settings") } + + require("lvim.lsp.null-ls").setup() + + require("lvim.utils").toggle_autoformat() +end + +return M diff --git a/lua/lvim/lsp/manager.lua b/lua/lvim/lsp/manager.lua new file mode 100644 index 00000000..678a08af --- /dev/null +++ b/lua/lvim/lsp/manager.lua @@ -0,0 +1,86 @@ +local M = {} + +local Log = require "lvim.core.log" +local lsp_utils = require "lvim.lsp.utils" + +function M.init_defaults(languages) + for _, entry in ipairs(languages) do + if not lvim.lang[entry] then + lvim.lang[entry] = { + formatters = {}, + linters = {}, + lsp = {}, + } + end + end +end + +local function is_overridden(server) + local overrides = lvim.lsp.override + if type(overrides) == "table" then + if vim.tbl_contains(overrides, server) then + return true + end + end +end + +---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("lvim.lsp").common_on_attach, + on_init = require("lvim.lsp").common_on_init, + capabilities = require("lvim.lsp").common_capabilities(), + } + + local status_ok, custom_config = pcall(require, "lvim.lsp/providers/" .. name) + if status_ok then + 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 + +---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 + + 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 + + if server_available and ensure_installed(requested_server) then + requested_server:setup(config) + else + require("lspconfig")[server_name].setup(config) + end +end + +return M diff --git a/lua/lvim/lsp/null-ls/formatters.lua b/lua/lvim/lsp/null-ls/formatters.lua new file mode 100644 index 00000000..663e2586 --- /dev/null +++ b/lua/lvim/lsp/null-ls/formatters.lua @@ -0,0 +1,66 @@ +local M = {} + +local null_ls = require "null-ls" +local services = require "lvim.lsp.null-ls.services" +local Log = require "lvim.core.log" + +function M.list_supported_names(filetype) + local null_ls_methods = require "null-ls.methods" + local formatter_method = null_ls_methods.internal["FORMATTING"] + local registered_providers = services.list_registered_providers_names(filetype) + return registered_providers[formatter_method] or {} +end + +function M.list_available(filetype) + local formatters = {} + local tbl = require "lvim.utils.table" + for _, provider in pairs(null_ls.builtins.formatting) do + if tbl.contains(provider.filetypes or {}, function(ft) + return ft == "*" or ft == filetype + end) then + table.insert(formatters, provider.name) + end + end + + return formatters +end + +function M.list_configured(formatter_configs) + local formatters, errors = {}, {} + + for _, fmt_config in ipairs(formatter_configs) do + local formatter_name = fmt_config.exe:gsub("-", "_") + local formatter = null_ls.builtins.formatting[formatter_name] + + if not formatter then + Log:error("Not a valid formatter: " .. fmt_config.exe) + errors[fmt_config.exe] = {} -- Add data here when necessary + else + local formatter_cmd = services.find_command(formatter._opts.command) + if not formatter_cmd then + Log:warn("Not found: " .. formatter._opts.command) + errors[fmt_config.exe] = {} -- Add data here when necessary + else + Log:debug("Using formatter: " .. formatter_cmd) + formatters[fmt_config.exe] = formatter.with { + command = formatter_cmd, + extra_args = fmt_config.args, + filetypes = fmt_config.filetypes, + } + end + end + end + + return { supported = formatters, unsupported = errors } +end + +function M.setup(formatter_configs) + if vim.tbl_isempty(formatter_configs) then + return + end + + local formatters_by_ft = M.list_configured(formatter_configs) + null_ls.register { sources = formatters_by_ft.supported } +end + +return M diff --git a/lua/lvim/lsp/null-ls/init.lua b/lua/lvim/lsp/null-ls/init.lua new file mode 100644 index 00000000..f2d3216d --- /dev/null +++ b/lua/lvim/lsp/null-ls/init.lua @@ -0,0 +1,32 @@ +local M = {} + +local Log = require "lvim.core.log" +local formatters = require "lvim.lsp.null-ls.formatters" +local linters = require "lvim.lsp.null-ls.linters" + +function M:setup() + local status_ok, null_ls = pcall(require, "null-ls") + if not status_ok then + Log:error "Missing null-ls dependency" + return + end + + null_ls.config() + require("lspconfig")["null-ls"].setup(lvim.lsp.null_ls.setup) + for filetype, config in pairs(lvim.lang) do + if not vim.tbl_isempty(config.formatters) then + vim.tbl_map(function(c) + c.filetypes = { filetype } + end, config.formatters) + formatters.setup(config.formatters) + end + if not vim.tbl_isempty(config.linters) then + vim.tbl_map(function(c) + c.filetypes = { filetype } + end, config.formatters) + linters.setup(config.linters) + end + end +end + +return M diff --git a/lua/lvim/lsp/null-ls/linters.lua b/lua/lvim/lsp/null-ls/linters.lua new file mode 100644 index 00000000..9ea2d55b --- /dev/null +++ b/lua/lvim/lsp/null-ls/linters.lua @@ -0,0 +1,66 @@ +local M = {} + +local null_ls = require "null-ls" +local services = require "lvim.lsp.null-ls.services" +local Log = require "lvim.core.log" + +function M.list_supported_names(filetype) + local null_ls_methods = require "null-ls.methods" + local linter_method = null_ls_methods.internal["DIAGNOSTICS"] + local registered_providers = services.list_registered_providers_names(filetype) + return registered_providers[linter_method] or {} +end + +function M.list_available(filetype) + local linters = {} + local tbl = require "lvim.utils.table" + for _, provider in pairs(null_ls.builtins.diagnostics) do + if tbl.contains(provider.filetypes or {}, function(ft) + return ft == "*" or ft == filetype + end) then + table.insert(linters, provider.name) + end + end + + return linters +end + +function M.list_configured(linter_configs) + local linters, errors = {}, {} + + for _, lnt_config in pairs(linter_configs) do + local linter_name = lnt_config.exe:gsub("-", "_") + local linter = null_ls.builtins.diagnostics[linter_name] + + if not linter then + Log:error("Not a valid linter: " .. lnt_config.exe) + errors[lnt_config.exe] = {} -- Add data here when necessary + else + local linter_cmd = services.find_command(linter._opts.command) + if not linter_cmd then + Log:warn("Not found: " .. linter._opts.command) + errors[lnt_config.exe] = {} -- Add data here when necessary + else + Log:debug("Using linter: " .. linter_cmd) + linters[lnt_config.exe] = linter.with { + command = linter_cmd, + extra_args = lnt_config.args, + filetypes = lnt_config.filetypes, + } + end + end + end + + return { supported = linters, unsupported = errors } +end + +function M.setup(linter_configs) + if vim.tbl_isempty(linter_configs) then + return + end + + local linters = M.list_configured(linter_configs) + null_ls.register { sources = linters.supported } +end + +return M diff --git a/lua/lvim/lsp/null-ls/services.lua b/lua/lvim/lsp/null-ls/services.lua new file mode 100644 index 00000000..9cb29f49 --- /dev/null +++ b/lua/lvim/lsp/null-ls/services.lua @@ -0,0 +1,63 @@ +local M = {} + +local function find_root_dir() + local util = require "lspconfig/util" + local lsp_utils = require "lvim.lsp.utils" + + local ts_client = lsp_utils.is_client_active "typescript" + if ts_client then + return ts_client.config.root_dir + end + local dirname = vim.fn.expand "%:p:h" + return util.root_pattern "package.json"(dirname) +end + +local function from_node_modules(command) + local root_dir = find_root_dir() + + if not root_dir then + return nil + end + + return root_dir .. "/node_modules/.bin/" .. command +end + +local local_providers = { + prettier = { find = from_node_modules }, + prettierd = { find = from_node_modules }, + prettier_d_slim = { find = from_node_modules }, + eslint_d = { find = from_node_modules }, + eslint = { find = from_node_modules }, + stylelint = { find = from_node_modules }, +} + +function M.find_command(command) + if local_providers[command] then + local local_command = local_providers[command].find(command) + if local_command and vim.fn.executable(local_command) == 1 then + return local_command + end + end + + if vim.fn.executable(command) == 1 then + return command + end + return nil +end + +function M.list_registered_providers_names(filetype) + local u = require "null-ls.utils" + local c = require "null-ls.config" + local registered = {} + for method, source in pairs(c.get()._methods) do + for name, filetypes in pairs(source) do + if u.filetype_matches(filetypes, filetype) then + registered[method] = registered[method] or {} + table.insert(registered[method], name) + end + end + end + return registered +end + +return M diff --git a/lua/lvim/lsp/peek.lua b/lua/lvim/lsp/peek.lua new file mode 100644 index 00000000..08345aff --- /dev/null +++ b/lua/lvim/lsp/peek.lua @@ -0,0 +1,152 @@ +local M = { + floating_buf = nil, + floating_win = nil, + prev_result = nil, +} + +local function create_floating_file(location, opts) + vim.validate { + location = { location, "t" }, + opts = { opts, "t", true }, + } + + -- Set some defaults + opts = opts or {} + local close_events = opts.close_events or { "CursorMoved", "CursorMovedI", "BufHidden", "InsertCharPre" } + + -- location may be LocationLink or Location + local uri = location.targetUri or location.uri + if uri == nil then + return + end + local bufnr = vim.uri_to_bufnr(uri) + if not vim.api.nvim_buf_is_loaded(bufnr) then + vim.fn.bufload(bufnr) + end + + local range = location.targetRange or location.range + + local contents = vim.api.nvim_buf_get_lines( + bufnr, + range.start.line, + math.min(range["end"].line + 1 + (opts.context or 10), range.start.line + (opts.max_height or 15)), -- Don't let the window be more that 15 lines long(height) + false + ) + local width, height = vim.lsp.util._make_floating_popup_size(contents, opts) + opts = vim.lsp.util.make_floating_popup_options(width, height, opts) + -- Don't make it minimal as it is meant to be fully featured + opts["style"] = nil + + vim.api.nvim_buf_set_option(bufnr, "bufhidden", "wipe") + + local winnr = vim.api.nvim_open_win(bufnr, false, opts) + vim.api.nvim_win_set_option(winnr, "winblend", 0) + + vim.api.nvim_win_set_cursor(winnr, { range.start.line + 1, range.start.character }) + vim.api.nvim_buf_set_var(bufnr, "lsp_floating_window", winnr) + + -- Set some autocmds to close the window + vim.api.nvim_command( + "autocmd QuitPre ++nested ++once lua pcall(vim.api.nvim_win_close, " .. winnr .. ", true)" + ) + vim.lsp.util.close_preview_autocmd(close_events, winnr) + + return bufnr, winnr +end + +local function preview_location_callback(result) + if result == nil or vim.tbl_isempty(result) then + return nil + end + + local opts = { + border = "rounded", + context = 10, + } + + if vim.tbl_islist(result) then + M.prev_result = result[1] + M.floating_buf, M.floating_win = create_floating_file(result[1], opts) + else + M.prev_result = result + M.floating_buf, M.floating_win = create_floating_file(result, opts) + end +end + +local function preview_location_callback_old_signature(_, _, result) + return preview_location_callback(result) +end + +local function preview_location_callback_new_signature(_, result) + return preview_location_callback(result) +end + +function M.open_file() + -- Get the file currently open in the floating window + local filepath = vim.fn.expand "%:." + + if not filepath then + print "peek: Unable to open the file!" + return + end + + -- Close the floating window + pcall(vim.api.nvim_win_close, M.floating_win, true) + + -- Edit the file + vim.cmd("edit " .. filepath) + + local winnr = vim.api.nvim_get_current_win() + + -- Set the cursor at the right position + M.set_cursor_to_prev_pos(winnr) +end + +function M.set_cursor_to_prev_pos(winnr) + -- Get position of the thing to peek at + local location = M.prev_result + local range = location.targetRange or location.range + local cursor_pos = { range.start.line + 1, range.start.character } + + -- Set the winnr to the floating window if none was passed in + winnr = winnr or M.floating_win + -- Set the cursor at the correct position in the floating window + vim.api.nvim_win_set_cursor(winnr, cursor_pos) +end + +function M.Peek(what) + -- If a window already exists, focus it at the right position! + if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then + local success_1, _ = pcall(vim.api.nvim_set_current_win, M.floating_win) + if not success_1 then + print "peek: You cannot edit the current file in a preview!" + return + end + + -- Set the cursor at the correct position in the floating window + M.set_cursor_to_prev_pos() + + vim.api.nvim_buf_set_keymap( + M.floating_buf, + "n", + "", + ":lua require('lvim.lsp.peek').open_file()", + { noremap = true, silent = true } + ) + else + -- Make a new request and then create the new window in the callback + local params = vim.lsp.util.make_position_params() + local preview_callback = preview_location_callback_old_signature + if vim.fn.has "nvim-0.5.1" > 0 then + preview_callback = preview_location_callback_new_signature + end + local success, _ = pcall(vim.lsp.buf_request, 0, "textDocument/" .. what, params, preview_callback) + if not success then + print( + 'peek: Error calling LSP method "textDocument/' .. what .. '". The current language lsp might not support it.' + ) + end + end +end + +return M diff --git a/lua/lvim/lsp/providers/jsonls.lua b/lua/lvim/lsp/providers/jsonls.lua new file mode 100644 index 00000000..1fffa686 --- /dev/null +++ b/lua/lvim/lsp/providers/jsonls.lua @@ -0,0 +1,197 @@ +local default_schemas = nil +local status_ok, jsonls_settings = pcall(require, "nlspsettings.jsonls") +if status_ok then + default_schemas = jsonls_settings.get_default_schemas() +end + +local schemas = { + { + description = "TypeScript compiler configuration file", + fileMatch = { + "tsconfig.json", + "tsconfig.*.json", + }, + url = "https://json.schemastore.org/tsconfig.json", + }, + { + description = "Lerna config", + fileMatch = { "lerna.json" }, + url = "https://json.schemastore.org/lerna.json", + }, + { + description = "Babel configuration", + fileMatch = { + ".babelrc.json", + ".babelrc", + "babel.config.json", + }, + url = "https://json.schemastore.org/babelrc.json", + }, + { + description = "ESLint config", + fileMatch = { + ".eslintrc.json", + ".eslintrc", + }, + url = "https://json.schemastore.org/eslintrc.json", + }, + { + description = "Bucklescript config", + fileMatch = { "bsconfig.json" }, + url = "https://raw.githubusercontent.com/rescript-lang/rescript-compiler/8.2.0/docs/docson/build-schema.json", + }, + { + description = "Prettier config", + fileMatch = { + ".prettierrc", + ".prettierrc.json", + "prettier.config.json", + }, + url = "https://json.schemastore.org/prettierrc", + }, + { + description = "Vercel Now config", + fileMatch = { "now.json" }, + url = "https://json.schemastore.org/now", + }, + { + description = "Stylelint config", + fileMatch = { + ".stylelintrc", + ".stylelintrc.json", + "stylelint.config.json", + }, + url = "https://json.schemastore.org/stylelintrc", + }, + { + description = "A JSON schema for the ASP.NET LaunchSettings.json files", + fileMatch = { "launchsettings.json" }, + url = "https://json.schemastore.org/launchsettings.json", + }, + { + description = "Schema for CMake Presets", + fileMatch = { + "CMakePresets.json", + "CMakeUserPresets.json", + }, + url = "https://raw.githubusercontent.com/Kitware/CMake/master/Help/manual/presets/schema.json", + }, + { + description = "Configuration file as an alternative for configuring your repository in the settings page.", + fileMatch = { + ".codeclimate.json", + }, + url = "https://json.schemastore.org/codeclimate.json", + }, + { + description = "LLVM compilation database", + fileMatch = { + "compile_commands.json", + }, + url = "https://json.schemastore.org/compile-commands.json", + }, + { + description = "Config file for Command Task Runner", + fileMatch = { + "commands.json", + }, + url = "https://json.schemastore.org/commands.json", + }, + { + description = "AWS CloudFormation provides a common language for you to describe and provision all the infrastructure resources in your cloud environment.", + fileMatch = { + "*.cf.json", + "cloudformation.json", + }, + url = "https://raw.githubusercontent.com/awslabs/goformation/v5.2.9/schema/cloudformation.schema.json", + }, + { + description = "The AWS Serverless Application Model (AWS SAM, previously known as Project Flourish) extends AWS CloudFormation to provide a simplified way of defining the Amazon API Gateway APIs, AWS Lambda functions, and Amazon DynamoDB tables needed by your serverless application.", + fileMatch = { + "serverless.template", + "*.sam.json", + "sam.json", + }, + url = "https://raw.githubusercontent.com/awslabs/goformation/v5.2.9/schema/sam.schema.json", + }, + { + description = "Json schema for properties json file for a GitHub Workflow template", + fileMatch = { + ".github/workflow-templates/**.properties.json", + }, + url = "https://json.schemastore.org/github-workflow-template-properties.json", + }, + { + description = "golangci-lint configuration file", + fileMatch = { + ".golangci.toml", + ".golangci.json", + }, + url = "https://json.schemastore.org/golangci-lint.json", + }, + { + description = "JSON schema for the JSON Feed format", + fileMatch = { + "feed.json", + }, + url = "https://json.schemastore.org/feed.json", + versions = { + ["1"] = "https://json.schemastore.org/feed-1.json", + ["1.1"] = "https://json.schemastore.org/feed.json", + }, + }, + { + description = "Packer template JSON configuration", + fileMatch = { + "packer.json", + }, + url = "https://json.schemastore.org/packer.json", + }, + { + description = "NPM configuration file", + fileMatch = { + "package.json", + }, + url = "https://json.schemastore.org/package.json", + }, + { + description = "JSON schema for Visual Studio component configuration files", + fileMatch = { + "*.vsconfig", + }, + url = "https://json.schemastore.org/vsconfig.json", + }, + { + description = "Resume json", + fileMatch = { "resume.json" }, + url = "https://raw.githubusercontent.com/jsonresume/resume-schema/v1.0.0/schema.json", + }, +} + +local function extend(tab1, tab2) + for _, value in ipairs(tab2) do + table.insert(tab1, value) + end + return tab1 +end + +local extended_schemas = extend(schemas, default_schemas) + +local opts = { + settings = { + json = { + schemas = extended_schemas, + }, + }, + setup = { + commands = { + Format = { + function() + vim.lsp.buf.range_formatting({}, { 0, 0 }, { vim.fn.line "$", 0 }) + end, + }, + }, + }, +} + +return opts diff --git a/lua/lvim/lsp/providers/sumneko_lua.lua b/lua/lvim/lsp/providers/sumneko_lua.lua new file mode 100644 index 00000000..6585c8c7 --- /dev/null +++ b/lua/lvim/lsp/providers/sumneko_lua.lua @@ -0,0 +1,19 @@ +local opts = { + settings = { + Lua = { + diagnostics = { + globals = { "vim", "lvim" }, + }, + workspace = { + library = { + [require("lvim.utils").join_paths(get_runtime_dir(), "lvim", "lua")] = true, + [vim.fn.expand "$VIMRUNTIME/lua"] = true, + [vim.fn.expand "$VIMRUNTIME/lua/vim/lsp"] = true, + }, + maxPreload = 100000, + preloadFileSize = 10000, + }, + }, + }, +} +return opts diff --git a/lua/lvim/lsp/providers/vuels.lua b/lua/lvim/lsp/providers/vuels.lua new file mode 100644 index 00000000..326363fd --- /dev/null +++ b/lua/lvim/lsp/providers/vuels.lua @@ -0,0 +1,26 @@ +local opts = { + setup = { + root_dir = function(fname) + local util = require "lvim.lspconfig/util" + return util.root_pattern "package.json"(fname) or util.root_pattern "vue.config.js"(fname) or vim.fn.getcwd() + end, + init_options = { + config = { + vetur = { + completion = { + autoImport = true, + tagCasing = "kebab", + useScaffoldSnippets = true, + }, + useWorkspaceDependencies = true, + validation = { + script = true, + style = true, + template = true, + }, + }, + }, + }, + }, +} +return opts diff --git a/lua/lvim/lsp/providers/yamlls.lua b/lua/lvim/lsp/providers/yamlls.lua new file mode 100644 index 00000000..156a35b0 --- /dev/null +++ b/lua/lvim/lsp/providers/yamlls.lua @@ -0,0 +1,30 @@ +local opts = { + settings = { + yaml = { + hover = true, + completion = true, + validate = true, + schemaStore = { + enable = true, + url = "https://www.schemastore.org/api/json/catalog.json", + }, + schemas = { + kubernetes = { + "daemon.{yml,yaml}", + "manager.{yml,yaml}", + "restapi.{yml,yaml}", + "role.{yml,yaml}", + "role_binding.{yml,yaml}", + "*onfigma*.{yml,yaml}", + "*ngres*.{yml,yaml}", + "*ecre*.{yml,yaml}", + "*eployment*.{yml,yaml}", + "*ervic*.{yml,yaml}", + "kubectl-edit*.yaml", + }, + }, + }, + }, +} + +return opts diff --git a/lua/lvim/lsp/templates.lua b/lua/lvim/lsp/templates.lua new file mode 100644 index 00000000..e0741b1b --- /dev/null +++ b/lua/lvim/lsp/templates.lua @@ -0,0 +1,98 @@ +local M = {} + +local Log = require "lvim.core.log" +local utils = require "lvim.utils" +local get_supported_filetypes = require("lvim.lsp.utils").get_supported_filetypes + +local ftplugin_dir = lvim.lsp.templates_dir + +local join_paths = _G.join_paths + +function M.remove_template_files() + -- remove any outdated files + for _, file in ipairs(vim.fn.glob(ftplugin_dir .. "/*.lua", 1, 1)) do + vim.fn.delete(file) + end +end + +---Checks if a server is ignored by default because of a conflict +---Only TSServer is enabled by default for the javascript-family +---@param server_name string +function M.is_ignored(server_name, filetypes) + --TODO: this is easy to be made configurable once stable + filetypes = filetypes or get_supported_filetypes(server_name) + + if vim.tbl_contains(filetypes, "javascript") then + if server_name == "tsserver" then + return false + else + return true + end + end + + local blacklist = { + "jedi_language_server", + "pylsp", + "sqlls", + "sqls", + "angularls", + "ansiblels", + } + return vim.tbl_contains(blacklist, server_name) +end + +---Generates an ftplugin file based on the server_name in the selected directory +---@param server_name string name of a valid language server, e.g. pyright, gopls, tsserver, etc. +---@param dir string the full path to the desired directory +function M.generate_ftplugin(server_name, dir) + -- we need to go through lspconfig to get the corresponding filetypes currently + local filetypes = get_supported_filetypes(server_name) or {} + if not filetypes then + return + end + + if M.is_ignored(server_name, filetypes) then + return + end + + -- print("got associated filetypes: " .. vim.inspect(filetypes)) + + for _, filetype in ipairs(filetypes) do + local filename = join_paths(dir, filetype .. ".lua") + local setup_cmd = string.format([[require("lvim.lsp.manager").setup(%q)]], server_name) + -- print("using setup_cmd: " .. setup_cmd) + -- overwrite the file completely + utils.write_file(filename, setup_cmd .. "\n", "a") + end +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 +function M.generate_templates(servers_names) + servers_names = servers_names or {} + + 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) + 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") + end + + for _, server in ipairs(servers_names) do + M.generate_ftplugin(server, ftplugin_dir) + end + Log:debug "Templates installation is complete" +end + +return M diff --git a/lua/lvim/lsp/utils.lua b/lua/lvim/lsp/utils.lua new file mode 100644 index 00000000..a34fbf44 --- /dev/null +++ b/lua/lvim/lsp/utils.lua @@ -0,0 +1,62 @@ +local M = {} + +local tbl = require "lvim.utils.table" + +function M.is_client_active(name) + local clients = vim.lsp.get_active_clients() + return tbl.find_first(clients, function(client) + return client.name == name + end) +end + +function M.get_active_clients_by_ft(filetype) + local matches = {} + local clients = vim.lsp.get_active_clients() + for _, client in pairs(clients) do + local supported_filetypes = client.config.filetypes or {} + if client.name ~= "null-ls" and vim.tbl_contains(supported_filetypes, filetype) then + table.insert(matches, client) + end + end + return matches +end + +function M.get_client_capabilities(client_id) + if not client_id then + local buf_clients = vim.lsp.buf_get_clients() + for _, buf_client in ipairs(buf_clients) do + if buf_client.name ~= "null-ls" then + client_id = buf_client.id + break + end + end + end + if not client_id then + error "Unable to determine client_id" + return + end + + local client = vim.lsp.get_client_by_id(tonumber(client_id)) + + local enabled_caps = {} + for capability, status in pairs(client.resolved_capabilities) do + if status == true then + table.insert(enabled_caps, capability) + end + end + + return enabled_caps +end + +function M.get_supported_filetypes(server_name) + -- print("got filetypes query request for: " .. server_name) + local configs = require "lspconfig/configs" + pcall(require, ("lspconfig/" .. server_name)) + for _, config in pairs(configs) do + if config.name == server_name then + return config.document_config.default_config.filetypes or {} + end + end +end + +return M diff --git a/lua/lvim/lualine/themes/onedarker.lua b/lua/lvim/lualine/themes/onedarker.lua new file mode 100644 index 00000000..396657bb --- /dev/null +++ b/lua/lvim/lualine/themes/onedarker.lua @@ -0,0 +1,35 @@ +-- Copyright (c) 2020-2021 shadmansaleh +-- MIT license, see LICENSE for more details. +-- Credit: Zoltan Dalmadi(lightline) +-- LuaFormatter off +local colors = { + blue = "#61afef", + green = "#98c379", + purple = "#c678dd", + red1 = "#e06c75", + red2 = "#be5046", + yellow = "#e5c07b", + orange = "#D19A66", + fg = "#abb2bf", + bg = "#282c34", + gray1 = "#5c6370", + gray2 = "#2c323d", + gray3 = "#3e4452", +} +-- LuaFormatter on +return { + normal = { + a = { fg = colors.fg, bg = colors.blue, gui = "bold" }, + b = { fg = colors.fg, bg = colors.bg }, + c = { fg = colors.fg, bg = colors.bg }, + }, + insert = { a = { fg = colors.fg, bg = colors.green, gui = "bold" } }, + visual = { a = { fg = colors.fg, bg = colors.purple, gui = "bold" } }, + command = { a = { fg = colors.fg, bg = colors.yellow, gui = "bold" } }, + replace = { a = { fg = colors.fg, bg = colors.red1, gui = "bold" } }, + inactive = { + a = { fg = colors.gray1, bg = colors.bg, gui = "bold" }, + b = { fg = colors.gray1, bg = colors.bg }, + c = { fg = colors.gray1, bg = colors.bg }, + }, +} diff --git a/lua/lvim/plugin-loader.lua b/lua/lvim/plugin-loader.lua new file mode 100644 index 00000000..feef7ea7 --- /dev/null +++ b/lua/lvim/plugin-loader.lua @@ -0,0 +1,63 @@ +local plugin_loader = {} + +local utils = require "lvim.utils" +local Log = require "lvim.core.log" +-- we need to reuse this outside of init() +local compile_path = get_config_dir() .. "/plugin/packer_compiled.lua" + +function plugin_loader:init(opts) + opts = opts or {} + + local install_path = opts.install_path or vim.fn.stdpath "data" .. "/site/pack/packer/start/packer.nvim" + local package_root = opts.package_root or vim.fn.stdpath "data" .. "/site/pack" + + if vim.fn.empty(vim.fn.glob(install_path)) > 0 then + vim.fn.system { "git", "clone", "--depth", "1", "https://github.com/wbthomason/packer.nvim", install_path } + vim.cmd "packadd packer.nvim" + end + + local packer_ok, packer = pcall(require, "packer") + if not packer_ok then + return + end + + packer.init { + package_root = package_root, + compile_path = compile_path, + git = { clone_timeout = 300 }, + display = { + open_fn = function() + return require("packer.util").float { border = "rounded" } + end, + }, + } + + self.packer = packer + return self +end + +function plugin_loader:cache_clear() + if vim.fn.delete(compile_path) == 0 then + Log:debug "deleted packer_compiled.lua" + end +end + +function plugin_loader:cache_reset() + self.cache_clear() + require("packer").compile() + if utils.is_file(compile_path) then + Log:debug "generated packer_compiled.lua" + end +end + +function plugin_loader:load(configurations) + return self.packer.startup(function(use) + for _, plugins in ipairs(configurations) do + for _, plugin in ipairs(plugins) do + use(plugin) + end + end + end) +end + +return plugin_loader diff --git a/lua/lvim/plugins.lua b/lua/lvim/plugins.lua new file mode 100644 index 00000000..fcb23328 --- /dev/null +++ b/lua/lvim/plugins.lua @@ -0,0 +1,180 @@ +return { + -- Packer can manage itself as an optional plugin + { "wbthomason/packer.nvim" }, + { "neovim/nvim-lspconfig" }, + { "tamago324/nlsp-settings.nvim" }, + { "jose-elias-alvarez/null-ls.nvim" }, + { "antoinemadec/FixCursorHold.nvim" }, -- Needed while issue https://github.com/neovim/neovim/issues/12587 is still open + { + "williamboman/nvim-lsp-installer", + }, + + { "nvim-lua/popup.nvim" }, + { "nvim-lua/plenary.nvim" }, + -- Telescope + { + "nvim-telescope/telescope.nvim", + config = function() + require("lvim.core.telescope").setup() + end, + disable = not lvim.builtin.telescope.active, + }, + -- Install nvim-cmp, and buffer source as a dependency + { + "hrsh7th/nvim-cmp", + config = function() + require("lvim.core.cmp").setup() + end, + requires = { + "L3MON4D3/LuaSnip", + "saadparwaiz1/cmp_luasnip", + "hrsh7th/cmp-buffer", + "hrsh7th/cmp-nvim-lsp", + "hrsh7th/cmp-path", + "hrsh7th/cmp-nvim-lua", + }, + run = function() + -- cmp's config requires cmp to be installed to run the first time + if not lvim.builtin.cmp then + require("lvim.core.cmp").config() + end + end, + }, + { + "rafamadriz/friendly-snippets", + -- event = "InsertCharPre", + -- disable = not lvim.builtin.compe.active, + }, + + -- Autopairs + { + "windwp/nvim-autopairs", + -- event = "InsertEnter", + config = function() + require("lvim.core.autopairs").setup() + end, + disable = not lvim.builtin.autopairs.active, + }, + + -- Treesitter + { + "nvim-treesitter/nvim-treesitter", + branch = "0.5-compat", + -- run = ":TSUpdate", + config = function() + require("lvim.core.treesitter").setup() + end, + }, + + -- NvimTree + { + "kyazdani42/nvim-tree.lua", + -- event = "BufWinOpen", + -- cmd = "NvimTreeToggle", + -- commit = "fd7f60e242205ea9efc9649101c81a07d5f458bb", + config = function() + require("lvim.core.nvimtree").setup() + end, + disable = not lvim.builtin.nvimtree.active, + }, + + { + "lewis6991/gitsigns.nvim", + + config = function() + require("lvim.core.gitsigns").setup() + end, + event = "BufRead", + disable = not lvim.builtin.gitsigns.active, + }, + + -- Whichkey + { + "folke/which-key.nvim", + config = function() + require("lvim.core.which-key").setup() + end, + event = "BufWinEnter", + disable = not lvim.builtin.which_key.active, + }, + + -- Comments + { + "terrortylor/nvim-comment", + event = "BufRead", + config = function() + require("lvim.core.comment").setup() + end, + disable = not lvim.builtin.comment.active, + }, + + -- project.nvim + { + "ahmedkhalf/project.nvim", + config = function() + require("lvim.core.project").setup() + end, + disable = not lvim.builtin.project.active, + }, + + -- Icons + { "kyazdani42/nvim-web-devicons" }, + + -- Status Line and Bufferline + { + -- "hoob3rt/lualine.nvim", + "shadmansaleh/lualine.nvim", + -- "Lunarvim/lualine.nvim", + config = function() + require("lvim.core.lualine").setup() + end, + disable = not lvim.builtin.lualine.active, + }, + + { + "romgrk/barbar.nvim", + config = function() + require("lvim.core.bufferline").setup() + end, + event = "BufWinEnter", + disable = not lvim.builtin.bufferline.active, + }, + + -- Debugging + { + "mfussenegger/nvim-dap", + -- event = "BufWinEnter", + config = function() + require("lvim.core.dap").setup() + end, + disable = not lvim.builtin.dap.active, + }, + + -- Debugger management + { + "Pocco81/DAPInstall.nvim", + -- event = "BufWinEnter", + -- event = "BufRead", + disable = not lvim.builtin.dap.active, + }, + + -- Dashboard + { + "ChristianChiarulli/dashboard-nvim", + event = "BufWinEnter", + config = function() + require("lvim.core.dashboard").setup() + end, + disable = not lvim.builtin.dashboard.active, + }, + + -- Terminal + { + "akinsho/toggleterm.nvim", + event = "BufWinEnter", + config = function() + require("lvim.core.terminal").setup() + end, + disable = not lvim.builtin.terminal.active, + }, +} diff --git a/lua/lvim/utils/ft.lua b/lua/lvim/utils/ft.lua new file mode 100644 index 00000000..e9852e6f --- /dev/null +++ b/lua/lvim/utils/ft.lua @@ -0,0 +1,47 @@ +-- Here be dragons +-- Opening files with telescope will not start LSP without this +local ft = {} + +ft.find_lua_ftplugins = function(filetype) + local patterns = { + string.format("ftplugin/%s.lua", filetype), + + -- Looks like we don't need this, because the first one works + -- string.format("after/ftplugin/%s.lua", filetype), + } + + local result = {} + for _, pat in ipairs(patterns) do + vim.list_extend(result, vim.api.nvim_get_runtime_file(pat, true)) + end + + return result +end + +ft.do_filetype = function(filetype) + local ftplugins = ft.find_lua_ftplugins(filetype) + + local f_env = setmetatable({ + -- Override print, so the prints still go through, otherwise it's confusing for people + print = vim.schedule_wrap(print), + }, { + -- Buf default back read/write to whatever is going on in the global landscape + __index = _G, + __newindex = _G, + }) + + for _, file in ipairs(ftplugins) do + local f = loadfile(file) + if not f then + vim.api.nvim_err_writeln("Unable to load file: " .. file) + else + local ok, msg = pcall(setfenv(f, f_env)) + + if not ok then + vim.api.nvim_err_writeln("Error while processing file: " .. file .. "\n" .. msg) + end + end + end +end + +return ft diff --git a/lua/lvim/utils/hooks.lua b/lua/lvim/utils/hooks.lua new file mode 100644 index 00000000..d536bc76 --- /dev/null +++ b/lua/lvim/utils/hooks.lua @@ -0,0 +1,35 @@ +local M = {} + +local Log = require "lvim.core.log" +local in_headless = #vim.api.nvim_list_uis() == 0 + +function M.run_pre_update() + Log:debug "Starting pre-update hook" + _G.__luacache.clear_cache() +end + +---Reset any startup cache files used by Packer and Impatient +---It also forces regenerating any template ftplugin files +---Tip: Useful for clearing any outdated settings +function M.reset_cache() + _G.__luacache.clear_cache() + require("lvim.plugin-loader"):cache_reset() + package.loaded["lvim.lsp.templates"] = nil + require("lvim.lsp.templates").generate_templates() +end + +function M.run_post_update() + Log:debug "Starting post-update hook" + M.reset_cache() + + 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 diff --git a/lua/lvim/utils/init.lua b/lua/lvim/utils/init.lua new file mode 100644 index 00000000..cebbe75c --- /dev/null +++ b/lua/lvim/utils/init.lua @@ -0,0 +1,205 @@ +local utils = {} +local Log = require "lvim.core.log" +local uv = vim.loop + +-- recursive Print (structure, limit, separator) +local function r_inspect_settings(structure, limit, separator) + limit = limit or 100 -- default item limit + separator = separator or "." -- indent string + if limit < 1 then + print "ERROR: Item limit reached." + return limit - 1 + end + if structure == nil then + io.write("-- O", separator:sub(2), " = nil\n") + return limit - 1 + end + local ts = type(structure) + + if ts == "table" then + for k, v in pairs(structure) do + -- replace non alpha keys with ["key"] + if tostring(k):match "[^%a_]" then + k = '["' .. tostring(k) .. '"]' + end + limit = r_inspect_settings(v, limit, separator .. "." .. tostring(k)) + if limit < 0 then + break + end + end + return limit + end + + if ts == "string" then + -- escape sequences + structure = string.format("%q", structure) + end + separator = separator:gsub("%.%[", "%[") + if type(structure) == "function" then + -- don't print functions + io.write("-- lvim", separator:sub(2), " = function ()\n") + else + io.write("lvim", separator:sub(2), " = ", tostring(structure), "\n") + end + return limit - 1 +end + +function utils.generate_settings() + -- Opens a file in append mode + local file = io.open("lv-settings.lua", "w") + + -- sets the default output file as test.lua + io.output(file) + + -- write all `lvim` related settings to `lv-settings.lua` file + r_inspect_settings(lvim, 10000, ".") + + -- closes the open file + io.close(file) +end + +-- autoformat +function utils.toggle_autoformat() + if lvim.format_on_save then + require("lvim.core.autocmds").define_augroups { + autoformat = { + { + "BufWritePre", + "*", + ":silent lua vim.lsp.buf.formatting_sync()", + }, + }, + } + Log:debug "Format on save active" + end + + if not lvim.format_on_save then + vim.cmd [[ + if exists('#autoformat#BufWritePre') + :autocmd! autoformat + endif + ]] + Log:debug "Format on save off" + end +end + +function utils.unrequire(m) + package.loaded[m] = nil + _G[m] = nil +end + +function utils.gsub_args(args) + if args == nil or type(args) ~= "table" then + return args + end + local buffer_filepath = vim.fn.fnameescape(vim.api.nvim_buf_get_name(0)) + for i = 1, #args do + args[i] = string.gsub(args[i], "${FILEPATH}", buffer_filepath) + end + return args +end + +--- Returns a table with the default values that are missing. +--- either paramter can be empty. +--@param config (table) table containing entries that take priority over defaults +--@param default_config (table) table contatining default values if found +function utils.apply_defaults(config, default_config) + config = config or {} + default_config = default_config or {} + local new_config = vim.tbl_deep_extend("keep", vim.empty_dict(), config) + new_config = vim.tbl_deep_extend("keep", new_config, default_config) + return new_config +end + +--- Checks whether a given path exists and is a file. +--@param path (string) path to check +--@returns (bool) +function utils.is_file(path) + local stat = uv.fs_stat(path) + return stat and stat.type == "file" or false +end + +--- Checks whether a given path exists and is a directory +--@param path (string) path to check +--@returns (bool) +function utils.is_directory(path) + local stat = uv.fs_stat(path) + return stat and stat.type == "directory" or false +end + +utils.join_paths = _G.join_paths + +function utils.write_file(path, txt, flag) + uv.fs_open(path, flag, 438, function(open_err, fd) + assert(not open_err, open_err) + uv.fs_write(fd, txt, -1, function(write_err) + assert(not write_err, write_err) + uv.fs_close(fd, function(close_err) + assert(not close_err, close_err) + end) + end) + end) +end + +function utils.debounce(ms, fn) + local timer = vim.loop.new_timer() + return function(...) + local argv = { ... } + timer:start(ms, 0, function() + timer:stop() + vim.schedule_wrap(fn)(unpack(argv)) + end) + end +end + +function utils.search_file(file, args) + local Job = require "plenary.job" + local stderr = {} + local stdout, ret = Job + :new({ + command = "grep", + args = { args, file }, + cwd = get_cache_dir(), + on_stderr = function(_, data) + table.insert(stderr, data) + end, + }) + :sync() + return stdout, ret, stderr +end + +function utils.file_contains(file, query) + local stdout, ret, stderr = utils.search_file(file, query) + if ret == 0 then + return true + end + if not vim.tbl_isempty(stderr) then + error(vim.inspect(stderr)) + end + if not vim.tbl_isempty(stdout) then + error(vim.inspect(stdout)) + end + return false +end + +function utils.log_contains(query) + local logfile = require("lvim.core.log"):get_path() + local stdout, ret, stderr = utils.search_file(logfile, query) + if ret == 0 then + return true + end + if not vim.tbl_isempty(stderr) then + error(vim.inspect(stderr)) + end + if not vim.tbl_isempty(stdout) then + error(vim.inspect(stdout)) + end + if not vim.tbl_isempty(stderr) then + error(vim.inspect(stderr)) + end + return false +end + +return utils + +-- TODO: find a new home for these autocommands diff --git a/lua/lvim/utils/table.lua b/lua/lvim/utils/table.lua new file mode 100644 index 00000000..1ac5949e --- /dev/null +++ b/lua/lvim/utils/table.lua @@ -0,0 +1,24 @@ +local Table = {} + +--- Find the first entry for which the predicate returns true. +-- @param t The table +-- @param predicate The function called for each entry of t +-- @return The entry for which the predicate returned True or nil +function Table.find_first(t, predicate) + for _, entry in pairs(t) do + if predicate(entry) then + return entry + end + end + return nil +end + +--- Check if the predicate returns True for at least one entry of the table. +-- @param t The table +-- @param predicate The function called for each entry of t +-- @return True if predicate returned True at least once, false otherwise +function Table.contains(t, predicate) + return Table.find_first(t, predicate) ~= nil +end + +return Table diff --git a/lua/plugin-loader.lua b/lua/plugin-loader.lua deleted file mode 100644 index c20dd21a..00000000 --- a/lua/plugin-loader.lua +++ /dev/null @@ -1,63 +0,0 @@ -local plugin_loader = {} - -local utils = require "utils" -local Log = require "core.log" --- we need to reuse this outside of init() -local compile_path = get_config_dir() .. "/plugin/packer_compiled.lua" - -function plugin_loader:init(opts) - opts = opts or {} - - local install_path = opts.install_path or vim.fn.stdpath "data" .. "/site/pack/packer/start/packer.nvim" - local package_root = opts.package_root or vim.fn.stdpath "data" .. "/site/pack" - - if vim.fn.empty(vim.fn.glob(install_path)) > 0 then - vim.fn.system { "git", "clone", "--depth", "1", "https://github.com/wbthomason/packer.nvim", install_path } - vim.cmd "packadd packer.nvim" - end - - local packer_ok, packer = pcall(require, "packer") - if not packer_ok then - return - end - - packer.init { - package_root = package_root, - compile_path = compile_path, - git = { clone_timeout = 300 }, - display = { - open_fn = function() - return require("packer.util").float { border = "rounded" } - end, - }, - } - - self.packer = packer - return self -end - -function plugin_loader:cache_clear() - if vim.fn.delete(compile_path) == 0 then - Log:debug "deleted packer_compiled.lua" - end -end - -function plugin_loader:cache_reset() - self.cache_clear() - require("packer").compile() - if utils.is_file(compile_path) then - Log:debug "generated packer_compiled.lua" - end -end - -function plugin_loader:load(configurations) - return self.packer.startup(function(use) - for _, plugins in ipairs(configurations) do - for _, plugin in ipairs(plugins) do - use(plugin) - end - end - end) -end - -return plugin_loader diff --git a/lua/plugins.lua b/lua/plugins.lua deleted file mode 100644 index 923ff7c2..00000000 --- a/lua/plugins.lua +++ /dev/null @@ -1,180 +0,0 @@ -return { - -- Packer can manage itself as an optional plugin - { "wbthomason/packer.nvim" }, - { "neovim/nvim-lspconfig" }, - { "tamago324/nlsp-settings.nvim" }, - { "jose-elias-alvarez/null-ls.nvim" }, - { "antoinemadec/FixCursorHold.nvim" }, -- Needed while issue https://github.com/neovim/neovim/issues/12587 is still open - { - "williamboman/nvim-lsp-installer", - }, - - { "nvim-lua/popup.nvim" }, - { "nvim-lua/plenary.nvim" }, - -- Telescope - { - "nvim-telescope/telescope.nvim", - config = function() - require("core.telescope").setup() - end, - disable = not lvim.builtin.telescope.active, - }, - -- Install nvim-cmp, and buffer source as a dependency - { - "hrsh7th/nvim-cmp", - config = function() - require("core.cmp").setup() - end, - requires = { - "L3MON4D3/LuaSnip", - "saadparwaiz1/cmp_luasnip", - "hrsh7th/cmp-buffer", - "hrsh7th/cmp-nvim-lsp", - "hrsh7th/cmp-path", - "hrsh7th/cmp-nvim-lua", - }, - run = function() - -- cmp's config requires cmp to be installed to run the first time - if not lvim.builtin.cmp then - require("core.cmp").config() - end - end, - }, - { - "rafamadriz/friendly-snippets", - -- event = "InsertCharPre", - -- disable = not lvim.builtin.compe.active, - }, - - -- Autopairs - { - "windwp/nvim-autopairs", - -- event = "InsertEnter", - config = function() - require("core.autopairs").setup() - end, - disable = not lvim.builtin.autopairs.active, - }, - - -- Treesitter - { - "nvim-treesitter/nvim-treesitter", - branch = "0.5-compat", - -- run = ":TSUpdate", - config = function() - require("core.treesitter").setup() - end, - }, - - -- NvimTree - { - "kyazdani42/nvim-tree.lua", - -- event = "BufWinOpen", - -- cmd = "NvimTreeToggle", - -- commit = "fd7f60e242205ea9efc9649101c81a07d5f458bb", - config = function() - require("core.nvimtree").setup() - end, - disable = not lvim.builtin.nvimtree.active, - }, - - { - "lewis6991/gitsigns.nvim", - - config = function() - require("core.gitsigns").setup() - end, - event = "BufRead", - disable = not lvim.builtin.gitsigns.active, - }, - - -- Whichkey - { - "folke/which-key.nvim", - config = function() - require("core.which-key").setup() - end, - event = "BufWinEnter", - disable = not lvim.builtin.which_key.active, - }, - - -- Comments - { - "terrortylor/nvim-comment", - event = "BufRead", - config = function() - require("core.comment").setup() - end, - disable = not lvim.builtin.comment.active, - }, - - -- project.nvim - { - "ahmedkhalf/project.nvim", - config = function() - require("core.project").setup() - end, - disable = not lvim.builtin.project.active, - }, - - -- Icons - { "kyazdani42/nvim-web-devicons" }, - - -- Status Line and Bufferline - { - -- "hoob3rt/lualine.nvim", - "shadmansaleh/lualine.nvim", - -- "Lunarvim/lualine.nvim", - config = function() - require("core.lualine").setup() - end, - disable = not lvim.builtin.lualine.active, - }, - - { - "romgrk/barbar.nvim", - config = function() - require("core.bufferline").setup() - end, - event = "BufWinEnter", - disable = not lvim.builtin.bufferline.active, - }, - - -- Debugging - { - "mfussenegger/nvim-dap", - -- event = "BufWinEnter", - config = function() - require("core.dap").setup() - end, - disable = not lvim.builtin.dap.active, - }, - - -- Debugger management - { - "Pocco81/DAPInstall.nvim", - -- event = "BufWinEnter", - -- event = "BufRead", - disable = not lvim.builtin.dap.active, - }, - - -- Dashboard - { - "ChristianChiarulli/dashboard-nvim", - event = "BufWinEnter", - config = function() - require("core.dashboard").setup() - end, - disable = not lvim.builtin.dashboard.active, - }, - - -- Terminal - { - "akinsho/toggleterm.nvim", - event = "BufWinEnter", - config = function() - require("core.terminal").setup() - end, - disable = not lvim.builtin.terminal.active, - }, -} diff --git a/lua/utils/ft.lua b/lua/utils/ft.lua deleted file mode 100644 index e9852e6f..00000000 --- a/lua/utils/ft.lua +++ /dev/null @@ -1,47 +0,0 @@ --- Here be dragons --- Opening files with telescope will not start LSP without this -local ft = {} - -ft.find_lua_ftplugins = function(filetype) - local patterns = { - string.format("ftplugin/%s.lua", filetype), - - -- Looks like we don't need this, because the first one works - -- string.format("after/ftplugin/%s.lua", filetype), - } - - local result = {} - for _, pat in ipairs(patterns) do - vim.list_extend(result, vim.api.nvim_get_runtime_file(pat, true)) - end - - return result -end - -ft.do_filetype = function(filetype) - local ftplugins = ft.find_lua_ftplugins(filetype) - - local f_env = setmetatable({ - -- Override print, so the prints still go through, otherwise it's confusing for people - print = vim.schedule_wrap(print), - }, { - -- Buf default back read/write to whatever is going on in the global landscape - __index = _G, - __newindex = _G, - }) - - for _, file in ipairs(ftplugins) do - local f = loadfile(file) - if not f then - vim.api.nvim_err_writeln("Unable to load file: " .. file) - else - local ok, msg = pcall(setfenv(f, f_env)) - - if not ok then - vim.api.nvim_err_writeln("Error while processing file: " .. file .. "\n" .. msg) - end - end - end -end - -return ft diff --git a/lua/utils/hooks.lua b/lua/utils/hooks.lua deleted file mode 100644 index fa667cfd..00000000 --- a/lua/utils/hooks.lua +++ /dev/null @@ -1,33 +0,0 @@ -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 diff --git a/lua/utils/init.lua b/lua/utils/init.lua deleted file mode 100644 index eaac54f4..00000000 --- a/lua/utils/init.lua +++ /dev/null @@ -1,237 +0,0 @@ -local utils = {} -local Log = require "core.log" -local uv = vim.loop - --- recursive Print (structure, limit, separator) -local function r_inspect_settings(structure, limit, separator) - limit = limit or 100 -- default item limit - separator = separator or "." -- indent string - if limit < 1 then - print "ERROR: Item limit reached." - return limit - 1 - end - if structure == nil then - io.write("-- O", separator:sub(2), " = nil\n") - return limit - 1 - end - local ts = type(structure) - - if ts == "table" then - for k, v in pairs(structure) do - -- replace non alpha keys with ["key"] - if tostring(k):match "[^%a_]" then - k = '["' .. tostring(k) .. '"]' - end - limit = r_inspect_settings(v, limit, separator .. "." .. tostring(k)) - if limit < 0 then - break - end - end - return limit - end - - if ts == "string" then - -- escape sequences - structure = string.format("%q", structure) - end - separator = separator:gsub("%.%[", "%[") - if type(structure) == "function" then - -- don't print functions - io.write("-- lvim", separator:sub(2), " = function ()\n") - else - io.write("lvim", separator:sub(2), " = ", tostring(structure), "\n") - end - return limit - 1 -end - -function utils.generate_settings() - -- Opens a file in append mode - local file = io.open("lv-settings.lua", "w") - - -- sets the default output file as test.lua - io.output(file) - - -- write all `lvim` related settings to `lv-settings.lua` file - r_inspect_settings(lvim, 10000, ".") - - -- closes the open file - io.close(file) -end - --- autoformat -function utils.toggle_autoformat() - if lvim.format_on_save then - require("core.autocmds").define_augroups { - autoformat = { - { - "BufWritePre", - "*", - ":silent lua vim.lsp.buf.formatting_sync()", - }, - }, - } - Log:debug "Format on save active" - end - - if not lvim.format_on_save then - vim.cmd [[ - if exists('#autoformat#BufWritePre') - :autocmd! autoformat - endif - ]] - Log:debug "Format on save off" - end -end - -function utils.reload_lv_config() - require("core.lualine").config() - - local config = require "config" - config:load() - - require("keymappings").setup() -- this should be done before loading the plugins - vim.cmd("source " .. utils.join_paths(get_runtime_dir(), "lvim", "lua", "plugins.lua")) - local plugins = require "plugins" - utils.toggle_autoformat() - local plugin_loader = require "plugin-loader" - plugin_loader:cache_reset() - plugin_loader:load { plugins, lvim.plugins } - vim.cmd ":PackerInstall" - vim.cmd ":PackerCompile" - -- vim.cmd ":PackerClean" - require("lsp").setup() - Log:info "Reloaded configuration" -end - -function utils.unrequire(m) - package.loaded[m] = nil - _G[m] = nil -end - -function utils.gsub_args(args) - if args == nil or type(args) ~= "table" then - return args - end - local buffer_filepath = vim.fn.fnameescape(vim.api.nvim_buf_get_name(0)) - for i = 1, #args do - args[i] = string.gsub(args[i], "${FILEPATH}", buffer_filepath) - end - return args -end - ---- Returns a table with the default values that are missing. ---- either paramter can be empty. ---@param config (table) table containing entries that take priority over defaults ---@param default_config (table) table contatining default values if found -function utils.apply_defaults(config, default_config) - config = config or {} - default_config = default_config or {} - local new_config = vim.tbl_deep_extend("keep", vim.empty_dict(), config) - new_config = vim.tbl_deep_extend("keep", new_config, default_config) - return new_config -end - ---- Checks whether a given path exists and is a file. ---@param path (string) path to check ---@returns (bool) -function utils.is_file(path) - local stat = uv.fs_stat(path) - return stat and stat.type == "file" or false -end - ---- Checks whether a given path exists and is a directory ---@param path (string) path to check ---@returns (bool) -function utils.is_directory(path) - local stat = uv.fs_stat(path) - return stat and stat.type == "directory" or false -end - -function utils.write_file(path, txt, flag) - uv.fs_open(path, flag, 438, function(open_err, fd) - assert(not open_err, open_err) - uv.fs_write(fd, txt, -1, function(write_err) - assert(not write_err, write_err) - uv.fs_close(fd, function(close_err) - assert(not close_err, close_err) - end) - end) - end) -end - -utils.join_paths = _G.join_paths - -function utils.write_file(path, txt, flag) - uv.fs_open(path, flag, 438, function(open_err, fd) - assert(not open_err, open_err) - uv.fs_write(fd, txt, -1, function(write_err) - assert(not write_err, write_err) - uv.fs_close(fd, function(close_err) - assert(not close_err, close_err) - end) - end) - end) -end - -function utils.debounce(ms, fn) - local timer = vim.loop.new_timer() - return function(...) - local argv = { ... } - timer:start(ms, 0, function() - timer:stop() - vim.schedule_wrap(fn)(unpack(argv)) - end) - end -end - -function utils.search_file(file, args) - local Job = require "plenary.job" - local stderr = {} - local stdout, ret = Job - :new({ - command = "grep", - args = { args, file }, - cwd = get_cache_dir(), - on_stderr = function(_, data) - table.insert(stderr, data) - end, - }) - :sync() - return stdout, ret, stderr -end - -function utils.file_contains(file, query) - local stdout, ret, stderr = utils.search_file(file, query) - if ret == 0 then - return true - end - if not vim.tbl_isempty(stderr) then - error(vim.inspect(stderr)) - end - if not vim.tbl_isempty(stdout) then - error(vim.inspect(stdout)) - end - return false -end - -function utils.log_contains(query) - local logfile = require("core.log"):get_path() - local stdout, ret, stderr = utils.search_file(logfile, query) - if ret == 0 then - return true - end - if not vim.tbl_isempty(stderr) then - error(vim.inspect(stderr)) - end - if not vim.tbl_isempty(stdout) then - error(vim.inspect(stdout)) - end - if not vim.tbl_isempty(stderr) then - error(vim.inspect(stderr)) - end - return false -end - -return utils - --- TODO: find a new home for these autocommands diff --git a/lua/utils/table.lua b/lua/utils/table.lua deleted file mode 100644 index 1ac5949e..00000000 --- a/lua/utils/table.lua +++ /dev/null @@ -1,24 +0,0 @@ -local Table = {} - ---- Find the first entry for which the predicate returns true. --- @param t The table --- @param predicate The function called for each entry of t --- @return The entry for which the predicate returned True or nil -function Table.find_first(t, predicate) - for _, entry in pairs(t) do - if predicate(entry) then - return entry - end - end - return nil -end - ---- Check if the predicate returns True for at least one entry of the table. --- @param t The table --- @param predicate The function called for each entry of t --- @return True if predicate returned True at least once, false otherwise -function Table.contains(t, predicate) - return Table.find_first(t, predicate) ~= nil -end - -return Table -- cgit v1.2.3 From fdec599954dcc093e56522c4f9dcb126ad869979 Mon Sep 17 00:00:00 2001 From: Abouzar Parvan Date: Mon, 11 Oct 2021 11:53:30 +0330 Subject: fix: core.telescope has migrated to lvim.core.telescope Fixes #1739 --- lua/lvim/core/which-key.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lua') diff --git a/lua/lvim/core/which-key.lua b/lua/lvim/core/which-key.lua index 15f63273..eebdc27b 100644 --- a/lua/lvim/core/which-key.lua +++ b/lua/lvim/core/which-key.lua @@ -139,7 +139,7 @@ M.config = function() l = { name = "LSP", - a = { "lua require('core.telescope').code_actions()", "Code Action" }, + a = { "lua require('lvim.core.telescope').code_actions()", "Code Action" }, d = { "Telescope lsp_document_diagnostics", "Document Diagnostics", -- cgit v1.2.3 From 965ea4bbb902d2f58108c5c01fcb6442e6aff51b Mon Sep 17 00:00:00 2001 From: Abouzar Parvan Date: Mon, 11 Oct 2021 20:05:43 +0330 Subject: fix: correct floating window position in Neovim 0.6 nightly (#1732) --- lua/lvim/plugins.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lua') diff --git a/lua/lvim/plugins.lua b/lua/lvim/plugins.lua index fcb23328..44fc4dd3 100644 --- a/lua/lvim/plugins.lua +++ b/lua/lvim/plugins.lua @@ -89,8 +89,10 @@ return { }, -- Whichkey + -- TODO: change back to folke/which-key.nvim after folke got back { - "folke/which-key.nvim", + "abzcoding/which-key.nvim", + branch = "fix/neovim-6-position", config = function() require("lvim.core.which-key").setup() end, -- cgit v1.2.3 From 3dc24cd0c32801afd44c0451932f8245cdf10a49 Mon Sep 17 00:00:00 2001 From: Abouzar Parvan Date: Mon, 11 Oct 2021 20:10:59 +0330 Subject: [Feature] use `Comment.nvim` instead of `nvim-comment` (#1736) --- lua/lvim/core/comment.lua | 66 ++++++++++++++++++++++++++++++++++++--------- lua/lvim/core/which-key.lua | 4 +-- lua/lvim/plugins.lua | 2 +- 3 files changed, 56 insertions(+), 16 deletions(-) (limited to 'lua') diff --git a/lua/lvim/core/comment.lua b/lua/lvim/core/comment.lua index b98410ab..0b454074 100644 --- a/lua/lvim/core/comment.lua +++ b/lua/lvim/core/comment.lua @@ -1,26 +1,66 @@ 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() + end + end lvim.builtin.comment = { active = true, on_config_done = nil, - -- Linters prefer comment and line to have a space in between markers - marker_padding = true, - -- should comment out empty or whitespace only lines - comment_empty = false, - -- Should key mappings be created - create_mappings = true, - -- Normal mode mapping left hand side - line_mapping = "gcc", - -- Visual/Operator mapping left hand side - operator_mapping = "gc", - -- Hook function to call before commenting takes place - hook = nil, + ---Add a space b/w comment and the line + ---@type boolean + padding = true, + + ---Lines to be ignored while comment/uncomment. + ---Could be a regex string or a function that returns a regex string. + ---Example: Use '^$' to ignore empty lines + ---@type string|function + ignore = "^$", + + ---Whether to create basic (operator-pending) and extra mappings for NORMAL/VISUAL mode + ---@type table + mappings = { + ---operator-pending mapping + ---Includes `gcc`, `gcb`, `gc[count]{motion}` and `gb[count]{motion}` + basic = true, + ---extended mapping + ---Includes `g>`, `g<`, `g>[count]{motion}` and `g<[count]{motion}` + extra = false, + }, + + ---LHS of line and block comment toggle mapping in NORMAL/VISUAL mode + ---@type table + toggler = { + ---line-comment toggle + line = "gcc", + ---block-comment toggle + block = "gbc", + }, + + ---LHS of line and block comment operator-mode mapping in NORMAL/VISUAL mode + ---@type table + opleader = { + ---line-comment opfunc mapping + line = "gc", + ---block-comment opfunc mapping + block = "gb", + }, + + ---Pre-hook, called before commenting the line + ---@type function|nil + pre_hook = pre_hook, + + ---Post-hook, called after commenting is done + ---@type function|nil + post_hook = nil, } end function M.setup() - local nvim_comment = require "nvim_comment" + local nvim_comment = require "Comment" nvim_comment.setup(lvim.builtin.comment) if lvim.builtin.comment.on_config_done then diff --git a/lua/lvim/core/which-key.lua b/lua/lvim/core/which-key.lua index eebdc27b..528c7600 100644 --- a/lua/lvim/core/which-key.lua +++ b/lua/lvim/core/which-key.lua @@ -61,12 +61,12 @@ M.config = function() -- NOTE: Prefer using : over as the latter avoids going back in normal-mode. -- see https://neovim.io/doc/user/map.html#:map-cmd vmappings = { - ["/"] = { ":CommentToggle", "Comment" }, + ["/"] = { "lua ___comment_gc(vim.fn.visualmode())", "Comment" }, }, mappings = { ["w"] = { "w!", "Save" }, ["q"] = { "q!", "Quit" }, - ["/"] = { "CommentToggle", "Comment" }, + ["/"] = { "lua require('Comment').toggle()", "Comment" }, ["c"] = { "BufferClose!", "Close Buffer" }, ["f"] = { "Telescope find_files", "Find File" }, ["h"] = { "nohlsearch", "No Highlight" }, diff --git a/lua/lvim/plugins.lua b/lua/lvim/plugins.lua index 44fc4dd3..84522366 100644 --- a/lua/lvim/plugins.lua +++ b/lua/lvim/plugins.lua @@ -102,7 +102,7 @@ return { -- Comments { - "terrortylor/nvim-comment", + "numToStr/Comment.nvim", event = "BufRead", config = function() require("lvim.core.comment").setup() -- cgit v1.2.3 From 5deb0e57ce083fa836762b34e36ff48fbd3a535c Mon Sep 17 00:00:00 2001 From: James Walmsley Date: Tue, 12 Oct 2021 16:12:55 +0100 Subject: bugfix: Ensure lvim table is valid before calling Log:warn() (#1742) Co-authored-by: kylo252 <59826753+kylo252@users.noreply.github.com> --- lua/lvim/bootstrap.lua | 8 +------- lua/lvim/config/init.lua | 16 +++++++--------- 2 files changed, 8 insertions(+), 16 deletions(-) (limited to 'lua') diff --git a/lua/lvim/bootstrap.lua b/lua/lvim/bootstrap.lua index 46c044ae..ab29bca2 100644 --- a/lua/lvim/bootstrap.lua +++ b/lua/lvim/bootstrap.lua @@ -109,13 +109,7 @@ function M:init() } end - require("lvim.config"):init { - config_dir = self.config_dir, - } - local config = require "lvim.config" - config:init { - user_config = join_paths(self.config_dir, "config.lua"), - } + require("lvim.config"):init() require("lvim.plugin-loader"):init { package_root = self.pack_dir, diff --git a/lua/lvim/config/init.lua b/lua/lvim/config/init.lua index d7877f1e..0ba0b64f 100644 --- a/lua/lvim/config/init.lua +++ b/lua/lvim/config/init.lua @@ -2,17 +2,11 @@ local utils = require "lvim.utils" local Log = require "lvim.core.log" local M = {} - local user_config_dir = get_config_dir() local user_config_file = utils.join_paths(user_config_dir, "config.lua") --- Fallback config.lua to lv-config.lua -if not utils.is_file(user_config_file) then - local lv_config = utils.join_paths(user_config_dir, "lv-config.lua") - Log:warn(string.format("[%s] not found, falling back to [%s]", user_config_file, lv_config)) - user_config_file = lv_config -end - +---Get the full path to the user configuration file +---@return string function M:get_user_config_path() return user_config_file end @@ -160,7 +154,11 @@ function M:load(config_path) config_path = config_path or self.get_user_config_path() local ok, _ = pcall(dofile, config_path) if not ok then - Log:warn("Invalid configuration: " .. config_path) + if utils.is_file(user_config_file) then + Log:warn("Invalid configuration: " .. config_path) + else + Log:warn(string.format("Unable to find configuration file [%s]", config_path)) + end end deprecation_notice() -- cgit v1.2.3 From 9e18c16b2b378792c689591190774786fd5da04c Mon Sep 17 00:00:00 2001 From: Chase Colman <5411+chase@users.noreply.github.com> Date: Tue, 12 Oct 2021 23:33:41 +0800 Subject: fix(config/log): show error in config instead of hiding (#1751) --- lua/lvim/config/init.lua | 4 ++-- lua/lvim/core/log.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lua') diff --git a/lua/lvim/config/init.lua b/lua/lvim/config/init.lua index 0ba0b64f..a7d4652b 100644 --- a/lua/lvim/config/init.lua +++ b/lua/lvim/config/init.lua @@ -152,10 +152,10 @@ end -- @param config_path The path to the configuration overrides function M:load(config_path) config_path = config_path or self.get_user_config_path() - local ok, _ = pcall(dofile, config_path) + local ok, err = pcall(dofile, config_path) if not ok then if utils.is_file(user_config_file) then - Log:warn("Invalid configuration: " .. config_path) + Log:warn("Invalid configuration: " .. err) else Log:warn(string.format("Unable to find configuration file [%s]", config_path)) end diff --git a/lua/lvim/core/log.lua b/lua/lvim/core/log.lua index fca1fcb4..3d8c0dc8 100644 --- a/lua/lvim/core/log.lua +++ b/lua/lvim/core/log.lua @@ -12,7 +12,7 @@ function Log:add_entry(msg, level) end local status_ok, plenary = pcall(require, "plenary") if status_ok then - local default_opts = { plugin = "lunarvim", level = lvim.log.level } + local default_opts = { plugin = "lunarvim", level = lvim.log.level, info_level = 4 } local handle = plenary.log.new(default_opts) handle[level:lower()](msg) self.__handle = handle -- cgit v1.2.3 From 4b0ce90a953735b18e0e059d99505519c5d344de Mon Sep 17 00:00:00 2001 From: Chase Colman <5411+chase@users.noreply.github.com> Date: Thu, 14 Oct 2021 13:03:54 +0800 Subject: fix(plenary): restore impatient caching for plenary (#1768) --- lua/lvim/bootstrap.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'lua') diff --git a/lua/lvim/bootstrap.lua b/lua/lvim/bootstrap.lua index ab29bca2..b1ecdf1c 100644 --- a/lua/lvim/bootstrap.lua +++ b/lua/lvim/bootstrap.lua @@ -103,6 +103,7 @@ function M:init() -- FIXME: currently unreliable in unit-tests if not os.getenv "LVIM_TEST_ENV" then + _G.PLENARY_DEBUG = false require("lvim.impatient").setup { path = vim.fn.stdpath "cache" .. "/lvim_cache", enable_profiling = true, -- cgit v1.2.3 From daa0b24a501939f9af7d37af12066d31f78f2df1 Mon Sep 17 00:00:00 2001 From: Robin Kautz Date: Thu, 14 Oct 2021 18:32:29 +0200 Subject: [Bugfix]: fixes custom autocommands not working (#1775) --- lua/lvim/config/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lua') diff --git a/lua/lvim/config/init.lua b/lua/lvim/config/init.lua index a7d4652b..e14f96fa 100644 --- a/lua/lvim/config/init.lua +++ b/lua/lvim/config/init.lua @@ -151,6 +151,7 @@ end --- Override the configuration with a user provided one -- @param config_path The path to the configuration overrides function M:load(config_path) + local autocmds = require "lvim.core.autocmds" config_path = config_path or self.get_user_config_path() local ok, err = pcall(dofile, config_path) if not ok then @@ -163,7 +164,6 @@ function M:load(config_path) deprecation_notice() - local autocmds = require "lvim.core.autocmds" autocmds.define_augroups(lvim.autocommands) local settings = require "lvim.config.settings" -- cgit v1.2.3 From f87416c141de0909a05f1d1cad162a9774def549 Mon Sep 17 00:00:00 2001 From: kylo252 <59826753+kylo252@users.noreply.github.com> Date: Thu, 14 Oct 2021 18:58:56 +0200 Subject: fix(null-ls): add common lsp-setup hooks (#1763) --- lua/lvim/lsp/null-ls/init.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lua') diff --git a/lua/lvim/lsp/null-ls/init.lua b/lua/lvim/lsp/null-ls/init.lua index f2d3216d..ef4a1844 100644 --- a/lua/lvim/lsp/null-ls/init.lua +++ b/lua/lvim/lsp/null-ls/init.lua @@ -12,6 +12,12 @@ function M:setup() end null_ls.config() + local default_opts = require("lvim.lsp").get_common_opts() + + if vim.tbl_isempty(lvim.lsp.null_ls.setup or {}) then + lvim.lsp.null_ls.setup = default_opts + end + require("lspconfig")["null-ls"].setup(lvim.lsp.null_ls.setup) for filetype, config in pairs(lvim.lang) do if not vim.tbl_isempty(config.formatters) then -- cgit v1.2.3 From ef41a3d24e753b7e82fe31ebe9e74048881c13e8 Mon Sep 17 00:00:00 2001 From: kylo252 <59826753+kylo252@users.noreply.github.com> Date: Fri, 15 Oct 2021 16:33:34 +0200 Subject: feat: better telescope integration (#1702) --- lua/lvim/core/telescope.lua | 181 ++++++++++------------------- lua/lvim/core/telescope/custom-finders.lua | 80 +++++++++++++ lua/lvim/core/which-key.lua | 6 +- lua/lvim/plugins.lua | 5 + 4 files changed, 149 insertions(+), 123 deletions(-) create mode 100644 lua/lvim/core/telescope/custom-finders.lua (limited to 'lua') diff --git a/lua/lvim/core/telescope.lua b/lua/lvim/core/telescope.lua index 35f6b4a2..7911d433 100644 --- a/lua/lvim/core/telescope.lua +++ b/lua/lvim/core/telescope.lua @@ -8,11 +8,6 @@ function M.config() on_config_done = nil, } - local status_ok, actions = pcall(require, "telescope.actions") - if not status_ok then - return - end - lvim.builtin.telescope = vim.tbl_extend("force", lvim.builtin.telescope, { defaults = { prompt_prefix = " ", @@ -28,135 +23,44 @@ function M.config() horizontal = { mirror = false }, vertical = { mirror = false }, }, - file_sorter = require("telescope.sorters").get_fzy_sorter, + vimgrep_arguments = { + "rg", + "--color=never", + "--no-heading", + "--with-filename", + "--line-number", + "--column", + "--smart-case", + "--hidden", + }, file_ignore_patterns = {}, - generic_sorter = require("telescope.sorters").get_generic_fuzzy_sorter, path_display = { shorten = 5 }, winblend = 0, border = {}, borderchars = { "─", "│", "─", "│", "╭", "╮", "╯", "╰" }, color_devicons = true, - use_less = true, set_env = { ["COLORTERM"] = "truecolor" }, -- default = nil, - file_previewer = require("telescope.previewers").vim_buffer_cat.new, - grep_previewer = require("telescope.previewers").vim_buffer_vimgrep.new, - qflist_previewer = require("telescope.previewers").vim_buffer_qflist.new, - - -- Developer configurations: Not meant for general override - -- buffer_previewer_maker = require("telescope.previewers").buffer_previewer_maker, - mappings = { - i = { - [""] = actions.move_selection_next, - [""] = actions.move_selection_previous, - [""] = actions.close, - [""] = actions.cycle_history_next, - [""] = actions.cycle_history_prev, - [""] = actions.smart_send_to_qflist + actions.open_qflist, - [""] = actions.select_default + actions.center, - -- To disable a keymap, put [map] = false - -- So, to not map "", just put - -- [""] = trouble.open_with_trouble, - -- [""] = false, - -- [""] = actions.close, - -- Otherwise, just set the mapping to the function that you want it to be. - -- [""] = actions.select_horizontal, - -- Add up multiple actions - -- You can perform as many actions in a row as you like - -- [""] = actions.select_default + actions.center + my_cool_custom_action, + pickers = { + find_files = { + find_command = { "fd", "--type=file", "--hidden", "--smart-case" }, }, - n = { - [""] = actions.move_selection_next, - [""] = actions.move_selection_previous, - [""] = actions.smart_send_to_qflist + actions.open_qflist, - -- [""] = trouble.open_with_trouble, - -- [""] = my_cool_custom_action, + live_grep = { + --@usage don't include the filename in the search results + only_sort_text = true, }, }, }, extensions = { - fzy_native = { - override_generic_sorter = false, - override_file_sorter = true, + fzf = { + fuzzy = true, -- false will only do exact matching + override_generic_sorter = true, -- override the generic sorter + override_file_sorter = true, -- override the file sorter + case_mode = "smart_case", -- or "ignore_case" or "respect_case" }, }, }) end -function M.find_lunarvim_files(opts) - opts = opts or {} - local themes = require "telescope.themes" - local theme_opts = themes.get_ivy { - sorting_strategy = "ascending", - layout_strategy = "bottom_pane", - prompt_prefix = ">> ", - prompt_title = "~ LunarVim files ~", - cwd = get_runtime_dir(), - search_dirs = { get_runtime_dir() .. "/lvim", lvim.lsp.templates_dir }, - } - opts = vim.tbl_deep_extend("force", theme_opts, opts) - require("telescope.builtin").find_files(opts) -end - -function M.grep_lunarvim_files(opts) - opts = opts or {} - local themes = require "telescope.themes" - local theme_opts = themes.get_ivy { - sorting_strategy = "ascending", - layout_strategy = "bottom_pane", - prompt_prefix = ">> ", - prompt_title = "~ search LunarVim ~", - cwd = get_runtime_dir(), - search_dirs = { get_runtime_dir() .. "/lvim", lvim.lsp.templates_dir }, - } - opts = vim.tbl_deep_extend("force", theme_opts, opts) - require("telescope.builtin").live_grep(opts) -end - -function M.view_lunarvim_changelog() - local finders = require "telescope.finders" - local make_entry = require "telescope.make_entry" - local pickers = require "telescope.pickers" - local previewers = require "telescope.previewers" - local actions = require "telescope.actions" - local opts = {} - - local conf = require("telescope.config").values - opts.entry_maker = make_entry.gen_from_git_commits(opts) - - pickers.new(opts, { - prompt_title = "LunarVim changelog", - - finder = finders.new_oneshot_job( - vim.tbl_flatten { - "git", - "log", - "--pretty=oneline", - "--abbrev-commit", - "--", - ".", - }, - opts - ), - previewer = { - previewers.git_commit_diff_to_parent.new(opts), - previewers.git_commit_diff_to_head.new(opts), - previewers.git_commit_diff_as_was.new(opts), - previewers.git_commit_message.new(opts), - }, - - --TODO: consider opening a diff view when pressing enter - attach_mappings = function(_, map) - map("i", "", actions._close) - map("n", "", actions._close) - map("i", "", actions._close) - map("n", "", actions._close) - map("n", "q", actions._close) - return true - end, - sorter = conf.file_sorter(opts), - }):find() -end - function M.code_actions() local opts = { winblend = 15, @@ -174,20 +78,57 @@ function M.code_actions() previewer = false, shorten_path = false, } - require("telescope.builtin").lsp_code_actions(require("telescope.themes").get_dropdown(opts)) + local builtin = require "telescope.builtin" + local themes = require "telescope.themes" + builtin.lsp_code_actions(themes.get_dropdown(opts)) end function M.setup() - local telescope = require "telescope" + local previewers = require "telescope.previewers" + local sorters = require "telescope.sorters" + local actions = require "telescope.actions" + lvim.builtin.telescope = vim.tbl_extend("keep", { + file_previewer = previewers.vim_buffer_cat.new, + grep_previewer = previewers.vim_buffer_vimgrep.new, + qflist_previewer = previewers.vim_buffer_qflist.new, + file_sorter = sorters.get_fuzzy_file, + generic_sorter = sorters.get_generic_fuzzy_sorter, + ---@usage Mappings are fully customizable. Many familiar mapping patterns are setup as defaults. + mappings = { + i = { + [""] = actions.move_selection_next, + [""] = actions.move_selection_previous, + [""] = actions.close, + [""] = actions.cycle_history_next, + [""] = actions.cycle_history_prev, + [""] = actions.smart_send_to_qflist + actions.open_qflist, + [""] = actions.select_default + actions.center, + }, + n = { + [""] = actions.move_selection_next, + [""] = actions.move_selection_previous, + [""] = actions.smart_send_to_qflist + actions.open_qflist, + }, + }, + }, lvim.builtin.telescope) + + local telescope = require "telescope" telescope.setup(lvim.builtin.telescope) + if lvim.builtin.project.active then - telescope.load_extension "projects" + pcall(function() + require("telescope").load_extension "projects" + end) end if lvim.builtin.telescope.on_config_done then lvim.builtin.telescope.on_config_done(telescope) end + + if lvim.builtin.telescope.extensions and lvim.builtin.telescope.extensions.fzf then + require("telescope").load_extension "fzf" + end end return M diff --git a/lua/lvim/core/telescope/custom-finders.lua b/lua/lvim/core/telescope/custom-finders.lua new file mode 100644 index 00000000..c3347fd0 --- /dev/null +++ b/lua/lvim/core/telescope/custom-finders.lua @@ -0,0 +1,80 @@ +local M = {} + +local _, builtin = pcall(require, "telescope.builtin") +local _, finders = pcall(require, "telescope.finders") +local _, pickers = pcall(require, "telescope.pickers") +local _, sorters = pcall(require, "telescope.sorters") +local _, themes = pcall(require, "telescope.themes") +local _, actions = pcall(require, "telescope.actions") +local _, previewers = pcall(require, "telescope.previewers") +local _, make_entry = pcall(require, "telescope.make_entry") + +local utils = require "lvim.utils" + +function M.find_lunarvim_files(opts) + opts = opts or {} + local theme_opts = themes.get_ivy { + sorting_strategy = "ascending", + layout_strategy = "bottom_pane", + prompt_prefix = ">> ", + prompt_title = "~ LunarVim files ~", + cwd = get_runtime_dir(), + search_dirs = { utils.join_paths(get_runtime_dir(), "lvim"), lvim.lsp.templates_dir }, + } + opts = vim.tbl_deep_extend("force", theme_opts, opts) + builtin.find_files(opts) +end + +function M.grep_lunarvim_files(opts) + opts = opts or {} + local theme_opts = themes.get_ivy { + sorting_strategy = "ascending", + layout_strategy = "bottom_pane", + prompt_prefix = ">> ", + prompt_title = "~ search LunarVim ~", + cwd = get_runtime_dir(), + search_dirs = { utils.join_paths(get_runtime_dir(), "lvim"), lvim.lsp.templates_dir }, + } + opts = vim.tbl_deep_extend("force", theme_opts, opts) + builtin.live_grep(opts) +end + +function M.view_lunarvim_changelog() + local opts = {} + opts.entry_maker = make_entry.gen_from_git_commits(opts) + + pickers.new(opts, { + prompt_title = "LunarVim changelog", + + finder = finders.new_oneshot_job( + vim.tbl_flatten { + "git", + "log", + "--pretty=oneline", + "--abbrev-commit", + "--", + ".", + }, + opts + ), + previewer = { + previewers.git_commit_diff_to_parent.new(opts), + previewers.git_commit_diff_to_head.new(opts), + previewers.git_commit_diff_as_was.new(opts), + previewers.git_commit_message.new(opts), + }, + + --TODO: consider opening a diff view when pressing enter + attach_mappings = function(_, map) + map("i", "", actions._close) + map("n", "", actions._close) + map("i", "", actions._close) + map("n", "", actions._close) + map("n", "q", actions._close) + return true + end, + sorter = sorters.generic_sorter, + }):find() +end + +return M diff --git a/lua/lvim/core/which-key.lua b/lua/lvim/core/which-key.lua index 528c7600..fcaeacf5 100644 --- a/lua/lvim/core/which-key.lua +++ b/lua/lvim/core/which-key.lua @@ -181,11 +181,11 @@ M.config = function() "Edit config.lua", }, f = { - "lua require('lvim.core.telescope').find_lunarvim_files()", + "lua require('lvim.core.telescope.custom-finders').find_lunarvim_files()", "Find LunarVim files", }, g = { - "lua require('lvim.core.telescope').grep_lunarvim_files()", + "lua require('lvim.core.telescope.custom-finders').grep_lunarvim_files()", "Grep LunarVim files", }, k = { "lua require('lvim.keymappings').print()", "View LunarVim's default keymappings" }, @@ -194,7 +194,7 @@ M.config = function() "Toggle LunarVim Info", }, I = { - "lua require('lvim.core.telescope').view_lunarvim_changelog()", + "lua require('lvim.core.telescope.custom-finders').view_lunarvim_changelog()", "View LunarVim's changelog", }, l = { diff --git a/lua/lvim/plugins.lua b/lua/lvim/plugins.lua index 84522366..88cd7ad4 100644 --- a/lua/lvim/plugins.lua +++ b/lua/lvim/plugins.lua @@ -19,6 +19,11 @@ return { end, disable = not lvim.builtin.telescope.active, }, + { + "nvim-telescope/telescope-fzf-native.nvim", + run = "make", + disable = not lvim.builtin.telescope.active, + }, -- Install nvim-cmp, and buffer source as a dependency { "hrsh7th/nvim-cmp", -- cgit v1.2.3 From 281c54ba55651af0b33dadeb3419e19b10fbed45 Mon Sep 17 00:00:00 2001 From: Subho Banerjee Date: Sat, 16 Oct 2021 05:03:17 -0500 Subject: [Bugfix]: Allow user autocmds (#1776) Co-authored-by: kylo252 <59826753+kylo252@users.noreply.github.com> --- lua/lvim/config/init.lua | 3 + lua/lvim/core/autocmds.lua | 155 +++++++++++++++++---------------------------- 2 files changed, 60 insertions(+), 98 deletions(-) (limited to 'lua') diff --git a/lua/lvim/config/init.lua b/lua/lvim/config/init.lua index e14f96fa..c06d28ef 100644 --- a/lua/lvim/config/init.lua +++ b/lua/lvim/config/init.lua @@ -27,6 +27,9 @@ function M:init() local settings = require "lvim.config.settings" settings.load_options() + local autocmds = require "lvim.core.autocmds" + lvim.autocommands = autocmds.load_augroups() + local lvim_lsp_config = require "lvim.lsp.config" lvim.lsp = vim.deepcopy(lvim_lsp_config) diff --git a/lua/lvim/core/autocmds.lua b/lua/lvim/core/autocmds.lua index 4f29f0e1..5d1d365e 100644 --- a/lua/lvim/core/autocmds.lua +++ b/lua/lvim/core/autocmds.lua @@ -1,110 +1,69 @@ -local autocommands = {} -local user_config_file = require("lvim.config"):get_user_config_path() +local M = {} -lvim.autocommands = { - _general_settings = { - { - "Filetype", - "*", - "lua require('lvim.utils.ft').do_filetype(vim.fn.expand(\"\"))", - }, - { - "FileType", - "qf", - "nnoremap q :q", +--- Load the default set of autogroups and autocommands. +function M.load_augroups() + local user_config_file = vim.fn.resolve(require("lvim.config"):get_user_config_path()) + + return { + _general_settings = { + { + "Filetype", + "*", + "lua require('lvim.utils.ft').do_filetype(vim.fn.expand(\"\"))", + }, + { "FileType", "qf,help,man", "nnoremap q :close" }, + { + "TextYankPost", + "*", + "lua require('vim.highlight').on_yank({higroup = 'Search', timeout = 200})", + }, + { + "BufWinEnter", + "dashboard", + "setlocal cursorline signcolumn=yes cursorcolumn number", + }, + { "BufWritePost", user_config_file, "lua require('lvim.config'):reload()" }, + { "FileType", "qf", "set nobuflisted" }, + -- { "VimLeavePre", "*", "set title set titleold=" }, }, - { - "FileType", - "lsp-installer", - "nnoremap q :q", + _formatoptions = { + { + "BufWinEnter,BufRead,BufNewFile", + "*", + "setlocal formatoptions-=c formatoptions-=r formatoptions-=o", + }, }, - { - "TextYankPost", - "*", - "lua require('vim.highlight').on_yank({higroup = 'Search', timeout = 200})", + _filetypechanges = { + { "BufWinEnter", ".tf", "setlocal filetype=terraform" }, + { "BufRead", "*.tf", "setlocal filetype=terraform" }, + { "BufNewFile", "*.tf", "setlocal filetype=terraform" }, + { "BufWinEnter", ".zsh", "setlocal filetype=sh" }, + { "BufRead", "*.zsh", "setlocal filetype=sh" }, + { "BufNewFile", "*.zsh", "setlocal filetype=sh" }, }, - { - "BufWinEnter", - "*", - "setlocal formatoptions-=c formatoptions-=r formatoptions-=o", + _git = { + { "FileType", "gitcommit", "setlocal wrap" }, + { "FileType", "gitcommit", "setlocal spell" }, }, - { - "BufWinEnter", - "dashboard", - "setlocal cursorline signcolumn=yes cursorcolumn number", + _markdown = { + { "FileType", "markdown", "setlocal wrap" }, + { "FileType", "markdown", "setlocal spell" }, }, - { - "BufRead", - "*", - "setlocal formatoptions-=c formatoptions-=r formatoptions-=o", + _buffer_bindings = { + { "FileType", "floaterm", "nnoremap q :q" }, }, - { - "BufNewFile", - "*", - "setlocal formatoptions-=c formatoptions-=r formatoptions-=o", + _auto_resize = { + -- will cause split windows to be resized evenly if main window is resized + { "VimResized", "*", "tabdo wincmd =" }, }, - { "BufWritePost", user_config_file, "lua require('lvim.config'):reload()" }, - { - "FileType", - "qf", - "set nobuflisted", + _general_lsp = { + { "FileType", "lspinfo,lsp-installer,null-ls-info", "nnoremap q :close" }, }, - -- { "VimLeavePre", "*", "set title set titleold=" }, - }, - _filetypechanges = { - { "BufWinEnter", ".tf", "setlocal filetype=terraform" }, - { "BufRead", "*.tf", "setlocal filetype=terraform" }, - { "BufNewFile", "*.tf", "setlocal filetype=terraform" }, - { "BufWinEnter", ".zsh", "setlocal filetype=sh" }, - { "BufRead", "*.zsh", "setlocal filetype=sh" }, - { "BufNewFile", "*.zsh", "setlocal filetype=sh" }, - }, - -- _solidity = { - -- {'BufWinEnter', '.sol', 'setlocal filetype=solidity'}, {'BufRead', '*.sol', 'setlocal filetype=solidity'}, - -- {'BufNewFile', '*.sol', 'setlocal filetype=solidity'} - -- }, - -- _gemini = { - -- {'BufWinEnter', '.gmi', 'setlocal filetype=markdown'}, {'BufRead', '*.gmi', 'setlocal filetype=markdown'}, - -- {'BufNewFile', '*.gmi', 'setlocal filetype=markdown'} - -- }, - _git = { - { "FileType", "gitcommit", "setlocal wrap" }, - { "FileType", "gitcommit", "setlocal spell" }, - }, - _markdown = { - { "FileType", "markdown", "setlocal wrap" }, - { "FileType", "markdown", "setlocal spell" }, - }, - _buffer_bindings = { - { "FileType", "floaterm", "nnoremap q :q" }, - }, - _auto_resize = { - -- will cause split windows to be resized evenly if main window is resized - { "VimResized", "*", "wincmd =" }, - }, - _packer_compile = { - -- will run PackerCompile after writing plugins.lua - { "BufWritePost", "plugins.lua", "PackerCompile" }, - }, - _general_lsp = { - { "FileType", "lspinfo", "nnoremap q :q" }, - }, - - -- _fterm_lazygit = { - -- -- will cause esc key to exit lazy git - -- {"TermEnter", "*", "call LazyGitNativation()"} - -- }, - -- _mode_switching = { - -- -- will switch between absolute and relative line numbers depending on mode - -- {'InsertEnter', '*', 'if &relativenumber | let g:ms_relativenumberoff = 1 | setlocal number norelativenumber | endif'}, - -- {'InsertLeave', '*', 'if exists("g:ms_relativenumberoff") | setlocal relativenumber | endif'}, - -- {'InsertEnter', '*', 'if &cursorline | let g:ms_cursorlineoff = 1 | setlocal nocursorline | endif'}, - -- {'InsertLeave', '*', 'if exists("g:ms_cursorlineoff") | setlocal cursorline | endif'}, - -- }, - custom_groups = {}, -} + custom_groups = {}, + } +end -function autocommands.define_augroups(definitions) -- {{{1 +function M.define_augroups(definitions) -- {{{1 -- Create autocommand groups based on the passed definitions -- -- The key will be the name of the group, and each definition @@ -126,4 +85,4 @@ function autocommands.define_augroups(definitions) -- {{{1 end end -return autocommands +return M -- cgit v1.2.3 From 92c07ed89f278a89a1dbf0437162f3a95661dd0e Mon Sep 17 00:00:00 2001 From: xeluxee <88047141+xeluxee@users.noreply.github.com> Date: Sat, 16 Oct 2021 20:19:50 +0200 Subject: fix(cmp): fix and keybindings not working --- lua/lvim/core/cmp.lua | 2 ++ lua/lvim/keymappings.lua | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'lua') diff --git a/lua/lvim/core/cmp.lua b/lua/lvim/core/cmp.lua index ad06a360..b1cb1431 100644 --- a/lua/lvim/core/cmp.lua +++ b/lua/lvim/core/cmp.lua @@ -204,6 +204,8 @@ M.config = function() { name = "crates" }, }, mapping = { + [""] = cmp.mapping.select_prev_item(), + [""] = cmp.mapping.select_next_item(), [""] = cmp.mapping.scroll_docs(-4), [""] = cmp.mapping.scroll_docs(4), -- TODO: potentially fix emmet nonsense diff --git a/lua/lvim/keymappings.lua b/lua/lvim/keymappings.lua index 68a49393..be8ebe96 100644 --- a/lua/lvim/keymappings.lua +++ b/lua/lvim/keymappings.lua @@ -81,10 +81,6 @@ function M.config() [""] = "j", [""] = "h", [""] = "l", - -- navigate tab completion with and - -- runs conditionally - [""] = { 'pumvisible() ? "\\" : "\\"', { expr = true, noremap = true } }, - [""] = { 'pumvisible() ? "\\" : "\\"', { expr = true, noremap = true } }, }, ---@usage change or add keymappings for normal mode -- cgit v1.2.3 From 7c96c45151033e7fd4bf29103f5d6fd482863c43 Mon Sep 17 00:00:00 2001 From: kylo252 <59826753+kylo252@users.noreply.github.com> Date: Wed, 20 Oct 2021 11:26:02 +0200 Subject: refactor(info): new layout with less clutter (#1809) --- lua/lvim/core/info.lua | 116 ++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 60 deletions(-) (limited to 'lua') diff --git a/lua/lvim/core/info.lua b/lua/lvim/core/info.lua index 7fdb665b..263a7928 100644 --- a/lua/lvim/core/info.lua +++ b/lua/lvim/core/info.lua @@ -12,51 +12,42 @@ local M = { local fmt = string.format local text = require "lvim.interface.text" local lsp_utils = require "lvim.lsp.utils" -local user_config_file = require("lvim.config"):get_user_config_path() local function str_list(list) return fmt("[ %s ]", table.concat(list, ", ")) end -local function get_formatter_suggestion_msg(ft) +local function make_formatters_info(ft) local null_formatters = require "lvim.lsp.null-ls.formatters" + local registered_formatters = null_formatters.list_supported_names(ft) local supported_formatters = null_formatters.list_available(ft) local section = { - " HINT ", - "", - fmt("* List of supported formatters: %s", str_list(supported_formatters)), + "Formatters info", + fmt( + "* Active: %s%s", + table.concat(registered_formatters, "  , "), + vim.tbl_count(registered_formatters) > 0 and "  " or "" + ), + fmt("* Supported: %s", str_list(supported_formatters)), } - if not vim.tbl_isempty(supported_formatters) then - vim.list_extend(section, { - "* Configured formatter needs to be installed and executable.", - fmt("* Enable installed formatter(s) with following config in %s", user_config_file), - "", - fmt(" lvim.lang.%s.formatters = { { exe = '%s' } }", ft, table.concat(supported_formatters, "│")), - }) - end - return section end -local function get_linter_suggestion_msg(ft) +local function make_linters_info(ft) local null_linters = require "lvim.lsp.null-ls.linters" local supported_linters = null_linters.list_available(ft) + local registered_linters = null_linters.list_supported_names(ft) local section = { - " HINT ", - "", - fmt("* List of supported linters: %s", str_list(supported_linters)), + "Linters info", + fmt( + "* Active: %s%s", + table.concat(registered_linters, "  , "), + vim.tbl_count(registered_linters) > 0 and "  " or "" + ), + fmt("* Supported: %s", str_list(supported_linters)), } - if not vim.tbl_isempty(supported_linters) then - vim.list_extend(section, { - "* Configured linter needs to be installed and executable.", - fmt("* Enable installed linter(s) with following config in %s", user_config_file), - "", - fmt(" lvim.lang.%s.linters = { { exe = '%s' } }", ft, table.concat(supported_linters, "│")), - }) - end - return section end @@ -71,13 +62,15 @@ local function make_client_info(client) local name = client.name local id = client.id local document_formatting = client.resolved_capabilities.document_formatting + local attached_buffers_list = table.concat(vim.lsp.get_buffers_by_client_id(client.id), ", ") local client_info = { - fmt("* Name: %s", name), - fmt("* Id: %s", tostring(id)), - fmt("* Supports formatting: %s", tostring(document_formatting)), + fmt("* Name: %s", name), + fmt("* Id: [%s]", tostring(id)), + fmt("* Attached buffers: [%s]", tostring(attached_buffers_list)), + fmt("* Supports formatting: %s", tostring(document_formatting)), } if not vim.tbl_isempty(client_enabled_caps) then - local caps_text = "* Capabilities list: " + local caps_text = "* Capabilities list: " local caps_text_len = caps_text:len() local enabled_caps = text.format_table(client_enabled_caps, 3, " | ") enabled_caps = text.shift_right(enabled_caps, caps_text_len) @@ -91,10 +84,24 @@ end function M.toggle_popup(ft) local clients = lsp_utils.get_active_clients_by_ft(ft) local client_names = {} - + local bufnr = vim.api.nvim_get_current_buf() + local ts_active_buffers = vim.tbl_keys(vim.treesitter.highlighter.active) + local is_treesitter_active = function() + local status = "inactive" + if vim.tbl_contains(ts_active_buffers, bufnr) then + status = "active" + end + return status + end local header = { - fmt("Detected filetype: %s", ft), - fmt("Treesitter active: %s", tostring(next(vim.treesitter.highlighter.active) ~= nil)), + fmt("Detected filetype: %s", ft), + fmt("Current buffer number: [%s]", bufnr), + } + + local ts_info = { + "Treesitter info", + fmt("* current buffer: %s", is_treesitter_active()), + fmt("* list: [%s]", table.concat(ts_active_buffers, ", ")), } local lsp_info = { @@ -107,22 +114,9 @@ function M.toggle_popup(ft) table.insert(client_names, client.name) end - local null_formatters = require "lvim.lsp.null-ls.formatters" - local null_linters = require "lvim.lsp.null-ls.linters" - local registered_formatters = null_formatters.list_supported_names(ft) - local registered_linters = null_linters.list_supported_names(ft) - local registered_providers = {} - vim.list_extend(registered_providers, registered_formatters) - vim.list_extend(registered_providers, registered_linters) - local registered_count = vim.tbl_count(registered_providers) - local null_ls_info = { - "Formatters and linters", - fmt( - "* Configured providers: %s%s", - table.concat(registered_providers, "  , "), - registered_count > 0 and "  " or "" - ), - } + local formatters_info = make_formatters_info(ft) + + local linters_info = make_linters_info(ft) local content_provider = function(popup) local content = {} @@ -133,15 +127,13 @@ function M.toggle_popup(ft) { "" }, header, { "" }, - lsp_info, + ts_info, { "" }, - null_ls_info, - { "" }, - { "" }, - get_formatter_suggestion_msg(ft), + lsp_info, { "" }, + formatters_info, { "" }, - get_linter_suggestion_msg(ft), + linters_info, } do vim.list_extend(content, section) end @@ -152,14 +144,18 @@ function M.toggle_popup(ft) local function set_syntax_hl() vim.cmd [[highlight LvimInfoIdentifier gui=bold]] vim.cmd [[highlight link LvimInfoHeader Type]] + vim.cmd [[let m=matchadd("LvimInfoHeader", "Treesitter info")]] vim.cmd [[let m=matchadd("LvimInfoHeader", "Language Server Protocol (LSP) info")]] - vim.cmd [[let m=matchadd("LvimInfoHeader", "Formatters and linters")]] + vim.cmd [[let m=matchadd("LvimInfoHeader", "Formatters info")]] + vim.cmd [[let m=matchadd("LvimInfoHeader", "Linters info")]] vim.cmd('let m=matchadd("LvimInfoIdentifier", " ' .. ft .. '$")') vim.cmd 'let m=matchadd("string", "true")' + vim.cmd 'let m=matchadd("string", "active")' + vim.cmd 'let m=matchadd("string", "")' vim.cmd 'let m=matchadd("error", "false")' - tbl_set_highlight(registered_providers, "LvimInfoIdentifier") - -- tbl_set_highlight(require("lvim.lsp.null-ls.formatters").list_available(ft), "LvimInfoIdentifier") - -- tbl_set_highlight(require("lvim.lsp.null-ls.linters").list_available(ft), "LvimInfoIdentifier") + -- tbl_set_highlight(registered_providers, "LvimInfoIdentifier") + tbl_set_highlight(require("lvim.lsp.null-ls.formatters").list_available(ft), "LvimInfoIdentifier") + tbl_set_highlight(require("lvim.lsp.null-ls.linters").list_available(ft), "LvimInfoIdentifier") end local Popup = require("lvim.interface.popup"):new { -- cgit v1.2.3 From 5cf8c07ee921f8dfed03415fe5b8322754ea8615 Mon Sep 17 00:00:00 2001 From: Sergio Mendez Date: Wed, 20 Oct 2021 12:05:18 -0400 Subject: fix(bootstrap): support for using default neovim config and data directories (#1777) Co-authored-by: kylo252 <59826753+kylo252@users.noreply.github.com> Co-authored-by: James Walmsley --- lua/lvim/bootstrap.lua | 82 ++++++++++++++++++++++----------------------- lua/lvim/core/dashboard.lua | 2 +- 2 files changed, 42 insertions(+), 42 deletions(-) (limited to 'lua') diff --git a/lua/lvim/bootstrap.lua b/lua/lvim/bootstrap.lua index b1ecdf1c..fbb362ce 100644 --- a/lua/lvim/bootstrap.lua +++ b/lua/lvim/bootstrap.lua @@ -3,11 +3,12 @@ local M = {} package.loaded["lvim.utils.hooks"] = nil local _, hooks = pcall(require, "lvim.utils.hooks") +local uv = vim.loop +local path_sep = uv.os_uname().version:match "Windows" and "\\" or "/" + ---Join path segments that were passed as input ---@return string function _G.join_paths(...) - local uv = vim.loop - local path_sep = uv.os_uname().version:match "Windows" and "\\" or "/" local result = table.concat({ ... }, path_sep) return result end @@ -18,7 +19,7 @@ function _G.get_runtime_dir() 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" + return vim.fn.stdpath "data" end return lvim_runtime_dir end @@ -43,47 +44,24 @@ 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_install_path() .. " describe --tags") - - if string.match(lvim_full_ver, "%d") == nil then - return nil - end - if type == "short" then - return vim.fn.split(lvim_full_ver, "-")[1] - else - return string.sub(lvim_full_ver, 1, #lvim_full_ver - 1) - end -end - ---Initialize the `&runtimepath` variables and prepare for startup ---@return table -function M:init() +function M:init(base_dir) self.runtime_dir = get_runtime_dir() self.config_dir = get_config_dir() self.cache_path = get_cache_dir() - 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") self.packer_cache_path = join_paths(self.config_dir, "plugin", "packer_compiled.lua") + ---Get the full path to LunarVim's base directory + ---@return string + function _G.get_lvim_base_dir() + return base_dir + end + if os.getenv "LUNARVIM_RUNTIME_DIR" then + -- vim.opt.rtp:append(os.getenv "LUNARVIM_RUNTIME_DIR" .. path_sep .. "lvim") vim.opt.rtp:remove(join_paths(vim.fn.stdpath "data", "site")) vim.opt.rtp:remove(join_paths(vim.fn.stdpath "data", "site", "after")) vim.opt.rtp:prepend(join_paths(self.runtime_dir, "site")) @@ -128,10 +106,10 @@ function M:update() hooks.run_post_update() end -local function git_cmd(subcmd) +local function git_cmd(subcmd, opts) local Job = require "plenary.job" local Log = require "lvim.core.log" - local args = { "-C", get_install_path() } + local args = { "-C", opts.cwd } vim.list_extend(args, subcmd) local stderr = {} @@ -139,7 +117,7 @@ local function git_cmd(subcmd) :new({ command = "git", args = args, - cwd = get_install_path(), + cwd = opts.cwd, on_stderr = function(_, data) table.insert(stderr, data) end, @@ -154,7 +132,7 @@ local function git_cmd(subcmd) Log:debug(stdout) end - return ret + return ret, stdout end ---pulls the latest changes from github @@ -165,22 +143,25 @@ function M:update_repo() diff = { "diff", "--quiet", "@{upstream}" }, merge = { "merge", "--ff-only", "--progress" }, } + local opts = { + cwd = get_lvim_base_dir(), + } Log:info "Checking for updates" - local ret = git_cmd(sub_commands.fetch) + local ret = git_cmd(sub_commands.fetch, opts) if ret ~= 0 then Log:error "Update failed! Check the log for further information" return end - ret = git_cmd(sub_commands.diff) + ret = git_cmd(sub_commands.diff, opts) if ret == 0 then Log:info "LunarVim is already up-to-date" return end - ret = git_cmd(sub_commands.merge) + ret = git_cmd(sub_commands.merge, opts) if ret ~= 0 then Log:error "Update failed! Please pull the changes manually instead." @@ -188,4 +169,23 @@ function M:update_repo() end end +---Get currently installed version of LunarVim +---@param type string can be "short" +---@return string +function M:get_version(type) + type = type or "" + local opts = { cwd = get_lvim_base_dir() } + local status_ok, results = git_cmd({ "describe", "--tags" }, opts) + local lvim_full_ver = results[1] or "" + + if not status_ok or string.match(lvim_full_ver, "%d") == nil then + return nil + end + if type == "short" then + return vim.fn.split(lvim_full_ver, "-")[1] + else + return string.sub(lvim_full_ver, 1, #lvim_full_ver - 1) + end +end + return M diff --git a/lua/lvim/core/dashboard.lua b/lua/lvim/core/dashboard.lua index 38d9d226..108ed0d2 100644 --- a/lua/lvim/core/dashboard.lua +++ b/lua/lvim/core/dashboard.lua @@ -70,7 +70,7 @@ M.setup = function() vim.g.dashboard_session_directory = lvim.builtin.dashboard.session_directory local lvim_site = "lunarvim.org" - local lvim_version = get_version "short" + local lvim_version = require("lvim.bootstrap"):get_version "short" local num_plugins_loaded = #vim.fn.globpath(get_runtime_dir() .. "/site/pack/packer/start", "*", 0, 1) local footer = { -- cgit v1.2.3 From 03e5760e59b5dd420956908b6f8b57c33f70f2cd Mon Sep 17 00:00:00 2001 From: kylo252 <59826753+kylo252@users.noreply.github.com> Date: Wed, 20 Oct 2021 20:01:51 +0200 Subject: fix(formatters): always select null-ls by default (#1810) --- lua/lvim/core/info.lua | 5 +++-- lua/lvim/core/lualine/components.lua | 4 ++-- lua/lvim/lsp/init.lua | 7 +++---- lua/lvim/lsp/null-ls/formatters.lua | 2 +- lua/lvim/lsp/null-ls/linters.lua | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) (limited to 'lua') diff --git a/lua/lvim/core/info.lua b/lua/lvim/core/info.lua index 263a7928..5707cc30 100644 --- a/lua/lvim/core/info.lua +++ b/lua/lvim/core/info.lua @@ -19,7 +19,7 @@ end local function make_formatters_info(ft) local null_formatters = require "lvim.lsp.null-ls.formatters" - local registered_formatters = null_formatters.list_supported_names(ft) + local registered_formatters = null_formatters.list_registered_providers(ft) local supported_formatters = null_formatters.list_available(ft) local section = { "Formatters info", @@ -37,7 +37,7 @@ end local function make_linters_info(ft) local null_linters = require "lvim.lsp.null-ls.linters" local supported_linters = null_linters.list_available(ft) - local registered_linters = null_linters.list_supported_names(ft) + local registered_linters = null_linters.list_registered_providers(ft) local section = { "Linters info", fmt( @@ -151,6 +151,7 @@ function M.toggle_popup(ft) vim.cmd('let m=matchadd("LvimInfoIdentifier", " ' .. ft .. '$")') vim.cmd 'let m=matchadd("string", "true")' vim.cmd 'let m=matchadd("string", "active")' + vim.cmd 'let m=matchadd("boolean", "inactive")' vim.cmd 'let m=matchadd("string", "")' vim.cmd 'let m=matchadd("error", "false")' -- tbl_set_highlight(registered_providers, "LvimInfoIdentifier") diff --git a/lua/lvim/core/lualine/components.lua b/lua/lvim/core/lualine/components.lua index 5c0fb84b..b10fdad9 100644 --- a/lua/lvim/core/lualine/components.lua +++ b/lua/lvim/core/lualine/components.lua @@ -104,12 +104,12 @@ return { -- add formatter local formatters = require "lvim.lsp.null-ls.formatters" - local supported_formatters = formatters.list_supported_names(buf_ft) + local supported_formatters = formatters.list_registered_providers(buf_ft) vim.list_extend(buf_client_names, supported_formatters) -- add linter local linters = require "lvim.lsp.null-ls.linters" - local supported_linters = linters.list_supported_names(buf_ft) + local supported_linters = linters.list_registered_providers(buf_ft) vim.list_extend(buf_client_names, supported_linters) return table.concat(buf_client_names, ", ") diff --git a/lua/lvim/lsp/init.lua b/lua/lvim/lsp/init.lua index c8d583a9..45ba04e0 100644 --- a/lua/lvim/lsp/init.lua +++ b/lua/lvim/lsp/init.lua @@ -86,15 +86,14 @@ function M.common_capabilities() end local function select_default_formater(client) - local client_formatting = client.resolved_capabilities.document_formatting - or client.resolved_capabilities.document_range_formatting - if client.name == "null-ls" or not client_formatting then + 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 lvim.lang[filetype] and #vim.tbl_keys(lvim.lang[filetype].formatters) > 0 then + if #vim.tbl_keys(formatters.list_registered_providers(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 diff --git a/lua/lvim/lsp/null-ls/formatters.lua b/lua/lvim/lsp/null-ls/formatters.lua index 663e2586..87583abd 100644 --- a/lua/lvim/lsp/null-ls/formatters.lua +++ b/lua/lvim/lsp/null-ls/formatters.lua @@ -4,7 +4,7 @@ local null_ls = require "null-ls" local services = require "lvim.lsp.null-ls.services" local Log = require "lvim.core.log" -function M.list_supported_names(filetype) +function M.list_registered_providers(filetype) local null_ls_methods = require "null-ls.methods" local formatter_method = null_ls_methods.internal["FORMATTING"] local registered_providers = services.list_registered_providers_names(filetype) diff --git a/lua/lvim/lsp/null-ls/linters.lua b/lua/lvim/lsp/null-ls/linters.lua index 9ea2d55b..1069ac58 100644 --- a/lua/lvim/lsp/null-ls/linters.lua +++ b/lua/lvim/lsp/null-ls/linters.lua @@ -4,7 +4,7 @@ local null_ls = require "null-ls" local services = require "lvim.lsp.null-ls.services" local Log = require "lvim.core.log" -function M.list_supported_names(filetype) +function M.list_registered_providers(filetype) local null_ls_methods = require "null-ls.methods" local linter_method = null_ls_methods.internal["DIAGNOSTICS"] local registered_providers = services.list_registered_providers_names(filetype) -- cgit v1.2.3 From 25747cfff457d5375b6141588d81017ca515ffcb Mon Sep 17 00:00:00 2001 From: kylo252 <59826753+kylo252@users.noreply.github.com> Date: Thu, 21 Oct 2021 07:42:28 +0200 Subject: [Feature] use structlog and notify.nvim (#1737) Co-authored-by: Luc Sinet --- lua/lvim/config/defaults.lua | 14 +++-- lua/lvim/core/log.lua | 147 ++++++++++++++++++++++++++++++++++++------- lua/lvim/plugins.lua | 2 + 3 files changed, 134 insertions(+), 29 deletions(-) (limited to 'lua') diff --git a/lua/lvim/config/defaults.lua b/lua/lvim/config/defaults.lua index ffbb2e1b..effe1e77 100644 --- a/lua/lvim/config/defaults.lua +++ b/lua/lvim/config/defaults.lua @@ -8,6 +8,12 @@ return { builtin = {}, + plugins = { + -- use config.lua for this not put here + }, + + autocommands = {}, + lang = {}, log = { ---@usage can be { "trace", "debug", "info", "warn", "error", "fatal" }, level = "warn", @@ -22,11 +28,7 @@ return { float_opts = {}, }, }, + ---@usage set to false to restore the default behavior of vim.notify + override_notify = true, }, - plugins = { - -- use config.lua for this not put here - }, - - autocommands = {}, - lang = {}, } diff --git a/lua/lvim/core/log.lua b/lua/lvim/core/log.lua index 3d8c0dc8..9ddc641f 100644 --- a/lua/lvim/core/log.lua +++ b/lua/lvim/core/log.lua @@ -1,60 +1,161 @@ local Log = {} +local logfile = string.format("%s/%s.log", vim.fn.stdpath "cache", "lvim") + +Log.levels = { + TRACE = 1, + DEBUG = 2, + INFO = 3, + WARN = 4, + ERROR = 5, +} + +vim.tbl_add_reverse_lookup(Log.levels) + +function Log:init() + local status_ok, structlog = pcall(require, "structlog") + if not status_ok then + return nil + end + + local nvim_notify_params = {} + local nvim_notify_params_injecter = function(_, entry) + for key, value in pairs(nvim_notify_params) do + entry[key] = value + end + return entry + end + + local nvim_notify_default_namer = function(logger, entry) + entry["title"] = logger.name + return entry + end + + nvim_notify_params_injecter(nil, {}) + local log_level = Log.levels[(lvim.log.level):upper() or "WARN"] + structlog.configure { + lvim = { + sinks = { + structlog.sinks.Console(log_level, { + async = false, + processors = { + structlog.processors.Namer(), + structlog.processors.StackWriter({ "line", "file" }, { max_parents = 0, stack_level = 2 }), + structlog.processors.Timestamper "%H:%M:%S", + }, + formatter = structlog.formatters.FormatColorizer( -- + "%s [%-5s] %s: %-30s", + { "timestamp", "level", "logger_name", "msg" }, + { level = structlog.formatters.FormatColorizer.color_level() } + ), + }), + structlog.sinks.NvimNotify(Log.levels.INFO, { + processors = { + nvim_notify_default_namer, + nvim_notify_params_injecter, + }, + formatter = structlog.formatters.Format( -- + "%s", + { "msg" }, + { blacklist_all = true } + ), + params_map = { + icon = "icon", + keep = "keep", + on_open = "on_open", + on_close = "on_close", + timeout = "timeout", + title = "title", + }, + }), + structlog.sinks.File(Log.levels.TRACE, logfile, { + processors = { + structlog.processors.Namer(), + structlog.processors.StackWriter({ "line", "file" }, { max_parents = 3, stack_level = 2 }), + structlog.processors.Timestamper "%H:%M:%S", + }, + formatter = structlog.formatters.Format( -- + "%s [%-5s] %s: %-30s", + { "timestamp", "level", "logger_name", "msg" } + ), + }), + }, + }, + } + + local logger = structlog.get_logger "lvim" + + if lvim.log.override_notify then + -- Overwrite vim.notify to use the logger + vim.notify = function(msg, vim_log_level, opts) + nvim_notify_params = opts or {} + -- https://github.com/neovim/neovim/blob/685cf398130c61c158401b992a1893c2405cd7d2/runtime/lua/vim/lsp/log.lua#L5 + logger:log(vim_log_level + 1, msg) + end + end + + return logger +end + --- Adds a log entry using Plenary.log ----@param msg any +---@fparam msg any ---@param level string [same as vim.log.log_levels] -function Log:add_entry(msg, level) - assert(type(level) == "string") +function Log:add_entry(level, msg, event) if self.__handle then - -- plenary uses lower-case log levels - self.__handle[level:lower()](msg) + self.__handle:log(level, msg, event) return end - local status_ok, plenary = pcall(require, "plenary") - if status_ok then - local default_opts = { plugin = "lunarvim", level = lvim.log.level, info_level = 4 } - local handle = plenary.log.new(default_opts) - handle[level:lower()](msg) - self.__handle = handle + + local logger = self:init() + if not logger then + return end - -- don't do anything if plenary is not available + + self.__handle = logger + self.__handle:log(level, msg, event) end ---Retrieves the path of the logfile ---@return string path of the logfile function Log:get_path() - return string.format("%s/%s.log", vim.fn.stdpath "cache", "lunarvim") + return logfile end ---Add a log entry at TRACE level ---@param msg any -function Log:trace(msg) - self:add_entry(msg, "TRACE") +---@param event any +function Log:trace(msg, event) + self:add_entry(self.levels.TRACE, msg, event) end ---Add a log entry at DEBUG level ---@param msg any -function Log:debug(msg) - self:add_entry(msg, "DEBUG") +---@param event any +function Log:debug(msg, event) + self:add_entry(self.levels.DEBUG, msg, event) end ---Add a log entry at INFO level ---@param msg any -function Log:info(msg) - self:add_entry(msg, "INFO") +---@param event any +function Log:info(msg, event) + self:add_entry(self.levels.INFO, msg, event) end ---Add a log entry at WARN level ---@param msg any -function Log:warn(msg) - self:add_entry(msg, "WARN") +---@param event any +function Log:warn(msg, event) + self:add_entry(self.levels.WARN, msg, event) end ---Add a log entry at ERROR level ---@param msg any -function Log:error(msg) - self:add_entry(msg, "ERROR") +---@param event any +function Log:error(msg, event) + self:add_entry(self.levels.ERROR, msg, event) end setmetatable({}, Log) + return Log diff --git a/lua/lvim/plugins.lua b/lua/lvim/plugins.lua index 88cd7ad4..f1c1dd1f 100644 --- a/lua/lvim/plugins.lua +++ b/lua/lvim/plugins.lua @@ -8,6 +8,8 @@ return { { "williamboman/nvim-lsp-installer", }, + { "rcarriga/nvim-notify" }, + { "Tastyep/structlog.nvim" }, { "nvim-lua/popup.nvim" }, { "nvim-lua/plenary.nvim" }, -- cgit v1.2.3