diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index b3051463a..0be5fc518 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -22,13 +22,21 @@ body: options: - label: "Confirm" required: true + - type: checkboxes + id: not-user-config-issue + attributes: + label: "Not a user config issue" + description: "This issue _persists_ after removing ALL user configs. If this is not the case, you should open a [Custom (User) Config Issue](https://github.com/ayamir/nvimdots/issues/new?assignees=&labels=usage&projects=&template=custom_config.yml) instead." + options: + - label: "Confirm" + required: true - type: input id: nvim-version attributes: label: "Neovim version" description: "Paste the output of `nvim --version` here" - placeholder: "NVIM v0.8.0-dev+199-g2875d45e7" + placeholder: "NVIM v0.10.0-dev-873+g71ad771ea" validations: required: true - type: input @@ -61,6 +69,7 @@ body: - main (Default/Latest) - 0.8 (Legacy) - 0.7 (Deprecated) + - 0.10 (Nightly) validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/custom_config.yml b/.github/ISSUE_TEMPLATE/custom_config.yml new file mode 100644 index 000000000..04eb02719 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/custom_config.yml @@ -0,0 +1,110 @@ +name: Custom (User) Config Issue +description: Problems when trying to implement your custom config +labels: [usage] +body: + - type: markdown + attributes: + value: | + _Before requesting:_ Make sure you've read through our [Wiki: Usage](https://github.com/ayamir/nvimdots/wiki/Usage) before you start to add things to nvimdots! + + - type: checkboxes + id: is-latest-commit + attributes: + label: "Version confirmation" + description: "The local configuration is up-to-date in the current branch and this issue _persists_." + options: + - label: "Confirm" + required: true + - type: checkboxes + id: prerequisites-done + attributes: + label: "Following prerequisites" + description: "I've checked everything mentioned in [Wiki: Prerequisites](https://github.com/ayamir/nvimdots/wiki/Prerequisites)." + options: + - label: "Confirm" + required: true + + - type: input + id: nvim-version + attributes: + label: "Neovim version" + description: "Paste the output of `nvim --version` here" + placeholder: "NVIM v0.10.0-dev-873+g71ad771ea" + validations: + required: true + - type: dropdown + id: branch-info + attributes: + label: "Branch info" + description: "This issue template mainly targets `main` branch. Check the output of `git rev-parse --abbrev-ref HEAD` if you're not sure." + options: + - main (Default/Latest) + - 0.8 (Legacy) + - 0.7 (Deprecated) + - 0.10 (Nightly) + validations: + required: true + + - type: textarea + id: folder-structure-ta + attributes: + label: "Minimal (user) folder structure required to reproduce the issue" + description: "Note: You only need to describe where the *new/modified files* are. This section will be automatically formatted." + render: console + placeholder: | + └── lua/ + ├── core/ + ├── keymap/ default keymaps + ├── modules/ default plugins and plugin configs + └── user custom configs root directory + ├── configs/ custom plugin config folder + │ ├── dap-clients/ custom dap client config folder + │ ├── lsp-servers/ custom lsp server config folder + │ └── your-config.lua your plugin configs (if applicable) + ├── keymap/ custom keymap folder + │ └── your-config.lua your keymap overrides (if applicable) + ├── plugins/ custom plugin folder + │ └── your-config.lua your plugins (if applicable) + ├── event.lua custom `core/events.lua` overrides + ├── options.lua custom `core/options.lua` overrides + └── settings.lua custom `core/settings.lua` overrides + validations: + required: true + + - type: textarea + id: repro-steps + attributes: + label: "Minimal config with steps on how to reproduce the issue" + description: "Note: Issues without any information will be closed directly" + placeholder: | + This is my custom config (`specs.lua`): + ```lua + return { + popup = { + delay_ms = 20, + } + } + ``` + + Steps to reproduce the behavior: + 1. Go to '...' + 2. Click on '....' + 3. Scroll down to '....' + 4. See error + validations: + required: true + + - type: textarea + id: expected-behavior + attributes: + label: "Expected behavior" + description: "Describe the behavior you expect" + validations: + required: true + - type: textarea + id: extras + attributes: + label: Additional information + description: If applicable, you may include logs, images, or videos to help explain your problem + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/lsp_issue_report.yml b/.github/ISSUE_TEMPLATE/lsp_issue_report.yml index 6c7db3d5d..068800536 100644 --- a/.github/ISSUE_TEMPLATE/lsp_issue_report.yml +++ b/.github/ISSUE_TEMPLATE/lsp_issue_report.yml @@ -22,13 +22,21 @@ body: options: - label: "Confirm" required: true + - type: checkboxes + id: not-user-config-issue + attributes: + label: "Not a user config issue" + description: "This issue _persists_ after removing ALL user configs. If this is not the case, you should open a [Custom (User) Config Issue](https://github.com/ayamir/nvimdots/issues/new?assignees=&labels=usage&projects=&template=custom_config.yml) instead." + options: + - label: "Confirm" + required: true - type: input id: nvim-version attributes: label: "Neovim version" description: "Paste the output of `nvim --version` here" - placeholder: "NVIM v0.8.0-dev+199-g2875d45e7" + placeholder: "NVIM v0.10.0-dev-873+g71ad771ea" validations: required: true - type: input @@ -61,6 +69,7 @@ body: - main (Default/Latest) - 0.8 (Legacy) - 0.7 (Deprecated) + - 0.10 (Nightly) validations: required: true - type: dropdown diff --git a/.gitignore b/.gitignore index c11568d93..8dec07754 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ lua/modules/plugins/custom.lua lua/modules/configs/custom +lua/user diff --git a/lua/core/event.lua b/lua/core/event.lua index c4b3e3d81..c4a6f4cb5 100644 --- a/lua/core/event.lua +++ b/lua/core/event.lua @@ -13,6 +13,7 @@ function autocmd.nvim_create_augroups(definitions) end end +-- defer setting LSP-related keymaps till LspAttach local mapping = require("keymap.completion") vim.api.nvim_create_autocmd("LspAttach", { group = vim.api.nvim_create_augroup("LspKeymapLoader", { clear = true }), @@ -151,8 +152,7 @@ function autocmd.load_autocmds() }, }, } - - autocmd.nvim_create_augroups(definitions) + autocmd.nvim_create_augroups(require("modules.utils").extend_config(definitions, "user.event")) end autocmd.load_autocmds() diff --git a/lua/core/options.lua b/lua/core/options.lua index 529c77f0e..e94197f28 100644 --- a/lua/core/options.lua +++ b/lua/core/options.lua @@ -121,19 +121,20 @@ local function load_options() vim.g.python3_host_prog = use_if_defined(vim.g.python3_host_prog, "python3") end - for name, value in pairs(global_local) do - vim.o[name] = value - end - + -- custom sqlite3 provider local sqlite_clib_path = os.getenv("SQLITE_CLIB_PATH") - -- Try environment variable first if not isempty(sqlite_clib_path) then + -- Try environment variable first vim.g.sqlite_clib_path = sqlite_clib_path - -- Fix sqlite3 missing-lib issue on Windows elseif global.is_windows then + -- Fix sqlite3 missing-lib issue on Windows -- Download the DLLs form https://www.sqlite.org/download.html vim.g.sqlite_clib_path = global.home .. "/Documents/sqlite-dll-win64-x64-3400200/sqlite3.dll" end + + for name, value in pairs(require("modules.utils").extend_config(global_local, "user.options")) do + vim.o[name] = value + end end load_options() diff --git a/lua/core/pack.lua b/lua/core/pack.lua index 7c1d537a3..54ad4482e 100644 --- a/lua/core/pack.lua +++ b/lua/core/pack.lua @@ -5,6 +5,7 @@ local vim_path = global.vim_path local data_dir = global.data_dir local lazy_path = data_dir .. "lazy/lazy.nvim" local modules_dir = vim_path .. "/lua/modules" +local user_config_dir = vim_path .. "/lua/user" local settings = require("core.settings") local use_ssh = settings.use_ssh @@ -24,28 +25,31 @@ function Lazy:load_plugins() local append_nativertp = function() package.path = package.path - .. string.format(";%s;%s", modules_dir .. "/configs/?.lua", modules_dir .. "/configs/?/init.lua") + .. string.format( + ";%s;%s;%s", + modules_dir .. "/configs/?.lua", + modules_dir .. "/configs/?/init.lua", + user_config_dir + ) end local get_plugins_list = function() local list = {} local plugins_list = vim.split(fn.glob(modules_dir .. "/plugins/*.lua"), "\n") - if type(plugins_list) == "table" then - for _, f in ipairs(plugins_list) do - -- fill list with `plugins/*.lua`'s path used for later `require` like this: - -- list[#list + 1] = "plugins/completion.lua" - list[#list + 1] = f:sub(#modules_dir - 6, -1) - end + local user_plugins_list = vim.split(fn.glob(user_config_dir .. "/plugins/*.lua"), "\n", { trimempty = true }) + vim.list_extend(plugins_list, user_plugins_list) + for _, f in ipairs(plugins_list) do + -- aggregate the plugins from `/plugins/*.lua` and `/user/plugins/*.lua` to a plugin list of a certain field for later `require` action. + -- current fields contains: completion, editor, lang, tool, ui + list[#list + 1] = f:find(modules_dir) and f:sub(#modules_dir - 6, -1) or f:sub(#user_config_dir - 3, -1) end return list end append_nativertp() - local plugins_file = get_plugins_list() - for _, m in ipairs(plugins_file) do - -- require modules which returned in previous operation like this: - -- local modules = require("modules/plugins/completion.lua") + for _, m in ipairs(get_plugins_list()) do + -- require modules returned from `get_plugins_list()` function. local modules = require(m:sub(0, #m - 4)) if type(modules) == "table" then for name, conf in pairs(modules) do @@ -53,6 +57,9 @@ function Lazy:load_plugins() end end end + for _, name in ipairs(settings.disabled_plugins) do + self.modules[#self.modules + 1] = { name, enabled = false } + end end function Lazy:load_lazy() diff --git a/lua/core/settings.lua b/lua/core/settings.lua index c4d8d4517..b005f8e6f 100644 --- a/lua/core/settings.lua +++ b/lua/core/settings.lua @@ -36,6 +36,11 @@ settings["format_disabled_dirs"] = { "~/format_disabled_dir", } +-- Set the plugins to disable here. +-- Example: "Some-User/A-Repo" +---@type string[] +settings["disabled_plugins"] = {} + -- Set it to false if you don't use nvim to open big files. ---@type boolean settings["load_big_files_faster"] = true @@ -118,4 +123,4 @@ settings["dap_deps"] = { "python", -- Python (debugpy) } -return settings +return require("modules.utils").extend_config(settings, "user.settings") diff --git a/lua/keymap/completion.lua b/lua/keymap/completion.lua index 036acfdf1..dfec1b256 100644 --- a/lua/keymap/completion.lua +++ b/lua/keymap/completion.lua @@ -12,7 +12,7 @@ local mapping = {} function mapping.lsp(buf) local map = { - -- LSP-related keymaps, work only when event = { "InsertEnter", "LspStart" } + -- LSP-related keymaps, ONLY effective in buffers with LSP(s) attached ["n|li"] = map_cr("LspInfo"):with_buffer(buf):with_desc("lsp: Info"), ["n|lr"] = map_cr("LspRestart"):with_buffer(buf):with_nowait():with_desc("lsp: Restart"), ["n|go"] = map_cr("SymbolsOutline"):with_buffer(buf):with_desc("lsp: Toggle outline"), @@ -35,6 +35,11 @@ function mapping.lsp(buf) ["n|co"] = map_cr("Lspsaga outgoing_calls"):with_buffer(buf):with_desc("lsp: Show outgoing calls"), } bind.nvim_load_mapping(map) + + local ok, user_mappings = pcall(require, "user.keymap.completion") + if ok and type(user_mappings.lsp) == "function" then + require("modules.utils.keymap").replace(user_mappings.lsp(buf)) + end end return mapping diff --git a/lua/keymap/init.lua b/lua/keymap/init.lua index 412ef59ca..dfef620c9 100644 --- a/lua/keymap/init.lua +++ b/lua/keymap/init.lua @@ -27,3 +27,9 @@ require("keymap.editor") require("keymap.lang") require("keymap.tool") require("keymap.ui") + +-- User keymaps +local ok, mappings = pcall(require, "user.keymap.init") +if ok then + require("modules.utils.keymap").replace(mappings) +end diff --git a/lua/modules/configs/completion/cmp.lua b/lua/modules/configs/completion/cmp.lua index 04918cdcf..ae4f6506f 100644 --- a/lua/modules/configs/completion/cmp.lua +++ b/lua/modules/configs/completion/cmp.lua @@ -68,7 +68,7 @@ return function() } local cmp = require("cmp") - cmp.setup({ + require("modules.utils").load_plugin("cmp", { preselect = cmp.PreselectMode.Item, window = { completion = { diff --git a/lua/modules/configs/completion/codeium.lua b/lua/modules/configs/completion/codeium.lua index 40bbd04fe..229eab65d 100644 --- a/lua/modules/configs/completion/codeium.lua +++ b/lua/modules/configs/completion/codeium.lua @@ -1,3 +1,3 @@ return function() - require("codeium").setup({}) + require("modules.utils").load_plugin("codeium", {}) end diff --git a/lua/modules/configs/completion/copilot-cmp.lua b/lua/modules/configs/completion/copilot-cmp.lua index d8689880c..26d1dadf7 100644 --- a/lua/modules/configs/completion/copilot-cmp.lua +++ b/lua/modules/configs/completion/copilot-cmp.lua @@ -1,3 +1,3 @@ return function() - require("copilot_cmp").setup({}) + require("modules.utils").load_plugin("copilot_cmp", {}) end diff --git a/lua/modules/configs/completion/copilot.lua b/lua/modules/configs/completion/copilot.lua index f1fd63b1f..96de94fd1 100644 --- a/lua/modules/configs/completion/copilot.lua +++ b/lua/modules/configs/completion/copilot.lua @@ -1,6 +1,6 @@ return function() vim.defer_fn(function() - require("copilot").setup({ + require("modules.utils").load_plugin("copilot", { cmp = { enabled = true, method = "getCompletionsCycling", diff --git a/lua/modules/configs/completion/glance.lua b/lua/modules/configs/completion/glance.lua index 2abb03ce4..f2950ded1 100644 --- a/lua/modules/configs/completion/glance.lua +++ b/lua/modules/configs/completion/glance.lua @@ -1,9 +1,8 @@ return function() local icons = { ui = require("modules.utils.icons").get("ui", true) } - local glance = require("glance") - local actions = glance.actions + local actions = require("glance").actions - glance.setup({ + require("modules.utils").load_plugin("glance", { height = 20, zindex = 50, preview_win_opts = { diff --git a/lua/modules/configs/completion/lsp-signature.lua b/lua/modules/configs/completion/lsp-signature.lua index 282001322..aacc20cb7 100644 --- a/lua/modules/configs/completion/lsp-signature.lua +++ b/lua/modules/configs/completion/lsp-signature.lua @@ -1,5 +1,5 @@ return function() - require("lsp_signature").setup({ + require("modules.utils").load_plugin("lsp_signature", { bind = true, -- TODO: Remove the following line when nvim-cmp#1613 gets resolved check_completion_visible = false, diff --git a/lua/modules/configs/completion/lsp.lua b/lua/modules/configs/completion/lsp.lua index 6bd0436c2..895c879b6 100644 --- a/lua/modules/configs/completion/lsp.lua +++ b/lua/modules/configs/completion/lsp.lua @@ -1,151 +1,22 @@ return function() - local diagnostics_virtual_text = require("core.settings").diagnostics_virtual_text - local diagnostics_level = require("core.settings").diagnostics_level - local is_windows = require("core.global").is_windows - local nvim_lsp = require("lspconfig") - local mason = require("mason") - local mason_registry = require("mason-registry") - local mason_lspconfig = require("mason-lspconfig") - require("lspconfig.ui.windows").default_options.border = "rounded" - - local icons = { - ui = require("modules.utils.icons").get("ui", true), - misc = require("modules.utils.icons").get("misc", true), - } - - mason.setup({ - ui = { - border = "single", - icons = { - package_pending = icons.ui.Modified_alt, - package_installed = icons.ui.Check, - package_uninstalled = icons.misc.Ghost, - }, - keymaps = { - toggle_server_expand = "", - install_server = "i", - update_server = "u", - check_server_version = "c", - update_all_servers = "U", - check_outdated_servers = "C", - uninstall_server = "X", - cancel_installation = "", - }, - }, - }) - - -- Additional plugins for pylsp - mason_registry:on( - "package:install:success", - vim.schedule_wrap(function(pkg) - if pkg.name ~= "python-lsp-server" then - return - end - - local venv = vim.fn.stdpath("data") .. "/mason/packages/python-lsp-server/venv" - local python = is_windows and venv .. "/Scripts/python.exe" or venv .. "/bin/python" - local black = is_windows and venv .. "/Scripts/black.exe" or venv .. "/bin/black" - local ruff = is_windows and venv .. "/Scripts/ruff.exe" or venv .. "/bin/ruff" - - require("plenary.job") - :new({ - command = python, - args = { - "-m", - "pip", - "install", - "-U", - "--disable-pip-version-check", - "python-lsp-black", - "python-lsp-ruff", - "pylsp-rope", - }, - cwd = venv, - env = { VIRTUAL_ENV = venv }, - on_exit = function() - if vim.fn.executable(black) == 1 and vim.fn.executable(ruff) == 1 then - vim.notify( - "Finished installing pylsp plugins", - vim.log.levels.INFO, - { title = "[lsp] Install Status" } - ) - else - vim.notify( - "Failed to install pylsp plugins. [Executable not found]", - vim.log.levels.ERROR, - { title = "[lsp] Install Failure" } - ) - end - end, - on_start = function() - vim.notify( - "Now installing pylsp plugins...", - vim.log.levels.INFO, - { title = "[lsp] Install Status", timeout = 6000 } - ) - end, - on_stderr = function(_, msg_stream) - vim.notify(msg_stream, vim.log.levels.ERROR, { title = "[lsp] Install Failure" }) - end, - }) - :start() - end) - ) - - mason_lspconfig.setup({ - ensure_installed = require("core.settings").lsp_deps, - }) - - vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { - signs = true, - underline = true, - virtual_text = diagnostics_virtual_text and { - severity_limit = diagnostics_level, - } or false, - -- set update_in_insert to false bacause it was enabled by lspsaga - update_in_insert = false, - }) + require("completion.mason").setup() + require("completion.mason-lspconfig").setup() local opts = { capabilities = require("cmp_nvim_lsp").default_capabilities(vim.lsp.protocol.make_client_capabilities()), } - ---A handler to setup all servers defined under `completion/servers/*.lua` - ---@param lsp_name string - local function mason_lsp_handler(lsp_name) - local ok, custom_handler = pcall(require, "completion.servers." .. lsp_name) - if not ok then - -- Default to use factory config for server(s) that doesn't include a spec - nvim_lsp[lsp_name].setup(opts) - return - elseif type(custom_handler) == "function" then - --- Case where language server requires its own setup - --- Make sure to call require("lspconfig")[lsp_name].setup() in the function - --- See `clangd.lua` for example. - custom_handler(opts) - elseif type(custom_handler) == "table" then - nvim_lsp[lsp_name].setup(vim.tbl_deep_extend("force", opts, custom_handler)) - else - vim.notify( - string.format( - "Failed to setup [%s].\n\nServer definition under `completion/servers` must return\neither a fun(opts) or a table (got '%s' instead)", - lsp_name, - type(custom_handler) - ), - vim.log.levels.ERROR, - { title = "nvim-lspconfig" } - ) - end - end - - mason_lspconfig.setup_handlers({ mason_lsp_handler }) - -- Setup lsps that are not supported by `mason.nvim` but supported by `nvim-lspconfig` here. if vim.fn.executable("dart") == 1 then - local _opts = require("completion.servers.dartls") + local ok, _opts = pcall(require, "user.configs.lsp-servers.dartls") + if not ok then + _opts = require("completion.servers.dartls") + end local final_opts = vim.tbl_deep_extend("keep", _opts, opts) nvim_lsp.dartls.setup(final_opts) end + pcall(require, "user.configs.lsp") + vim.api.nvim_command([[LspStart]]) -- Start LSPs end diff --git a/lua/modules/configs/completion/lspsaga.lua b/lua/modules/configs/completion/lspsaga.lua index 3b977b003..35c2a2a5d 100644 --- a/lua/modules/configs/completion/lspsaga.lua +++ b/lua/modules/configs/completion/lspsaga.lua @@ -25,7 +25,7 @@ return function() set_sidebar_icons() - require("lspsaga").setup({ + require("modules.utils").load_plugin("lspsaga", { -- Breadcrumbs: https://dev.neovim.pro/lspsaga/breadcrumbs/ symbol_in_winbar = { enable = true, diff --git a/lua/modules/configs/completion/luasnip.lua b/lua/modules/configs/completion/luasnip.lua index ac343855e..d4ecd2b84 100644 --- a/lua/modules/configs/completion/luasnip.lua +++ b/lua/modules/configs/completion/luasnip.lua @@ -4,11 +4,11 @@ return function() vim.opt.rtp:append(snippet_path) end - require("luasnip").config.set_config({ + require("modules.utils").load_plugin("luasnip", { history = true, update_events = "TextChanged,TextChangedI", delete_check_events = "TextChanged,InsertLeave", - }) + }, false, require("luasnip").config.set_config) require("luasnip.loaders.from_lua").lazy_load() require("luasnip.loaders.from_vscode").lazy_load() require("luasnip.loaders.from_snipmate").lazy_load() diff --git a/lua/modules/configs/completion/mason-lspconfig.lua b/lua/modules/configs/completion/mason-lspconfig.lua new file mode 100644 index 000000000..fdf54587c --- /dev/null +++ b/lua/modules/configs/completion/mason-lspconfig.lua @@ -0,0 +1,63 @@ +local M = {} + +M.setup = function() + local diagnostics_virtual_text = require("core.settings").diagnostics_virtual_text + local diagnostics_level = require("core.settings").diagnostics_level + + local nvim_lsp = require("lspconfig") + local mason_lspconfig = require("mason-lspconfig") + require("lspconfig.ui.windows").default_options.border = "rounded" + + require("modules.utils").load_plugin("mason-lspconfig", { + ensure_installed = require("core.settings").lsp_deps, + }) + + vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { + signs = true, + underline = true, + virtual_text = diagnostics_virtual_text and { + severity_limit = diagnostics_level, + } or false, + -- set update_in_insert to false bacause it was enabled by lspsaga + update_in_insert = false, + }) + + local opts = { + capabilities = require("cmp_nvim_lsp").default_capabilities(vim.lsp.protocol.make_client_capabilities()), + } + ---A handler to setup all servers defined under `completion/servers/*.lua` + ---@param lsp_name string + local function mason_lsp_handler(lsp_name) + local ok, custom_handler = pcall(require, "user.configs.lsp-servers." .. lsp_name) + -- Use preset if there is no user definition + if not ok then + ok, custom_handler = pcall(require, "completion.servers." .. lsp_name) + end + if not ok then + -- Default to use factory config for server(s) that doesn't include a spec + nvim_lsp[lsp_name].setup(opts) + return + elseif type(custom_handler) == "function" then + --- Case where language server requires its own setup + --- Make sure to call require("lspconfig")[lsp_name].setup() in the function + --- See `clangd.lua` for example. + custom_handler(opts) + elseif type(custom_handler) == "table" then + nvim_lsp[lsp_name].setup(vim.tbl_deep_extend("force", opts, custom_handler)) + else + vim.notify( + string.format( + "Failed to setup [%s].\n\nServer definition under `completion/servers` must return\neither a fun(opts) or a table (got '%s' instead)", + lsp_name, + type(custom_handler) + ), + vim.log.levels.ERROR, + { title = "nvim-lspconfig" } + ) + end + end + + mason_lspconfig.setup_handlers({ mason_lsp_handler }) +end + +return M diff --git a/lua/modules/configs/completion/mason-null-ls.lua b/lua/modules/configs/completion/mason-null-ls.lua new file mode 100644 index 000000000..d077fec41 --- /dev/null +++ b/lua/modules/configs/completion/mason-null-ls.lua @@ -0,0 +1,12 @@ +local M = {} + +M.setup = function() + require("modules.utils").load_plugin("mason-null-ls", { + ensure_installed = require("core.settings").null_ls_deps, + automatic_installation = false, + automatic_setup = true, + handlers = {}, + }) +end + +return M diff --git a/lua/modules/configs/completion/mason.lua b/lua/modules/configs/completion/mason.lua new file mode 100644 index 000000000..4773532fa --- /dev/null +++ b/lua/modules/configs/completion/mason.lua @@ -0,0 +1,94 @@ +local M = {} + +M.setup = function() + local is_windows = require("core.global").is_windows + + local mason_registry = require("mason-registry") + require("lspconfig.ui.windows").default_options.border = "rounded" + + local icons = { + ui = require("modules.utils.icons").get("ui", true), + misc = require("modules.utils.icons").get("misc", true), + } + + require("modules.utils").load_plugin("mason", { + ui = { + border = "single", + icons = { + package_pending = icons.ui.Modified_alt, + package_installed = icons.ui.Check, + package_uninstalled = icons.misc.Ghost, + }, + keymaps = { + toggle_server_expand = "", + install_server = "i", + update_server = "u", + check_server_version = "c", + update_all_servers = "U", + check_outdated_servers = "C", + uninstall_server = "X", + cancel_installation = "", + }, + }, + }) + + -- Additional plugins for pylsp + mason_registry:on( + "package:install:success", + vim.schedule_wrap(function(pkg) + if pkg.name ~= "python-lsp-server" then + return + end + + local venv = vim.fn.stdpath("data") .. "/mason/packages/python-lsp-server/venv" + local python = is_windows and venv .. "/Scripts/python.exe" or venv .. "/bin/python" + local black = is_windows and venv .. "/Scripts/black.exe" or venv .. "/bin/black" + local ruff = is_windows and venv .. "/Scripts/ruff.exe" or venv .. "/bin/ruff" + + require("plenary.job") + :new({ + command = python, + args = { + "-m", + "pip", + "install", + "-U", + "--disable-pip-version-check", + "python-lsp-black", + "python-lsp-ruff", + "pylsp-rope", + }, + cwd = venv, + env = { VIRTUAL_ENV = venv }, + on_exit = function() + if vim.fn.executable(black) == 1 and vim.fn.executable(ruff) == 1 then + vim.notify( + "Finished installing pylsp plugins", + vim.log.levels.INFO, + { title = "[lsp] Install Status" } + ) + else + vim.notify( + "Failed to install pylsp plugins. [Executable not found]", + vim.log.levels.ERROR, + { title = "[lsp] Install Failure" } + ) + end + end, + on_start = function() + vim.notify( + "Now installing pylsp plugins...", + vim.log.levels.INFO, + { title = "[lsp] Install Status", timeout = 6000 } + ) + end, + on_stderr = function(_, msg_stream) + vim.notify(msg_stream, vim.log.levels.ERROR, { title = "[lsp] Install Failure" }) + end, + }) + :start() + end) + ) +end + +return M diff --git a/lua/modules/configs/completion/null-ls.lua b/lua/modules/configs/completion/null-ls.lua index f957ad6cb..ab42abdd7 100644 --- a/lua/modules/configs/completion/null-ls.lua +++ b/lua/modules/configs/completion/null-ls.lua @@ -1,6 +1,5 @@ return function() local null_ls = require("null-ls") - local mason_null_ls = require("mason-null-ls") local btns = null_ls.builtins -- Please set additional flags for the supported servers here @@ -27,7 +26,7 @@ return function() }), btns.formatting.rustfmt, } - null_ls.setup({ + require("modules.utils").load_plugin("null-ls", { border = "rounded", debug = false, log_level = "warn", @@ -35,12 +34,7 @@ return function() sources = sources, }) - mason_null_ls.setup({ - ensure_installed = require("core.settings").null_ls_deps, - automatic_installation = false, - automatic_setup = true, - handlers = {}, - }) + require("completion.mason-null-ls").setup() -- Setup usercmd to register/deregister available source(s) local function _gen_completion() diff --git a/lua/modules/configs/completion/symbols-outline.lua b/lua/modules/configs/completion/symbols-outline.lua index 923d06051..e44a9268e 100644 --- a/lua/modules/configs/completion/symbols-outline.lua +++ b/lua/modules/configs/completion/symbols-outline.lua @@ -5,7 +5,7 @@ return function() ui = require("modules.utils.icons").get("ui", true), } - require("symbols-outline").setup({ + require("modules.utils").load_plugin("symbols-outline", { highlight_hovered_item = true, show_guides = true, auto_preview = false, diff --git a/lua/modules/configs/editor/accelerated-jk.lua b/lua/modules/configs/editor/accelerated-jk.lua index 92e28a4e5..97132e0d9 100644 --- a/lua/modules/configs/editor/accelerated-jk.lua +++ b/lua/modules/configs/editor/accelerated-jk.lua @@ -1,5 +1,5 @@ return function() - require("accelerated-jk").setup({ + require("modules.utils").load_plugin("accelerated-jk", { mode = "time_driven", enable_deceleration = false, acceleration_motions = {}, diff --git a/lua/modules/configs/editor/autoclose.lua b/lua/modules/configs/editor/autoclose.lua index 39a2d84f2..d5e9b0d46 100644 --- a/lua/modules/configs/editor/autoclose.lua +++ b/lua/modules/configs/editor/autoclose.lua @@ -1,5 +1,5 @@ return function() - require("autoclose").setup({ + require("modules.utils").load_plugin("autoclose", { keys = { ["("] = { escape = false, close = true, pair = "()" }, ["["] = { escape = false, close = true, pair = "[]" }, diff --git a/lua/modules/configs/editor/autotag.lua b/lua/modules/configs/editor/autotag.lua index 6926a65d0..303b67fd2 100644 --- a/lua/modules/configs/editor/autotag.lua +++ b/lua/modules/configs/editor/autotag.lua @@ -1,5 +1,5 @@ return function() - require("nvim-ts-autotag").setup({ + require("modules.utils").load_plugin("nvim-ts-autotag", { filetypes = { "html", "javascript", diff --git a/lua/modules/configs/editor/better-escape.lua b/lua/modules/configs/editor/better-escape.lua index 7a80e9276..9d6c7bfb8 100644 --- a/lua/modules/configs/editor/better-escape.lua +++ b/lua/modules/configs/editor/better-escape.lua @@ -1,5 +1,5 @@ return function() - require("better_escape").setup({ + require("modules.utils").load_plugin("better_escape", { mapping = { "jk", "jj" }, -- a table with mappings to use timeout = vim.o.timeoutlen, -- the time in which the keys must be hit in ms. Use option timeoutlen by default clear_empty_lines = false, -- clear line after escaping if there is only whitespace diff --git a/lua/modules/configs/editor/bigfile.lua b/lua/modules/configs/editor/bigfile.lua index 90c6c9fbb..f5f0ae46d 100644 --- a/lua/modules/configs/editor/bigfile.lua +++ b/lua/modules/configs/editor/bigfile.lua @@ -15,7 +15,7 @@ return function() end, } - require("bigfile").setup({ + require("modules.utils").load_plugin("bigfile", { filesize = 1, -- size of the file in MiB pattern = { "*" }, -- autocmd pattern features = { -- features to disable diff --git a/lua/modules/configs/editor/cleverf.lua b/lua/modules/configs/editor/cleverf.lua index 731a7adec..2b640a933 100644 --- a/lua/modules/configs/editor/cleverf.lua +++ b/lua/modules/configs/editor/cleverf.lua @@ -8,4 +8,6 @@ return function() vim.g.clever_f_mark_direct_color = "CleverChar" vim.g.clever_f_mark_direct = true vim.g.clever_f_timeout_ms = 1500 + + require("modules.utils").load_plugin("cleverf", nil, true) end diff --git a/lua/modules/configs/editor/colorizer.lua b/lua/modules/configs/editor/colorizer.lua index d0e7569ab..efee45019 100644 --- a/lua/modules/configs/editor/colorizer.lua +++ b/lua/modules/configs/editor/colorizer.lua @@ -1,3 +1,3 @@ return function() - require("colorizer").setup({}) + require("modules.utils").load_plugin("colorizer", {}) end diff --git a/lua/modules/configs/editor/comment.lua b/lua/modules/configs/editor/comment.lua index 9f161ddfd..a4a0c2d57 100644 --- a/lua/modules/configs/editor/comment.lua +++ b/lua/modules/configs/editor/comment.lua @@ -1,5 +1,5 @@ return function() - require("Comment").setup({ + require("modules.utils").load_plugin("Comment", { -- Add a space b/w comment and the line padding = true, -- Whether the cursor should stay at its position diff --git a/lua/modules/configs/editor/hop.lua b/lua/modules/configs/editor/hop.lua index be2a5ebf7..d52fa5bd6 100644 --- a/lua/modules/configs/editor/hop.lua +++ b/lua/modules/configs/editor/hop.lua @@ -1,3 +1,3 @@ return function() - require("hop").setup({ keys = "etovxqpdygfblzhckisuran" }) + require("modules.utils").load_plugin("hop", { keys = "etovxqpdygfblzhckisuran" }) end diff --git a/lua/modules/configs/editor/persisted.lua b/lua/modules/configs/editor/persisted.lua index 8b1c9538e..003d8cb9d 100644 --- a/lua/modules/configs/editor/persisted.lua +++ b/lua/modules/configs/editor/persisted.lua @@ -1,5 +1,5 @@ return function() - require("persisted").setup({ + require("modules.utils").load_plugin("persisted", { save_dir = vim.fn.expand(vim.fn.stdpath("data") .. "/sessions/"), -- directory where session files are saved silent = false, -- silent nvim message when sourcing session file use_git_branch = true, -- create session files based on the branch of the git enabled repository diff --git a/lua/modules/configs/editor/rainbow_delims.lua b/lua/modules/configs/editor/rainbow_delims.lua index e263cbf6a..0f1a50aa2 100644 --- a/lua/modules/configs/editor/rainbow_delims.lua +++ b/lua/modules/configs/editor/rainbow_delims.lua @@ -40,4 +40,5 @@ return function() "RainbowDelimiterViolet", }, } + require("modules.utils").load_plugin("rainbow_delimiters", nil, true) end diff --git a/lua/modules/configs/editor/suda.lua b/lua/modules/configs/editor/suda.lua index bf77b65b1..d70aa61b6 100644 --- a/lua/modules/configs/editor/suda.lua +++ b/lua/modules/configs/editor/suda.lua @@ -1,3 +1,5 @@ return function() vim.g["suda#prompt"] = "Enter administrator password: " + + require("modules.utils").load_plugin("suda", nil, true) end diff --git a/lua/modules/configs/editor/tabout.lua b/lua/modules/configs/editor/tabout.lua index dd6915f27..f333c683e 100644 --- a/lua/modules/configs/editor/tabout.lua +++ b/lua/modules/configs/editor/tabout.lua @@ -1,5 +1,5 @@ return function() - require("tabout").setup({ + require("modules.utils").load_plugin("tabout", { tabkey = "", -- key to trigger tabout, set to an empty string to disable backwards_tabkey = "", -- key to trigger backwards tabout, set to an empty string to disable act_as_tab = true, -- shift content if tab out is not possible diff --git a/lua/modules/configs/editor/treesitter.lua b/lua/modules/configs/editor/treesitter.lua index 2ee63f399..d9d352a25 100644 --- a/lua/modules/configs/editor/treesitter.lua +++ b/lua/modules/configs/editor/treesitter.lua @@ -4,7 +4,7 @@ return vim.schedule_wrap(function() vim.api.nvim_set_option_value("foldmethod", "expr", {}) vim.api.nvim_set_option_value("foldexpr", "nvim_treesitter#foldexpr()", {}) - require("nvim-treesitter.configs").setup({ + require("modules.utils").load_plugin("nvim-treesitter", { ensure_installed = { "bash", "c", @@ -72,7 +72,7 @@ return vim.schedule_wrap(function() }, context_commentstring = { enable = true, enable_autocmd = false }, matchup = { enable = true }, - }) + }, false, require("nvim-treesitter.configs").setup) require("nvim-treesitter.install").prefer_git = true if use_ssh then local parsers = require("nvim-treesitter.parsers").get_parser_configs() diff --git a/lua/modules/configs/editor/ts-context.lua b/lua/modules/configs/editor/ts-context.lua index 4f31e5a70..7dcf25c44 100644 --- a/lua/modules/configs/editor/ts-context.lua +++ b/lua/modules/configs/editor/ts-context.lua @@ -1,5 +1,5 @@ return function() - require("treesitter-context").setup({ + require("modules.utils").load_plugin("treesitter-context", { enable = true, max_lines = 0, -- How many lines the window should span. Values <= 0 mean no limit. min_window_height = 0, -- Minimum editor window height to enable context. Values <= 0 mean no limit. diff --git a/lua/modules/configs/editor/vim-illuminate.lua b/lua/modules/configs/editor/vim-illuminate.lua index c0cafbe76..906489008 100644 --- a/lua/modules/configs/editor/vim-illuminate.lua +++ b/lua/modules/configs/editor/vim-illuminate.lua @@ -1,5 +1,5 @@ return function() - require("illuminate").configure({ + require("modules.utils").load_plugin("vim-illuminate", { providers = { "lsp", "treesitter", @@ -24,5 +24,5 @@ return function() "toggleterm", }, under_cursor = false, - }) + }, false, require("illuminate").configure) end diff --git a/lua/modules/configs/lang/crates.lua b/lua/modules/configs/lang/crates.lua index f6272b312..e77c222b2 100644 --- a/lua/modules/configs/lang/crates.lua +++ b/lua/modules/configs/lang/crates.lua @@ -7,7 +7,7 @@ return function() kind = require("modules.utils.icons").get("kind", true), } - require("crates").setup({ + require("modules.utils").load_plugin("crates", { smart_insert = true, insert_closing_quote = true, avoid_prerelease = true, diff --git a/lua/modules/configs/lang/rust-tools.lua b/lua/modules/configs/lang/rust-tools.lua index b844e1463..0db716733 100644 --- a/lua/modules/configs/lang/rust-tools.lua +++ b/lua/modules/configs/lang/rust-tools.lua @@ -164,5 +164,5 @@ return function() }, } - require("rust-tools").setup(opts) + require("moudles.utils").load_plugin("rust-tools", opts) end diff --git a/lua/modules/configs/lang/vim-go.lua b/lua/modules/configs/lang/vim-go.lua index d5452ea94..f4279e367 100644 --- a/lua/modules/configs/lang/vim-go.lua +++ b/lua/modules/configs/lang/vim-go.lua @@ -2,4 +2,6 @@ return function() vim.g.go_doc_keywordprg_enabled = 0 vim.g.go_def_mapping_enabled = 0 vim.g.go_code_completion_enabled = 0 + + require("modules.utils").load_plugin("vim-go", nil, true) end diff --git a/lua/modules/configs/tool/dap/dapui.lua b/lua/modules/configs/tool/dap/dapui.lua index b588f0816..ab14dbc26 100644 --- a/lua/modules/configs/tool/dap/dapui.lua +++ b/lua/modules/configs/tool/dap/dapui.lua @@ -4,7 +4,7 @@ return function() dap = require("modules.utils.icons").get("dap"), } - require("dapui").setup({ + require("modules.utils").load_plugin("dapui", { force_buffers = true, icons = { expanded = icons.ui.ArrowOpen, diff --git a/lua/modules/configs/tool/dap/init.lua b/lua/modules/configs/tool/dap/init.lua index 8fff15a4e..f2fa42aa6 100644 --- a/lua/modules/configs/tool/dap/init.lua +++ b/lua/modules/configs/tool/dap/init.lua @@ -47,7 +47,11 @@ return function() ---@param config table local function mason_dap_handler(config) local dap_name = config.name - local ok, custom_handler = pcall(require, "tool.dap.clients." .. dap_name) + local ok, custom_handler = pcall(require, "user.configs.dap-clients." .. dap_name) + if not ok then + -- Use preset if there is no user definition + ok, custom_handler = pcall(require, "tool.dap.clients." .. dap_name) + end if not ok then -- Default to use factory config for clients(s) that doesn't include a spec mason_dap.default_setup(config) @@ -72,7 +76,7 @@ return function() end end - mason_dap.setup({ + require("modules.utils").load_plugin("mason-nvim-dap", { ensure_installed = require("core.settings").dap_deps, automatic_installation = true, handlers = { mason_dap_handler }, diff --git a/lua/modules/configs/tool/fcitx5.lua b/lua/modules/configs/tool/fcitx5.lua index c5bc70c94..c8b10e14e 100644 --- a/lua/modules/configs/tool/fcitx5.lua +++ b/lua/modules/configs/tool/fcitx5.lua @@ -1,5 +1,5 @@ return function() - require("fcitx5").setup({ + require("modules.utils").load_plugin("fcitx5", { msg = nil, -- string | nil: printed when startup is completed imname = { -- fcitx5.Imname | nil: imnames on each mode set as prior. See `:h map-table` for more in-depth information. norm = nil, -- string | nil: imname to set in normal mode. if nil, will restore the mode on exit. diff --git a/lua/modules/configs/tool/nvim-tree.lua b/lua/modules/configs/tool/nvim-tree.lua index 0930efed3..c799629c8 100644 --- a/lua/modules/configs/tool/nvim-tree.lua +++ b/lua/modules/configs/tool/nvim-tree.lua @@ -6,7 +6,7 @@ return function() ui = require("modules.utils.icons").get("ui"), } - require("nvim-tree").setup({ + require("modules.utils").load_plugin("nvim-tree", { auto_reload_on_write = true, create_in_closed_folder = false, disable_netrw = false, diff --git a/lua/modules/configs/tool/project.lua b/lua/modules/configs/tool/project.lua index 153d023ee..3d77ab7ad 100644 --- a/lua/modules/configs/tool/project.lua +++ b/lua/modules/configs/tool/project.lua @@ -1,5 +1,5 @@ return function() - require("project_nvim").setup({ + require("modules.utils").load_plugin("project_nvim", { manual_mode = false, detection_methods = { "lsp", "pattern" }, patterns = { ".git", "_darcs", ".hg", ".bzr", ".svn", "Makefile", "package.json" }, diff --git a/lua/modules/configs/tool/smartyank.lua b/lua/modules/configs/tool/smartyank.lua index d354de52a..551ae6fab 100644 --- a/lua/modules/configs/tool/smartyank.lua +++ b/lua/modules/configs/tool/smartyank.lua @@ -1,5 +1,5 @@ return function() - require("smartyank").setup({ + require("modules.utils").load_plugin("smartyank", { highlight = { enabled = false, -- highlight yanked text higroup = "IncSearch", -- highlight group of yanked text diff --git a/lua/modules/configs/tool/sniprun.lua b/lua/modules/configs/tool/sniprun.lua index 06f018542..78cb97941 100644 --- a/lua/modules/configs/tool/sniprun.lua +++ b/lua/modules/configs/tool/sniprun.lua @@ -1,5 +1,5 @@ return function() - require("sniprun").setup({ + require("modules.utils").load_plugin("sniprun", { selected_interpreters = {}, -- " use those instead of the default for the current filetype repl_enable = {}, -- " enable REPL-like behavior for the given interpreters repl_disable = {}, -- " disable REPL-like behavior for the given interpreters diff --git a/lua/modules/configs/tool/telescope.lua b/lua/modules/configs/tool/telescope.lua index cdd38cea6..01f7854da 100644 --- a/lua/modules/configs/tool/telescope.lua +++ b/lua/modules/configs/tool/telescope.lua @@ -2,7 +2,7 @@ return function() local icons = { ui = require("modules.utils.icons").get("ui", true) } local lga_actions = require("telescope-live-grep-args.actions") - require("telescope").setup({ + require("modules.utils").load_plugin("telescope", { defaults = { vimgrep_arguments = { "rg", diff --git a/lua/modules/configs/tool/toggleterm.lua b/lua/modules/configs/tool/toggleterm.lua index dba129dfe..c05c2f64f 100644 --- a/lua/modules/configs/tool/toggleterm.lua +++ b/lua/modules/configs/tool/toggleterm.lua @@ -1,5 +1,5 @@ return function() - require("toggleterm").setup({ + require("modules.utils").load_plugin("toggleterm", { -- size can be a number or function which is passed the current terminal size = function(term) if term.direction == "horizontal" then diff --git a/lua/modules/configs/tool/trouble.lua b/lua/modules/configs/tool/trouble.lua index fe9fb60c0..386af479a 100644 --- a/lua/modules/configs/tool/trouble.lua +++ b/lua/modules/configs/tool/trouble.lua @@ -4,7 +4,7 @@ return function() diagnostics = require("modules.utils.icons").get("diagnostics"), } - require("trouble").setup({ + require("modules.utils").load_plugin("trouble", { position = "bottom", -- position of the list can be: bottom, top, left, right height = 10, -- height of the trouble list when position is top or bottom width = 50, -- width of the list when position is left or right diff --git a/lua/modules/configs/tool/which-key.lua b/lua/modules/configs/tool/which-key.lua index 319264fde..9c9d8d95f 100644 --- a/lua/modules/configs/tool/which-key.lua +++ b/lua/modules/configs/tool/which-key.lua @@ -4,7 +4,7 @@ return function() misc = require("modules.utils.icons").get("misc"), } - require("which-key").setup({ + require("modules.utils").load_plugin("which-key", { plugins = { presets = { operators = false, diff --git a/lua/modules/configs/tool/wilder.lua b/lua/modules/configs/tool/wilder.lua index 6f08ada28..45105b3f7 100644 --- a/lua/modules/configs/tool/wilder.lua +++ b/lua/modules/configs/tool/wilder.lua @@ -2,7 +2,6 @@ return function() local wilder = require("wilder") local icons = { ui = require("modules.utils.icons").get("ui") } - wilder.setup({ modes = { ":", "/", "?" } }) wilder.set_option("use_python_remote_plugin", 0) wilder.set_option("pipeline", { wilder.branch( @@ -61,4 +60,6 @@ return function() substitute = wildmenu_renderer, }) ) + + require("modules.utils").load_plugin("wilder", { modes = { ":", "/", "?" } }) end diff --git a/lua/modules/configs/ui/alpha.lua b/lua/modules/configs/ui/alpha.lua index beefe686d..b3d5f1a6d 100644 --- a/lua/modules/configs/ui/alpha.lua +++ b/lua/modules/configs/ui/alpha.lua @@ -1,5 +1,4 @@ return function() - local alpha = require("alpha") local dashboard = require("alpha.themes.dashboard") require("modules.utils").gen_alpha_hl() @@ -154,7 +153,7 @@ return function() dashboard.section.footer, } - alpha.setup(dashboard.opts) + require("modules.utils").load_plugin("alpha", dashboard.opts) vim.api.nvim_create_autocmd("User", { pattern = "LazyVimStarted", diff --git a/lua/modules/configs/ui/bufferline.lua b/lua/modules/configs/ui/bufferline.lua index 2b34868a9..f497a72cd 100644 --- a/lua/modules/configs/ui/bufferline.lua +++ b/lua/modules/configs/ui/bufferline.lua @@ -67,5 +67,5 @@ return function() opts = vim.tbl_deep_extend("force", opts, catppuccin_hl_overwrite) end - require("bufferline").setup(opts) + require("modules.utils").load_plugin("bufferline", opts) end diff --git a/lua/modules/configs/ui/catppuccin.lua b/lua/modules/configs/ui/catppuccin.lua index e2b63ac22..c4f1ae033 100644 --- a/lua/modules/configs/ui/catppuccin.lua +++ b/lua/modules/configs/ui/catppuccin.lua @@ -2,7 +2,7 @@ return function() local transparent_background = require("core.settings").transparent_background local clear = {} - require("catppuccin").setup({ + require("modules.utils").load_plugin("catppuccin", { flavour = "mocha", -- Can be one of: latte, frappe, macchiato, mocha background = { light = "latte", dark = "mocha" }, dim_inactive = { diff --git a/lua/modules/configs/ui/edge.lua b/lua/modules/configs/ui/edge.lua index 6f63356be..04d1ebc4a 100644 --- a/lua/modules/configs/ui/edge.lua +++ b/lua/modules/configs/ui/edge.lua @@ -5,4 +5,6 @@ return function() vim.g.edge_show_eob = 1 vim.g.edge_better_performance = 1 vim.g.edge_transparent_background = require("core.settings").transparent_background and 2 or 0 + + require("modules.utils").load_plugin("edge", nil, true) end diff --git a/lua/modules/configs/ui/fidget.lua b/lua/modules/configs/ui/fidget.lua index 5d5ffbf79..e2ef87a61 100644 --- a/lua/modules/configs/ui/fidget.lua +++ b/lua/modules/configs/ui/fidget.lua @@ -1,5 +1,5 @@ return function() - require("fidget").setup({ + require("modules.utils").load_plugin("fidget", { window = { blend = 0 }, sources = { ["null-ls"] = { ignore = true }, diff --git a/lua/modules/configs/ui/gitsigns.lua b/lua/modules/configs/ui/gitsigns.lua index cefc4712c..c70684266 100644 --- a/lua/modules/configs/ui/gitsigns.lua +++ b/lua/modules/configs/ui/gitsigns.lua @@ -1,6 +1,6 @@ return function() local mapping = require("keymap.ui") - require("gitsigns").setup({ + require("modules.utils").load_plugin("gitsigns", { signs = { add = { hl = "GitSignsAdd", diff --git a/lua/modules/configs/ui/indent-blankline.lua b/lua/modules/configs/ui/indent-blankline.lua index 36f4516d9..b7735bcc1 100644 --- a/lua/modules/configs/ui/indent-blankline.lua +++ b/lua/modules/configs/ui/indent-blankline.lua @@ -1,5 +1,5 @@ return function() - require("indent_blankline").setup({ + require("modules.utils").load_plugin("indent_blankline", { char = "│", context_char = "┃", show_first_indent_level = true, diff --git a/lua/modules/configs/ui/lualine.lua b/lua/modules/configs/ui/lualine.lua index ed6366fb7..9b3fcc951 100644 --- a/lua/modules/configs/ui/lualine.lua +++ b/lua/modules/configs/ui/lualine.lua @@ -254,7 +254,7 @@ return function() }, } - require("lualine").setup({ + require("modules.utils").load_plugin("lualine", { options = { icons_enabled = true, theme = custom_theme(), diff --git a/lua/modules/configs/ui/neodim.lua b/lua/modules/configs/ui/neodim.lua index 56f94fac1..17a5b262c 100644 --- a/lua/modules/configs/ui/neodim.lua +++ b/lua/modules/configs/ui/neodim.lua @@ -1,7 +1,7 @@ return function() local blend_color = require("modules.utils").gen_neodim_blend_attr() - require("neodim").setup({ + require("modules.utils").load_plugin("neodim", { alpha = 0.45, blend_color = blend_color, refresh_delay = 75, -- time in ms to wait after typing before refreshing diagnostics diff --git a/lua/modules/configs/ui/neoscroll.lua b/lua/modules/configs/ui/neoscroll.lua index 10235a846..9b1ae9069 100644 --- a/lua/modules/configs/ui/neoscroll.lua +++ b/lua/modules/configs/ui/neoscroll.lua @@ -1,5 +1,5 @@ return function() - require("neoscroll").setup({ + require("modules.utils").load_plugin("neoscroll", { -- All these keys will be mapped to their corresponding default scrolling animation mappings = { "", diff --git a/lua/modules/configs/ui/nord.lua b/lua/modules/configs/ui/nord.lua index 17f535539..c196a24eb 100644 --- a/lua/modules/configs/ui/nord.lua +++ b/lua/modules/configs/ui/nord.lua @@ -5,4 +5,6 @@ return function() vim.g.nord_disable_background = require("core.settings").transparent_background vim.g.nord_enable_sidebar_background = true vim.g.nord_italic = true + + require("modules.utils").load_plugin("nord", nil, true) end diff --git a/lua/modules/configs/ui/notify.lua b/lua/modules/configs/ui/notify.lua index 21f6168e9..2eacdfb23 100644 --- a/lua/modules/configs/ui/notify.lua +++ b/lua/modules/configs/ui/notify.lua @@ -6,7 +6,7 @@ return function() ui = require("modules.utils.icons").get("ui"), } - notify.setup({ + require("modules.utils").load_plugin("notify", { ---@usage Animation style one of { "fade", "slide", "fade_in_slide_out", "static" } stages = "fade", ---@usage Function called when a new window is opened, use for changing win settings/config diff --git a/lua/modules/configs/ui/paint.lua b/lua/modules/configs/ui/paint.lua index 434355659..5747cc2a9 100644 --- a/lua/modules/configs/ui/paint.lua +++ b/lua/modules/configs/ui/paint.lua @@ -1,5 +1,5 @@ return function() - require("paint").setup({ + require("modules.utils").load_plugin("paint", { ---type PaintHighlight[] highlights = { { diff --git a/lua/modules/configs/ui/scrollview.lua b/lua/modules/configs/ui/scrollview.lua index a304ec989..78a7c7ce7 100644 --- a/lua/modules/configs/ui/scrollview.lua +++ b/lua/modules/configs/ui/scrollview.lua @@ -1,7 +1,7 @@ return function() local icons = { diagnostics = require("modules.utils.icons").get("diagnostics", true) } - require("scrollview").setup({ + require("modules.utils").load_plugin("scrollview", { scrollview_mode = "virtual", excluded_filetypes = { "NvimTree", "terminal", "nofile", "Outline" }, winblend = 0, diff --git a/lua/modules/configs/ui/specs.lua b/lua/modules/configs/ui/specs.lua index e32382b1b..4fc97ec38 100644 --- a/lua/modules/configs/ui/specs.lua +++ b/lua/modules/configs/ui/specs.lua @@ -1,5 +1,5 @@ return function() - require("specs").setup({ + require("modules.utils").load_plugin("specs", { show_jumps = true, min_jump = 10, popup = { diff --git a/lua/modules/utils/init.lua b/lua/modules/utils/init.lua index 57bb46da1..f6ab9e88b 100644 --- a/lua/modules/utils/init.lua +++ b/lua/modules/utils/init.lua @@ -249,4 +249,104 @@ function M.tobool(value) end end +--- Function to recursively merge src into dst +--- Unlike vim.tbl_deep_extend(), this function extends if the original value is a list +---@paramm dst table @Table which will be modified and appended to +---@paramm src table @Table from which values will be inserted +---@return table @Modified table +local function tbl_recursive_merge(dst, src) + for key, value in pairs(src) do + if type(dst[key]) == "table" and type(value) == "function" then + dst[key] = value() + elseif type(dst[key]) == "table" and vim.tbl_islist(dst[key]) then + vim.list_extend(dst[key], value) + elseif type(dst[key]) == "table" and not vim.tbl_islist(dst[key]) then + tbl_recursive_merge(dst[key], value) + else + dst[key] = value + end + end + return dst +end + +-- Function to extend existing core configs (settings, events, etc.) +---@param config table @The default config to be merged with +---@param user_config string @The module name used to require user config +---@return table @Extended config +function M.extend_config(config, user_config) + local ok, extras = pcall(require, user_config) + if ok and type(extras) == "table" then + config = tbl_recursive_merge(config, extras) + end + return config +end + +---@param plugin_name string @Module name of the plugin (used to setup itself) +---@param opts nil|table @The default config to be merged with +---@param vim_plugin? boolean @If this plugin is written in vimscript or not +---@param setup_callback? function @Add new callback if the plugin needs unusual setup function +function M.load_plugin(plugin_name, opts, vim_plugin, setup_callback) + vim_plugin = vim_plugin or false + + -- Get the file name of the default config + local fname = debug.getinfo(2, "S").source:match("[^@/\\]*.lua$") + local ok, user_config = pcall(require, "user.configs." .. fname:sub(0, #fname - 4)) + if ok and vim_plugin then + if user_config == false then + -- Return early if the user explicitly requires disabling plugin setup + return + elseif type(user_config) == "function" then + -- OK, setup as instructed by the user + user_config() + else + vim.notify( + string.format( + "<%s> is not a typical Lua plugin, please return a function with\nthe corresponding options defined instead (usually via `vim.g.*`)", + plugin_name + ), + vim.log.levels.ERROR, + { title = "[utils] Runtime Error (User Config)" } + ) + end + elseif not vim_plugin then + if user_config == false then + -- Return early if the user explicitly requires disabling plugin setup + return + else + setup_callback = setup_callback or require(plugin_name).setup + -- User config exists? + if ok then + -- Extend base config if the returned user config is a table + if type(user_config) == "table" then + opts = tbl_recursive_merge(opts, user_config) + setup_callback(opts) + -- Replace base config if the returned user config is a function + elseif type(user_config) == "function" then + local user_opts = user_config() + if type(user_opts) == "table" then + setup_callback(user_opts) + end + else + vim.notify( + string.format( + [[ +Please return a `table` if you want to override some of the default options OR a +`function` returning a `table` if you want to replace the default options completely. + +We received a `%s` for plugin <%s>.]], + type(user_config), + plugin_name + ), + vim.log.levels.ERROR, + { title = "[utils] Runtime Error (User Config)" } + ) + end + else + -- Nothing provided... Fallback as default setup of the plugin + setup_callback(opts) + end + end + end +end + return M diff --git a/lua/modules/utils/keymap.lua b/lua/modules/utils/keymap.lua index 2b66a092d..e249250d5 100644 --- a/lua/modules/utils/keymap.lua +++ b/lua/modules/utils/keymap.lua @@ -92,6 +92,7 @@ local function get_fallback(map) end end +-- Amends a mapping (i.e., allows fallback when certain conditions are met) ---@param cond string ---@param mode string ---@param lhs string @@ -112,6 +113,23 @@ local function amend(cond, mode, lhs, rhs, opts) end, options) end +-- Completely replace a mapping +---@param mode string +---@param lhs string +---@param rhs string +---@param opts? table +---@param buf? boolean|number +local function replace(mode, lhs, rhs, opts, buf) + get_map(mode, lhs) + + local options = vim.deepcopy(opts) or {} + if buf and type(buf) == "number" then + vim.api.nvim_buf_set_keymap(buf, mode, lhs, rhs, options) + else + vim.api.nvim_set_keymap(mode, lhs, rhs, options) + end +end + ---Amend the existing keymap. ---@param cond string ---@param mode string | string[] @@ -128,6 +146,23 @@ local function modes_amend(cond, mode, lhs, rhs, opts) end end +---Replace the existing keymap. +---@param mode string | string[] +---@param lhs string +---@param rhs string +---@param opts? table +---@param buf? boolean|number +local function modes_replace(mode, lhs, rhs, opts, buf) + if type(mode) == "table" then + for _, m in ipairs(mode) do + replace(m, lhs, rhs, opts, buf) + end + else + replace(mode, lhs, rhs, opts, buf) + end +end + +---Amend the existing keymap. ---@param cond string ---@param global_flag string ---@param mapping table @@ -149,4 +184,22 @@ function M.amend(cond, global_flag, mapping) end end +---Replace the existing keymap. +---@param mapping table +function M.replace(mapping) + for key, value in pairs(mapping) do + local modes, keymap = key:match("([^|]*)|?(.*)") + if type(value) == "table" then + local rhs = value.cmd + local options = value.options + local buffer = value.buffer + modes_replace(vim.split(modes, ""), keymap, rhs, options, buffer) + elseif value == "" or value == false then + for _, m in ipairs(vim.split(modes, "")) do + get_map(m, keymap) + end + end + end +end + return M diff --git a/lua/user/configs/.gitkeep b/lua/user/configs/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/lua/user/configs/dap-clients/.gitkeep b/lua/user/configs/dap-clients/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/lua/user/configs/lsp-servers/.gitkeep b/lua/user/configs/lsp-servers/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/lua/user/event.lua b/lua/user/event.lua new file mode 100644 index 000000000..44bee88ca --- /dev/null +++ b/lua/user/event.lua @@ -0,0 +1,8 @@ +local definitions = { + -- Example + bufs = { + { "BufWritePre", "COMMIT_EDITMSG", "setlocal noundofile" }, + }, +} + +return definitions diff --git a/lua/user/keymap/completion.lua b/lua/user/keymap/completion.lua new file mode 100644 index 000000000..1000f157d --- /dev/null +++ b/lua/user/keymap/completion.lua @@ -0,0 +1,16 @@ +local mappings = {} + +-- Place global keymaps here. +mappings["plug_map"] = {} + +-- NOTE: This function is special! Keymaps defined here are ONLY effective in buffers with LSP(s) attached +-- NOTE: Make sure to include `:with_buffer(buf)` to limit the scope of your mappings. +---@param buf number @The effective bufnr +mappings["lsp"] = function(buf) + return { + -- Example + ["n|K"] = require("keymap.bind").map_cr("Lspsaga hover_doc"):with_buffer(buf):with_desc("lsp: Show doc"), + } +end + +return mappings diff --git a/lua/user/keymap/core.lua b/lua/user/keymap/core.lua new file mode 100644 index 000000000..a56470754 --- /dev/null +++ b/lua/user/keymap/core.lua @@ -0,0 +1 @@ +return {} diff --git a/lua/user/keymap/editor.lua b/lua/user/keymap/editor.lua new file mode 100644 index 000000000..a56470754 --- /dev/null +++ b/lua/user/keymap/editor.lua @@ -0,0 +1 @@ +return {} diff --git a/lua/user/keymap/init.lua b/lua/user/keymap/init.lua new file mode 100644 index 000000000..f4a08e258 --- /dev/null +++ b/lua/user/keymap/init.lua @@ -0,0 +1,9 @@ +return vim.tbl_extend( + "force", + require("user.keymap.core"), + require("user.keymap.completion").plug_map, + require("user.keymap.editor"), + require("user.keymap.lang"), + require("user.keymap.tool"), + require("user.keymap.ui") +) diff --git a/lua/user/keymap/lang.lua b/lua/user/keymap/lang.lua new file mode 100644 index 000000000..a56470754 --- /dev/null +++ b/lua/user/keymap/lang.lua @@ -0,0 +1 @@ +return {} diff --git a/lua/user/keymap/tool.lua b/lua/user/keymap/tool.lua new file mode 100644 index 000000000..a56470754 --- /dev/null +++ b/lua/user/keymap/tool.lua @@ -0,0 +1 @@ +return {} diff --git a/lua/user/keymap/ui.lua b/lua/user/keymap/ui.lua new file mode 100644 index 000000000..a56470754 --- /dev/null +++ b/lua/user/keymap/ui.lua @@ -0,0 +1 @@ +return {} diff --git a/lua/user/options.lua b/lua/user/options.lua new file mode 100644 index 000000000..df03ac57f --- /dev/null +++ b/lua/user/options.lua @@ -0,0 +1,6 @@ +local options = { + -- Example + autoindent = true, +} + +return options diff --git a/lua/user/plugins/.gitkeep b/lua/user/plugins/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/lua/user/settings.lua b/lua/user/settings.lua new file mode 100644 index 000000000..3e11eb9c7 --- /dev/null +++ b/lua/user/settings.lua @@ -0,0 +1,9 @@ +-- Please check `lua/core/settings.lua` to view the full list of configurable settings +local settings = {} + +-- Examples +settings["use_ssh"] = true + +settings["colorscheme"] = "catppuccin" + +return settings diff --git a/tutor/dots.tutor b/tutor/dots.tutor index 3e14150f7..044595ef4 100644 --- a/tutor/dots.tutor +++ b/tutor/dots.tutor @@ -36,14 +36,15 @@ Of course, the resize process can be continous by holding the key. Back to the left window, the status line is showed at the bottom of the window. ------------------------------------------------------------------------------- -|Normal|main|+1-1~3| |~/.config/nvim|utf-8|LF|4%|50:1| +|Normal|main| 1| 󱜙 [lua_ls,null-ls] UTF-8 LF  4|󱃪 ~/.config/nvim|4% 50:1| ------------------------------------------------------------------------------- - | | | | | | | - | | | current work directory -----| | | | - | | | | | | | - | | |------ git status of current file charset -| | | - | |----- current git branch EOL format ---| | - |---- current edit mode cursor position ----| + | | | | | | | | | + | | | LSPs ---| | | | | | + | | | charset ---| | | | | + | | | EOL format ---| | | | + | | |------ git status tab size ---| | | + | |----- git branch work directory ---| | + |---- edit mode cursor position ----| You will see different content under different conditions. It will looks like this if you switch to the right window and move cursor to the second line. @@ -121,15 +122,11 @@ latter to jump previous. Format on save is a very useful feature which is enabled by default. It can ensure the code style is consistent and you don't need to care about it. -You can disable it temprarily by executing -~~~ cmd - :FormatToggle -~~~ -and permanently by set **settings["format_on_save"] = false** in -**lua/core/settings.lua**. +You can disable it temprarily by using shortcut ``{normal} and permanently +by adding **settings["format_on_save"] = false** in **lua/user/settings.lua**. Besides, you can just toggle it for specific language temprarily by executing ~~~ cmd - :FormatterToggle {language_name} + :FormatterToggleFt {language_name} ~~~ # Lesson 1: SUMMARY