diff options
67 files changed, 1611 insertions, 1749 deletions
diff --git a/.config/nvim/config.lua b/.config/nvim/config.lua index c2f5468..d1103df 100644 --- a/.config/nvim/config.lua +++ b/.config/nvim/config.lua @@ -10,7 +10,7 @@ options.keys.normal_mode["<esc><esc>"] = "<cmd>nohlsearch<cr>" -- LSP options.lsp.diagnostics.virtual_text = false -require("extra.json_schemas").setup() +-- require("extra.json_schemas").setup() -- After changing plugin config it is recommended to run :PackerCompile options.builtin.autopairs.active = true @@ -18,7 +18,7 @@ options.builtin.dashboard.active = true options.builtin.terminal.active = true options.builtin.telescope.active = true options.builtin.bufferline.active = true -options.builtin.nvimtree.active = true +-- options.builtin.nvimtree.active = true options.builtin.lualine.active = true options.builtin.lualine.style = "dark" @@ -51,45 +51,13 @@ options.builtin.which_key.mappings.f = { options.builtin.which_key.mappings.v = { "<cmd>vsplit<cr>", "Vertical Split" } options.builtin.which_key.mappings.h = { "<cmd>split<cr>", "Horizontal Split" } -options.builtin.nvimtree.auto_open = 0 +-- options.builtin.nvimtree.auto_open = 0 -- Treesitter options.builtin.treesitter.ensure_installed = "maintained" options.builtin.treesitter.autotag.enable = false options.builtin.treesitter.playground.enable = false - --- Formatters --- python -options.lang.python.formatters = { - { - exe = "black", - args = {}, - }, -} - -options.lang.python.linters = { - { - exe = "flake8", - args = {}, - }, -} - -options.lang.python.lsp.on_attach = nil - --- lua -options.lang.lua.formatters = { - { - exe = "stylua", - }, -} - ---json -options.lang.json.formatters = { - { - exe = "prettier", - args = {}, - }, -} +options.builtin.treesitter.indent.disable = { "python" } options.plugins = { { diff --git a/.config/nvim/ftplugin/c.lua b/.config/nvim/ftplugin/c.lua deleted file mode 100644 index 4fd8004..0000000 --- a/.config/nvim/ftplugin/c.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "c" diff --git a/.config/nvim/ftplugin/dockerfile.lua b/.config/nvim/ftplugin/dockerfile.lua deleted file mode 100644 index 98fa710..0000000 --- a/.config/nvim/ftplugin/dockerfile.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "dockerfile" diff --git a/.config/nvim/ftplugin/go.lua b/.config/nvim/ftplugin/go.lua deleted file mode 100644 index 218b634..0000000 --- a/.config/nvim/ftplugin/go.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "go" diff --git a/.config/nvim/ftplugin/graphql.lua b/.config/nvim/ftplugin/graphql.lua deleted file mode 100644 index 83e8878..0000000 --- a/.config/nvim/ftplugin/graphql.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "graphql" diff --git a/.config/nvim/ftplugin/haskell.lua b/.config/nvim/ftplugin/haskell.lua deleted file mode 100644 index 374bed1..0000000 --- a/.config/nvim/ftplugin/haskell.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "haskell" diff --git a/.config/nvim/ftplugin/html.lua b/.config/nvim/ftplugin/html.lua deleted file mode 100644 index c60394c..0000000 --- a/.config/nvim/ftplugin/html.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "html" diff --git a/.config/nvim/ftplugin/javascript.lua b/.config/nvim/ftplugin/javascript.lua deleted file mode 100644 index 37b95c7..0000000 --- a/.config/nvim/ftplugin/javascript.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "javascript" diff --git a/.config/nvim/ftplugin/javascriptreact.lua b/.config/nvim/ftplugin/javascriptreact.lua deleted file mode 100644 index 9092016..0000000 --- a/.config/nvim/ftplugin/javascriptreact.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "javascriptreact" diff --git a/.config/nvim/ftplugin/json.lua b/.config/nvim/ftplugin/json.lua index 18368cf..9483cd0 100644 --- a/.config/nvim/ftplugin/json.lua +++ b/.config/nvim/ftplugin/json.lua @@ -1 +1,6 @@ -require("lsp").setup "json" +options.lang.json.formatters = { + { + exe = "prettier", + args = {}, + }, +} diff --git a/.config/nvim/ftplugin/kotlin.lua b/.config/nvim/ftplugin/kotlin.lua deleted file mode 100644 index a0e6d5d..0000000 --- a/.config/nvim/ftplugin/kotlin.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "kotlin" diff --git a/.config/nvim/ftplugin/lua.lua b/.config/nvim/ftplugin/lua.lua index 2ed8831..d0408a1 100644 --- a/.config/nvim/ftplugin/lua.lua +++ b/.config/nvim/ftplugin/lua.lua @@ -1 +1,5 @@ -require("lsp").setup "lua" +options.lang.lua.formatters = { + { + exe = "stylua", + }, +} diff --git a/.config/nvim/ftplugin/python.lua b/.config/nvim/ftplugin/python.lua index fbe1beb..81812fc 100644 --- a/.config/nvim/ftplugin/python.lua +++ b/.config/nvim/ftplugin/python.lua @@ -1 +1,13 @@ -require("lsp").setup "python" +options.lang.python.formatters = { + { + exe = "black", + args = {}, + }, +} + +options.lang.python.linters = { + { + exe = "flake8", + args = {}, + }, +} diff --git a/.config/nvim/ftplugin/rust.lua b/.config/nvim/ftplugin/rust.lua deleted file mode 100644 index 3831055..0000000 --- a/.config/nvim/ftplugin/rust.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "rust" diff --git a/.config/nvim/ftplugin/sh.lua b/.config/nvim/ftplugin/sh.lua deleted file mode 100644 index 4f18fbc..0000000 --- a/.config/nvim/ftplugin/sh.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "sh" diff --git a/.config/nvim/ftplugin/sql.lua b/.config/nvim/ftplugin/sql.lua deleted file mode 100644 index b465802..0000000 --- a/.config/nvim/ftplugin/sql.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "sql" diff --git a/.config/nvim/ftplugin/terraform.lua b/.config/nvim/ftplugin/terraform.lua deleted file mode 100644 index 3486663..0000000 --- a/.config/nvim/ftplugin/terraform.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "terraform" diff --git a/.config/nvim/ftplugin/tex.lua b/.config/nvim/ftplugin/tex.lua deleted file mode 100644 index e9a98ec..0000000 --- a/.config/nvim/ftplugin/tex.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "tex" diff --git a/.config/nvim/ftplugin/toml.lua b/.config/nvim/ftplugin/toml.lua deleted file mode 100644 index 701685a..0000000 --- a/.config/nvim/ftplugin/toml.lua +++ /dev/null @@ -1 +0,0 @@ -vim.cmd [[setlocal commentstring=#%s]] diff --git a/.config/nvim/ftplugin/vim.lua b/.config/nvim/ftplugin/vim.lua deleted file mode 100644 index 88c00c1..0000000 --- a/.config/nvim/ftplugin/vim.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "vim" diff --git a/.config/nvim/ftplugin/yaml.lua b/.config/nvim/ftplugin/yaml.lua deleted file mode 100644 index d21f978..0000000 --- a/.config/nvim/ftplugin/yaml.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "yaml" diff --git a/.config/nvim/ftplugin/zsh.lua b/.config/nvim/ftplugin/zsh.lua deleted file mode 100644 index 4f18fbc..0000000 --- a/.config/nvim/ftplugin/zsh.lua +++ /dev/null @@ -1 +0,0 @@ -require("lsp").setup "sh" diff --git a/.config/nvim/init.lua b/.config/nvim/init.lua index 033963e..042e95b 100644 --- a/.config/nvim/init.lua +++ b/.config/nvim/init.lua @@ -1,41 +1,21 @@ -local home_dir = vim.loop.os_homedir() - --- TODO: we need something like this: vim.opt.packpath = vim.opt.rtp -vim.cmd [[let &packpath = &runtimepath]] --- }}} +require("bootstrap"):init() local config = require "config" -config:init() +-- config:init() config:load() local plugins = require "plugins" -local plugin_loader = require("plugin-loader").init() -plugin_loader:load { plugins, options.plugins } +require("plugin-loader"):load { plugins, options.plugins } local Log = require "core.log" -Log:info "Starting nvim" +Log:debug "Starting nvim" vim.g.colors_name = options.colorscheme -- Colorscheme must get called after plugins are loaded or it will break new installs. vim.cmd("colorscheme " .. options.colorscheme) -local utils = require "utils" -utils.toggle_autoformat() local commands = require "core.commands" commands.load(commands.defaults) -require("lsp").config() - -local null_status_ok, null_ls = pcall(require, "null-ls") -if null_status_ok then - null_ls.config {} - require("lspconfig")["null-ls"].setup(options.lsp.null_ls.setup) -end - -local lsp_settings_status_ok, lsp_settings = pcall(require, "nlspsettings") -if lsp_settings_status_ok then - lsp_settings.setup { - config_home = home_dir .. "/.config/nvim/lsp-settings", - } -end - require("keymappings").setup() + +require("lsp").setup() diff --git a/.config/nvim/lua/bootstrap.lua b/.config/nvim/lua/bootstrap.lua new file mode 100644 index 0000000..e8794d6 --- /dev/null +++ b/.config/nvim/lua/bootstrap.lua @@ -0,0 +1,154 @@ +local M = {} + +local in_headless = #vim.api.nvim_list_uis() == 0 + +---Join path segments that were passed as input +---@return string +function _G.join_paths(...) + local uv = vim.loop + local path_sep = "/" + local result = table.concat({ ... }, path_sep) + return result +end + +---Get the full path to `$LUNARVIM_RUNTIME_DIR` +---@return string +function _G.get_runtime_dir() + -- when nvim is used directly + return vim.fn.stdpath "config" +end + +---Get the full path to `$LUNARVIM_CONFIG_DIR` +---@return string +function _G.get_config_dir() + return vim.fn.stdpath "config" +end + +function _G.get_data_dir() + return vim.fn.stdpath "data" +end + +---Get the full path to `$LUNARVIM_CACHE_DIR` +---@return string +function _G.get_cache_dir() + return vim.fn.stdpath "cache" +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.data_dir = get_data_dir() + self.repo_dir = join_paths(self.runtime_dir, "nvim") + + self.pack_dir = join_paths(self.data_dir, "site", "pack") + self.packer_install_dir = join_paths( + self.data_dir, + "site", + "pack", + "packer", + "start", + "packer.nvim" + ) + self.packer_cache_path = join_paths(self.config_dir, "plugin", "packer_compiled.lua") + vim.fn.mkdir(vim.fn.stdpath "cache", "p") + + 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() + M:update_repo() + M:reset_cache() + require("lsp.templates").generate_templates() + if not in_headless then + vim.schedule(function() + require("packer").install() + -- TODO: add a changelog + vim.notify("Update complete", vim.log.levels.INFO) + end) + end +end + +local function git_cmd(subcmd) + local Job = require "plenary.job" + local Log = require "core.log" + local repo_dir = join_paths(get_runtime_dir(), "nvim") + local args = { "-C", repo_dir } + vim.list_extend(args, subcmd) + + local stderr = {} + local stdout, ret = Job + :new({ + command = "git", + args = args, + cwd = repo_dir, + 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 + error "Update failed! Check the log for further information" + end + + ret = git_cmd(sub_commands.diff) + + if ret == 0 then + Log:info "nvim is already up-to-date" + return + end + + ret = git_cmd(sub_commands.merge) + + if ret ~= 0 then + error "Error: unable to guarantee data integrity while updating your branch" + error "Please pull the changes manually instead." + end +end + +---Reset any startup cache files used by Packer and Impatient +---Tip: Useful for clearing any outdated settings +function M:reset_cache() + _G.__luacache.clear_cache() + _G.__luacache.save_cache() + require("plugin-loader"):cache_reset() +end + +return M diff --git a/.config/nvim/lua/config/defaults.lua b/.config/nvim/lua/config/defaults.lua index bcadef3..bb2bcc6 100644 --- a/.config/nvim/lua/config/defaults.lua +++ b/.config/nvim/lua/config/defaults.lua @@ -1,22 +1,19 @@ local home_dir = vim.loop.os_homedir() -CONFIG_PATH = vim.fn.stdpath "config" -DATA_PATH = vim.fn.stdpath "data" -CACHE_PATH = vim.fn.stdpath "cache" -TERMINAL = vim.fn.expand "$TERMINAL" -USER = vim.fn.expand "$USER" -vim.cmd [[ set spellfile=~/.config/nvim/spell/en.utf-8.add ]] +local utils = require "utils" options = { - leader_key = "space", + leader = "space", colorscheme = "dark", line_wrap_cursor_movement = true, transparent_window = false, format_on_save = true, - vsnip_dir = home_dir .. "/.config/snippets", - database = { save_location = "~/.config/nvim_db", auto_execute = 1 }, + vsnip_dir = utils.join_paths(home_dir, ".config", "snippets"), + database = { + save_location = utils.join_paths(home_dir, ".config", "nvim_db"), + auto_execute = 1, + }, keys = {}, - -- TODO: might remove later builtin = {}, log = { @@ -34,1137 +31,10 @@ options = { }, }, }, - - lsp = { - completion = { - item_kind = { - " (Text) ", - " (Method)", - " (Function)", - " (Constructor)", - " (Field)", - " (Variable)", - " (Class)", - " ﰮ (Interface)", - " (Module)", - " (Property)", - " 塞 (Unit)", - " (Value)", - " 練 (Enum)", - " (Keyword)", - " (Snippet)", - " (Color)", - " (File)", - " (Reference)", - " (Folder)", - " (EnumMember)", - " ﲀ (Constant)", - " (Struct)", - " (Event)", - " (Operator)", - " (TypeParameter)", - }, - }, - diagnostics = { - signs = { - active = true, - values = { - { name = "LspDiagnosticsSignError", text = "" }, - { name = "LspDiagnosticsSignWarning", text = "" }, - { name = "LspDiagnosticsSignHint", text = "" }, - { name = "LspDiagnosticsSignInformation", text = "" }, - }, - }, - virtual_text = { - prefix = "", - spacing = 0, - }, - underline = true, - severity_sort = true, - }, - override = {}, - document_highlight = true, - popup_border = "single", - on_attach_callback = nil, - on_init_callback = nil, - null_ls = { - setup = {}, - }, - }, - plugins = { -- use config.lua for this not put here }, autocommands = {}, -} - -local schemas = nil -local status_ok, jsonls_settings = pcall(require, "nlspsettings.jsonls") -if status_ok then - schemas = jsonls_settings.get_default_schemas() -end - --- TODO move all of this into lang specific files, only require when using -options.lang = { - asm = { - formatters = { - -- { - -- exe = "asmfmt", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "", - setup = {}, - }, - }, - beancount = { - formatters = { - -- { - -- exe = "bean_format", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "beancount", - setup = { - cmd = { "beancount-langserver" }, - }, - }, - }, - c = { - formatters = { - -- { - -- exe = "clang_format", - -- args = {}, - -- }, - -- { - -- exe = "uncrustify", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "clangd", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/cpp/clangd/bin/clangd", - "--background-index", - "--header-insertion=never", - "--cross-file-rename", - "--clang-tidy", - "--clang-tidy-checks=-*,llvm-*,clang-analyzer-*", - }, - }, - }, - }, - cpp = { - formatters = { - -- { - -- exe = "clang_format", - -- args = {}, - -- }, - -- { - -- exe = "uncrustify", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "clangd", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/cpp/clangd/bin/clangd", - "--background-index", - "--header-insertion=never", - "--cross-file-rename", - "--clang-tidy", - "--clang-tidy-checks=-*,llvm-*,clang-analyzer-*", - }, - }, - }, - }, - crystal = { - formatters = { - -- { - -- exe = "crystal_format", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "crystalline", - setup = { - cmd = { "crystalline" }, - }, - }, - }, - cs = { - formatters = { - -- { - -- exe = "clang_format ", - -- args = {}, - -- }, - -- { - -- exe = "uncrustify", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "omnisharp", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/csharp/omnisharp/run", - "--languageserver", - "--hostPID", - tostring(vim.fn.getpid()), - }, - }, - }, - }, - cmake = { - formatters = { - -- { - -- exe = "cmake_format", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "cmake", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/cmake/venv/bin/cmake-language-server", - }, - }, - }, - }, - clojure = { - formatters = {}, - linters = {}, - lsp = { - provider = "clojure_lsp", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/clojure/clojure-lsp", - }, - }, - }, - }, - css = { - formatters = { - -- { - -- exe = "prettier", - -- args = {}, - -- }, - -- { - -- exe = "prettierd", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "cssls", - setup = { - cmd = { - "node", - DATA_PATH - .. "/lspinstall/css/vscode-css/css-language-features/server/dist/node/cssServerMain.js", - "--stdio", - }, - }, - }, - }, - less = { - formatters = { - -- { - -- exe = "prettier", - -- args = {}, - -- }, - -- { - -- exe = "prettierd", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "cssls", - setup = { - cmd = { - "node", - DATA_PATH - .. "/lspinstall/css/vscode-css/css-language-features/server/dist/node/cssServerMain.js", - "--stdio", - }, - }, - }, - }, - d = { - formatters = { - -- { - -- exe = "dfmt", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "serve_d", - setup = { - cmd = { "serve-d" }, - }, - }, - }, - dart = { - formatters = { - -- { - -- exe = "dart_format", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "dartls", - setup = { - cmd = { - "dart", - "/usr/lib/dart/bin/snapshots/analysis_server.dart.snapshot", - "--lsp", - }, - }, - }, - }, - dockerfile = { - formatters = {}, - linters = {}, - lsp = { - provider = "dockerls", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/dockerfile/node_modules/.bin/docker-langserver", - "--stdio", - }, - }, - }, - }, - elixir = { - formatters = { - -- { - -- exe = "mix", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "elixirls", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/elixir/elixir-ls/language_server.sh", - }, - }, - }, - }, - elm = { - formatters = { - -- { - -- exe = "elm_format", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "elmls", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/elm/node_modules/.bin/elm-language-server", - }, - -- init_options = { - -- elmAnalyseTrigger = "change", - -- elmFormatPath = DATA_PATH .. "/lspinstall/elm/node_modules/.bin/elm-format", - -- elmPath = DATA_PATH .. "/lspinstall/elm/node_modules/.bin/", - -- elmTestPath = DATA_PATH .. "/lspinstall/elm/node_modules/.bin/elm-test", - -- }, - }, - }, - }, - erlang = { - formatters = { - -- { - -- exe = "erlfmt", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "erlangls", - setup = { - cmd = { - "erlang_ls", - }, - }, - }, - }, - emmet = { active = false }, - fish = { - formatters = { - -- { - -- exe = "fish_indent", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "", - setup = {}, - }, - }, - fortran = { - formatters = {}, - linters = {}, - lsp = { - provider = "fortls", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/fortran/venv/bin/fortls", - }, - }, - }, - }, - go = { - formatters = { - -- { - -- exe = "gofmt", - -- args = {}, - -- }, - -- { - -- exe = "goimports", - -- args = {}, - -- }, - -- { - -- exe = "gofumpt", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "gopls", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/go/gopls", - }, - }, - }, - }, - graphql = { - formatters = {}, - linters = {}, - lsp = { - provider = "graphql", - setup = { - cmd = { - "graphql-lsp", - "server", - "-m", - "stream", - }, - }, - }, - }, - haskell = { - formatters = {}, - linters = {}, - lsp = { - provider = "hls", - setup = { - cmd = { DATA_PATH .. "/lspinstall/haskell/hls" }, - }, - }, - }, - html = { - formatters = { - -- { - -- exe = "prettier", - -- args = {}, - -- }, - -- { - -- exe = "prettierd", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "html", - setup = { - cmd = { - "node", - DATA_PATH - .. "/lspinstall/html/vscode-html/html-language-features/server/dist/node/htmlServerMain.js", - "--stdio", - }, - }, - }, - }, - java = { - formatters = { - -- { - -- exe = "clang_format", - -- args = {}, - -- }, - -- { - -- exe = "uncrustify", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "jdtls", - setup = { - cmd = { DATA_PATH .. "/lspinstall/java/jdtls.sh" }, - }, - }, - }, - json = { - formatters = { - -- { - -- exe = "json_tool", - -- args = {}, - -- }, - -- { - -- exe = "prettier", - -- args = {}, - -- }, - -- { - -- exe = "prettierd", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "jsonls", - setup = { - cmd = { - "node", - DATA_PATH - .. "/lspinstall/json/vscode-json/json-language-features/server/dist/node/jsonServerMain.js", - "--stdio", - }, - settings = { - json = { - schemas = schemas, - -- = { - -- { - -- fileMatch = { "package.json" }, - -- url = "https://json.schemastore.org/package.json", - -- }, - -- }, - }, - }, - commands = { - Format = { - function() - vim.lsp.buf.range_formatting({}, { 0, 0 }, { vim.fn.line "$", 0 }) - end, - }, - }, - }, - }, - }, - julia = { - formatters = {}, - linters = {}, - lsp = { - provider = "julials", - setup = { - { - "julia", - "--startup-file=no", - "--history-file=no", - -- vim.fn.expand "~/.config/nvim/lua/lsp/julia/run.jl", - CONFIG_PATH .. "/utils/julia/run.jl", - }, - }, - }, - }, - kotlin = { - formatters = {}, - linters = {}, - lsp = { - provider = "kotlin_language_server", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/kotlin/server/bin/kotlin-language-server", - }, - root_dir = function(fname) - local util = require "lspconfig/util" - - local root_files = { - "settings.gradle", -- Gradle (multi-project) - "settings.gradle.kts", -- Gradle (multi-project) - "build.xml", -- Ant - "pom.xml", -- Maven - } - - local fallback_root_files = { - "build.gradle", -- Gradle - "build.gradle.kts", -- Gradle - } - return util.root_pattern(unpack(root_files))(fname) - or util.root_pattern(unpack(fallback_root_files))(fname) - end, - }, - }, - }, - lua = { - formatters = { - -- { - -- exe = "stylua", - -- args = {}, - -- }, - -- { - -- exe = "lua_format", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "sumneko_lua", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/lua/sumneko-lua-language-server", - "-E", - DATA_PATH .. "/lspinstall/lua/main.lua", - }, - settings = { - Lua = { - runtime = { - -- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim) - version = "LuaJIT", - -- Setup your lua path - path = vim.split(package.path, ";"), - }, - diagnostics = { - -- Get the language server to recognize the `vim` global - globals = { "vim", "lvim" }, - }, - workspace = { - -- Make the server aware of Neovim runtime files - library = { - [vim.fn.expand "~/.local/share/lunarvim/lvim/lua"] = true, - [vim.fn.expand "$VIMRUNTIME/lua"] = true, - [vim.fn.expand "$VIMRUNTIME/lua/vim/lsp"] = true, - }, - maxPreload = 100000, - preloadFileSize = 1000, - }, - }, - }, - }, - }, - }, - nginx = { - formatters = { - -- { - -- exe = "nginx_beautifier", - -- args = { - -- provider = "", - -- setup = {}, - -- }, - -- }, - }, - linters = {}, - lsp = {}, - }, - perl = { - formatters = { - -- { - -- exe = "perltidy", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "", - setup = {}, - }, - }, - sql = { - formatters = { - -- { - -- exe = "sqlformat", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "sqls", - setup = { - cmd = { "sqls" }, - }, - }, - }, - php = { - formatters = { - -- { - -- exe = "phpcbf", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "intelephense", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/php/node_modules/.bin/intelephense", - "--stdio", - }, - filetypes = { "php", "phtml" }, - settings = { - intelephense = { - environment = { - phpVersion = "7.4", - }, - }, - }, - }, - }, - }, - puppet = { - formatters = {}, - linters = {}, - lsp = { - provider = "puppet", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/puppet/puppet-editor-services/puppet-languageserver", - "--stdio", - }, - }, - }, - }, - javascript = { - formatters = { - -- { - -- exe = "prettier", - -- args = {}, - -- }, - -- { - -- exe = "prettier_d_slim", - -- args = {}, - -- }, - -- { - -- exe = "prettierd", - -- args = {}, - -- }, - }, - -- @usage can be {"eslint"} or {"eslint_d"} - linters = {}, - lsp = { - provider = "tsserver", - setup = { - cmd = { - -- TODO: - DATA_PATH .. "/lspinstall/typescript/node_modules/.bin/typescript-language-server", - "--stdio", - }, - }, - }, - }, - javascriptreact = { - formatters = { - -- { - -- exe = "prettier", - -- args = {}, - -- }, - -- { - -- exe = "prettier_d_slim", - -- args = {}, - -- }, - -- { - -- exe = "prettierd", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "tsserver", - setup = { - cmd = { - -- TODO: - DATA_PATH .. "/lspinstall/typescript/node_modules/.bin/typescript-language-server", - "--stdio", - }, - }, - }, - }, - python = { - formatters = { - -- { - -- exe = "yapf", - -- args = {}, - -- }, - -- { - -- exe = "isort", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "pyright", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/python/node_modules/.bin/pyright-langserver", - "--stdio", - }, - }, - }, - }, - -- R -e 'install.packages("formatR",repos = "http://cran.us.r-project.org")' - -- R -e 'install.packages("readr",repos = "http://cran.us.r-project.org")' - r = { - formatters = { - -- { - -- exe = "format_r", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "r_language_server", - setup = { - cmd = { - "R", - "--slave", - "-e", - "languageserver::run()", - }, - }, - }, - }, - ruby = { - formatters = { - -- { - -- exe = "rufo", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "solargraph", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/ruby/solargraph/solargraph", - "stdio", - }, - filetypes = { "ruby" }, - init_options = { - formatting = true, - }, - root_dir = function(fname) - local util = require("lspconfig").util - return util.root_pattern("Gemfile", ".git")(fname) - end, - settings = { - solargraph = { - diagnostics = true, - }, - }, - }, - }, - }, - rust = { - formatters = { - -- { - -- exe = "rustfmt", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "rust_analyzer", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/rust/rust-analyzer", - }, - }, - }, - }, - scala = { - formatters = { - -- { - -- exe = "scalafmt", - -- args = {}, - -- }, - }, - linters = { "" }, - lsp = { - provider = "metals", - setup = {}, - }, - }, - sh = { - formatters = { - -- { - -- exe = "shfmt", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "bashls", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/bash/node_modules/.bin/bash-language-server", - "start", - }, - }, - }, - }, - svelte = { - formatters = {}, - linters = {}, - lsp = { - provider = "svelte", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/svelte/node_modules/.bin/svelteserver", - "--stdio", - }, - }, - }, - }, - swift = { - formatters = { - -- { - -- exe = "swiftformat", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "sourcekit", - setup = { - cmd = { - "xcrun", - "sourcekit-lsp", - }, - }, - }, - }, - tailwindcss = { - lsp = { - active = false, - provider = "tailwindcss", - setup = { - cmd = { - DATA_PATH - .. "/lspinstall/tailwindcss/node_modules/.bin/tailwindcss-language-server", - "--stdio", - }, - }, - }, - }, - terraform = { - formatters = { - -- { - -- exe = "terraform_fmt", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "terraformls", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/terraform/terraform-ls", - "serve", - }, - }, - }, - }, - tex = { - formatters = {}, - linters = {}, - lsp = { - provider = "texlab", - setup = { - cmd = { DATA_PATH .. "/lspinstall/latex/texlab" }, - }, - }, - }, - typescript = { - formatters = { - -- { - -- exe = "prettier", - -- args = {}, - -- }, - -- { - -- exe = "prettierd", - -- args = {}, - -- }, - -- { - -- exe = "prettier_d_slim", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "tsserver", - setup = { - cmd = { - -- TODO: - DATA_PATH .. "/lspinstall/typescript/node_modules/.bin/typescript-language-server", - "--stdio", - }, - }, - }, - }, - typescriptreact = { - formatters = { - -- { - -- exe = "prettier", - -- args = {}, - -- }, - -- { - -- exe = "prettierd", - -- args = {}, - -- }, - -- { - -- exe = "prettier_d_slim", - -- args = {}, - -- }, - }, - -- @usage can be {"eslint"} or {"eslint_d"} - linters = {}, - lsp = { - provider = "tsserver", - setup = { - cmd = { - -- TODO: - DATA_PATH .. "/lspinstall/typescript/node_modules/.bin/typescript-language-server", - "--stdio", - }, - }, - }, - }, - vim = { - formatters = {}, - linters = {}, - lsp = { - provider = "vimls", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/vim/node_modules/.bin/vim-language-server", - "--stdio", - }, - }, - }, - }, - vue = { - formatters = { - -- { - -- exe = "prettier", - -- args = {}, - -- }, - -- { - -- exe = "prettierd", - -- args = {}, - -- }, - -- { - -- exe = "prettier_d_slim", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "vuels", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/vue/node_modules/.bin/vls", - }, - }, - }, - }, - yaml = { - formatters = { - -- { - -- exe = "prettier", - -- args = {}, - -- }, - -- { - -- exe = "prettierd", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "yamlls", - setup = { - cmd = { - DATA_PATH .. "/lspinstall/yaml/node_modules/.bin/yaml-language-server", - "--stdio", - }, - }, - }, - }, - zig = { - formatters = {}, - linters = {}, - lsp = { - provider = "zls", - setup = { - cmd = { - "zls", - }, - }, - }, - }, - gdscript = { - formatters = {}, - linters = {}, - lsp = { - provider = "gdscript", - setup = { - cmd = { - "nc", - "localhost", - "6008", - }, - }, - }, - }, - ps1 = { - formatters = {}, - linters = {}, - lsp = { - provider = "powershell_es", - setup = { - bundle_path = "", - }, - }, - }, - nix = { - formatters = { - -- { - -- exe = "nixfmt", - -- args = {}, - -- }, - }, - linters = {}, - lsp = { - provider = "rnix", - setup = { - cmd = { "rnix-lsp" }, - filetypes = { "nix" }, - init_options = {}, - settings = {}, - root_dir = function(fname) - local util = require "lspconfig/util" - return util.root_pattern ".git"(fname) or vim.fn.getcwd() - end, - }, - }, - }, + lang = {}, } diff --git a/.config/nvim/lua/config/init.lua b/.config/nvim/lua/config/init.lua index 7d42ad1..f4179ee 100644 --- a/.config/nvim/lua/config/init.lua +++ b/.config/nvim/lua/config/init.lua @@ -1,26 +1,134 @@ -local home_dir = vim.loop.os_homedir() -local M = { - path = string.format("%s/.config/nvim/config.lua", home_dir), -} +local M = {} --- Initialize nvim default configuration -- Define nvim global variable -function M:init() +function M:init(opts) + opts = opts or {} + self.path = opts.path local utils = require "utils" require "config.defaults" + -- Fallback config.lua to config.lua + if not utils.is_file(self.path) then + local config = self.path:gsub("config.lua$", "config.lua") + print(self.path, "not found, falling back to", config) + + self.path = config + end + local builtins = require "core.builtins" builtins.config(self) local settings = require "config.settings" settings.load_options() + + local lsp_config = require "lsp.config" + options.lsp = vim.deepcopy(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 --- 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 diff --git a/.config/nvim/lua/config/settings.lua b/.config/nvim/lua/config/settings.lua index 82d7f48..09f4a8b 100644 --- a/.config/nvim/lua/config/settings.lua +++ b/.config/nvim/lua/config/settings.lua @@ -1,4 +1,5 @@ local M = {} +local utils = require "utils" M.load_options = function() local default_options = { @@ -28,7 +29,7 @@ M.load_options = function() 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 = CACHE_PATH .. "/undo", -- set an undo directory + 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 diff --git a/.config/nvim/lua/core/autocmds.lua b/.config/nvim/lua/core/autocmds.lua index 3432e14..9ee9e90 100644 --- a/.config/nvim/lua/core/autocmds.lua +++ b/.config/nvim/lua/core/autocmds.lua @@ -14,6 +14,11 @@ options.autocommands = { "nnoremap <silent> <buffer> q :q<CR>", }, { + "FileType", + "lsp-installer", + "nnoremap <silent> <buffer> q :q<CR>", + }, + { "TextYankPost", "*", "lua require('vim.highlight').on_yank({higroup = 'Search', timeout = 200})", diff --git a/.config/nvim/lua/core/autopairs.lua b/.config/nvim/lua/core/autopairs.lua index 8ea3094..0c9ec28 100644 --- a/.config/nvim/lua/core/autopairs.lua +++ b/.config/nvim/lua/core/autopairs.lua @@ -7,8 +7,16 @@ function M.config() ---@usage map <CR> on insert mode map_cr = true, ---@usage auto insert after select function or method item - -- NOTE: This should be wrapped into a function so that it is re-evaluated when opening new files - map_complete = vim.bo.filetype ~= "tex", + map_complete = true, + ---@usage automatically select the first item + auto_select = true, + ---@usage use insert confirm behavior instead of replace + insert = false, + ---@usage -- modifies the function or method delimiter by filetypes + map_char = { + all = "(", + tex = "{", + }, ---@usage check treesitter check_ts = true, ts_config = { @@ -52,9 +60,11 @@ M.setup = function() if package.loaded["cmp"] then require("nvim-autopairs.completion.cmp").setup { - map_cr = true, -- map <CR> on insert mode - map_complete = true, -- it will auto insert `(` after select function or method item - auto_select = true, -- automatically select the first item + map_cr = options.builtin.autopairs.map_cr, + map_complete = options.builtin.autopairs.map_complete, + auto_select = options.builtin.autopairs.auto_select, + insert = options.builtin.autopairs.insert, + map_char = options.builtin.autopairs.map_char, } end diff --git a/.config/nvim/lua/core/builtins/init.lua b/.config/nvim/lua/core/builtins/init.lua index dc9b5ff..c3b3618 100644 --- a/.config/nvim/lua/core/builtins/init.lua +++ b/.config/nvim/lua/core/builtins/init.lua @@ -15,7 +15,6 @@ local builtins = { "core.bufferline", "core.autopairs", "core.comment", - "core.lspinstall", "core.lualine", } diff --git a/.config/nvim/lua/core/cmp.lua b/.config/nvim/lua/core/cmp.lua index 50f7058..f9f2d01 100644 --- a/.config/nvim/lua/core/cmp.lua +++ b/.config/nvim/lua/core/cmp.lua @@ -30,10 +30,40 @@ M.config = function() return end options.builtin.cmp = { + confirm_opts = { + behavior = cmp.ConfirmBehavior.Replace, + select = true, + }, 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 = " ", + }, format = function(entry, vim_item) - local icons = require("lsp.kind").icons - vim_item.kind = icons[vim_item.kind] + vim_item.kind = options.builtin.cmp.formatting.kind_icons[vim_item.kind] vim_item.menu = ({ nvim_lsp = "(LSP)", emoji = "(Emoji)", @@ -78,7 +108,7 @@ M.config = function() -- TODO: potentially fix emmet nonsense ["<Tab>"] = cmp.mapping(function() if vim.fn.pumvisible() == 1 then - vim.fn.feedkeys(T "<C-n>", "n") + vim.fn.feedkeys(T "<down>", "n") elseif luasnip.expand_or_jumpable() then vim.fn.feedkeys(T "<Plug>luasnip-expand-or-jump", "") elseif check_backspace() then @@ -94,7 +124,7 @@ M.config = function() }), ["<S-Tab>"] = cmp.mapping(function(fallback) if vim.fn.pumvisible() == 1 then - vim.fn.feedkeys(T "<C-p>", "n") + vim.fn.feedkeys(T "<up>", "n") elseif luasnip.jumpable(-1) then vim.fn.feedkeys(T "<Plug>luasnip-jump-prev", "") else @@ -107,10 +137,15 @@ M.config = function() ["<C-Space>"] = cmp.mapping.complete(), ["<C-e>"] = cmp.mapping.close(), - ["<CR>"] = cmp.mapping.confirm { - behavior = cmp.ConfirmBehavior.Replace, - select = true, - }, + ["<CR>"] = cmp.mapping(function(fallback) + if not require("cmp").confirm(options.builtin.cmp.confirm_opts) then + if luasnip.jumpable() then + vim.fn.feedkeys(T "<Plug>luasnip-jump-next", "") + else + fallback() + end + end + end), }, } end diff --git a/.config/nvim/lua/core/commands.lua b/.config/nvim/lua/core/commands.lua index 403194e..34033d4 100644 --- a/.config/nvim/lua/core/commands.lua +++ b/.config/nvim/lua/core/commands.lua @@ -10,7 +10,7 @@ M.defaults = { endif endfunction ]], - [[command! LvimInfo lua require('core.info').toggle_popup(vim.bo.filetype)]], + [[command! NvimInfo lua require('core.info').toggle_popup(vim.bo.filetype)]], } M.load = function(commands) diff --git a/.config/nvim/lua/core/dap.lua b/.config/nvim/lua/core/dap.lua index 6179ea3..fb56f82 100644 --- a/.config/nvim/lua/core/dap.lua +++ b/.config/nvim/lua/core/dap.lua @@ -10,6 +10,18 @@ M.config = function() linehl = "", numhl = "", }, + breakpoint_rejected = { + text = "", + texthl = "LspDiagnosticsSignHint", + linehl = "", + numhl = "", + }, + stopped = { + text = "", + texthl = "LspDiagnosticsSignInformation", + linehl = "DiagnosticUnderlineInfo", + numhl = "LspDiagnosticsSignInformation", + }, } end @@ -17,6 +29,8 @@ M.setup = function() local dap = require "dap" vim.fn.sign_define("DapBreakpoint", options.builtin.dap.breakpoint) + vim.fn.sign_define("DapBreakpointRejected", options.builtin.dap.breakpoint_rejected) + vim.fn.sign_define("DapStopped", options.builtin.dap.stopped) dap.defaults.fallback.terminal_win_cmd = "50vsplit new" options.builtin.which_key.mappings["d"] = { diff --git a/.config/nvim/lua/core/dashboard.lua b/.config/nvim/lua/core/dashboard.lua index 70e862e..8df581e 100644 --- a/.config/nvim/lua/core/dashboard.lua +++ b/.config/nvim/lua/core/dashboard.lua @@ -1,5 +1,5 @@ local M = {} -local home_dir = vim.loop.os_homedir() +local utils = require "utils" M.config = function(config) options.builtin.dashboard = { @@ -7,7 +7,7 @@ M.config = function(config) on_config_done = nil, search_handler = "telescope", disable_at_vim_enter = 0, - session_directory = home_dir .. "/.cache/options/sessions", + session_directory = utils.join_paths(get_cache_dir(), "sessions"), custom_header = { " ##############..... ############## ", " ##############......############## ", @@ -67,15 +67,21 @@ M.setup = function() vim.g.dashboard_session_directory = options.builtin.dashboard.session_directory - vim.cmd "let packages = len(globpath('~/.local/share/lunarvim/site/pack/packer/start', '*', 0, 1))" - - vim.api.nvim_exec( - [[ - let g:dashboard_custom_footer = ['LunarVim loaded '..packages..' plugins '] -]], - false + local num_plugins_loaded = #vim.fn.globpath( + get_runtime_dir() .. "/site/pack/packer/start", + "*", + 0, + 1 ) + local footer = { + "nvim loaded " .. num_plugins_loaded .. " plugins ", + "", + } + + 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 diff --git a/.config/nvim/lua/core/gitsigns.lua b/.config/nvim/lua/core/gitsigns.lua index d9c9187..97f5314 100644 --- a/.config/nvim/lua/core/gitsigns.lua +++ b/.config/nvim/lua/core/gitsigns.lua @@ -42,7 +42,7 @@ M.config = function() noremap = true, buffer = true, }, - watch_index = { interval = 1000 }, + watch_gitdir = { interval = 1000 }, sign_priority = 6, update_debounce = 200, status_formatter = nil, -- Use default diff --git a/.config/nvim/lua/core/info.lua b/.config/nvim/lua/core/info.lua index 83e3542..bb53644 100644 --- a/.config/nvim/lua/core/info.lua +++ b/.config/nvim/lua/core/info.lua @@ -10,6 +10,7 @@ local M = { } local fmt = string.format +local text = require "interface.text" local function str_list(list) return fmt("[ %s ]", table.concat(list, ", ")) @@ -73,21 +74,32 @@ local function tbl_set_highlight(terms, highlight_group) end end +local function make_client_info(client) + local client_enabled_caps = require("lsp.utils").get_ls_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 lsp_utils = require "lsp.utils" - local client = lsp_utils.get_active_client_by_ft(ft) - local is_client_active = false - local client_enabled_caps = {} - local client_name = "" - local client_id = 0 - local document_formatting = false - if client ~= nil then - is_client_active = not client.is_stopped() - client_enabled_caps = require("lsp").get_ls_capabilities(client.id) - client_name = client.name - client_id = client.id - document_formatting = client.resolved_capabilities.document_formatting - end + local clients = lsp_utils.get_active_client_by_ft(ft) + local client_names = {} local header = { fmt("Detected filetype: %s", ft), @@ -97,23 +109,23 @@ function M.toggle_popup(ft) ), } - local text = require "interface.text" local lsp_info = { "Language Server Protocol (LSP) info", - fmt("* Associated server: %s", client_name), - fmt("* Active: %s (id: %d)", tostring(is_client_active), client_id), - fmt("* Supports formatting: %s", tostring(document_formatting)), + fmt "* Associated server(s):", } - 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_left(enabled_caps, caps_text_len) - enabled_caps[1] = fmt("%s%s", caps_text, enabled_caps[1]:sub(caps_text_len + 1)) - vim.list_extend(lsp_info, enabled_caps) + + for _, client in pairs(clients) do + vim.list_extend(lsp_info, make_client_info(client)) + table.insert(client_names, client.name) end - local null_ls = require "lsp.null-ls" - local registered_providers = null_ls.list_supported_provider_names(ft) + + 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", @@ -124,30 +136,6 @@ function M.toggle_popup(ft) ), } - local null_formatters = require "lsp.null-ls.formatters" - local missing_formatters = null_formatters.list_unsupported_names(ft) - local missing_formatters_status = {} - if not vim.tbl_isempty(missing_formatters) then - missing_formatters_status = { - fmt( - "* Missing formatters: %s", - table.concat(missing_formatters, " , ") .. " " - ), - } - end - - local null_linters = require "lsp.null-ls.linters" - local missing_linters = null_linters.list_unsupported_names(ft) - local missing_linters_status = {} - if not vim.tbl_isempty(missing_linters) then - missing_linters_status = { - fmt( - "* Missing linters: %s", - table.concat(missing_linters, " , ") .. " " - ), - } - end - local content_provider = function(popup) local content = {} @@ -160,8 +148,6 @@ function M.toggle_popup(ft) lsp_info, { "" }, null_ls_info, - missing_formatters_status, - missing_linters_status, { "" }, { "" }, get_formatter_suggestion_msg(ft), @@ -172,21 +158,18 @@ function M.toggle_popup(ft) vim.list_extend(content, section) end - return text.align(popup, content, 0.5) + return text.align_left(popup, content, 0.5) end local function set_syntax_hl() - vim.cmd [[highlight NvimInfoIdentifier gui=bold]] - vim.cmd [[highlight link NvimInfoHeader Type]] - vim.cmd [[let m=matchadd("NvimInfoHeader", "Language Server Protocol (LSP) info")]] - vim.cmd [[let m=matchadd("NvimInfoHeader", "Formatters and linters")]] - vim.cmd('let m=matchadd("NvimInfoIdentifier", " ' .. ft .. '$")') + vim.cmd [[highlight nvimInfoIdentifier gui=bold]] + vim.cmd [[highlight link nvimInfoHeader Type]] + vim.cmd [[let m=matchadd("nvimInfoHeader", "Language Server Protocol (LSP) info")]] + vim.cmd [[let m=matchadd("nvimInfoHeader", "Formatters and linters")]] + vim.cmd('let m=matchadd("nvimInfoIdentifier", " ' .. ft .. '$")') vim.cmd 'let m=matchadd("string", "true")' vim.cmd 'let m=matchadd("error", "false")' - tbl_set_highlight(registered_providers, "NvimInfoIdentifier") - tbl_set_highlight(missing_formatters, "NvimInfoIdentifier") - tbl_set_highlight(missing_linters, "NvimInfoIdentifier") - vim.cmd('let m=matchadd("NvimInfoIdentifier", "' .. client_name .. '")') + tbl_set_highlight(registered_providers, "nvimInfoIdentifier") end local Popup = require("interface.popup"):new { diff --git a/.config/nvim/lua/core/log.lua b/.config/nvim/lua/core/log.lua index bcc68e4..de03521 100644 --- a/.config/nvim/lua/core/log.lua +++ b/.config/nvim/lua/core/log.lua @@ -8,6 +8,7 @@ function Log:add_entry(msg, level) 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 diff --git a/.config/nvim/lua/core/lspinstall.lua b/.config/nvim/lua/core/lspinstall.lua deleted file mode 100644 index 79c7502..0000000 --- a/.config/nvim/lua/core/lspinstall.lua +++ /dev/null @@ -1,19 +0,0 @@ -local M = {} - -M.config = function() - options.builtin.lspinstall = { - active = true, - on_config_done = nil, - } -end - -M.setup = function() - local lspinstall = require "lspinstall" - lspinstall.setup() - - if options.builtin.lspinstall.on_config_done then - options.builtin.lspinstall.on_config_done(lspinstall) - end -end - -return M diff --git a/.config/nvim/lua/core/lualine/components.lua b/.config/nvim/lua/core/lualine/components.lua index 78f1793..9333a17 100644 --- a/.config/nvim/lua/core/lualine/components.lua +++ b/.config/nvim/lua/core/lualine/components.lua @@ -109,14 +109,11 @@ return { local buf_client_names = {} -- add client - local utils = require "lsp.utils" - local active_client = utils.get_active_client_by_ft(buf_ft) for _, client in pairs(buf_clients) do if client.name ~= "null-ls" then table.insert(buf_client_names, client.name) end end - vim.list_extend(buf_client_names, active_client or {}) -- add formatter local formatters = require "lsp.null-ls.formatters" diff --git a/.config/nvim/lua/core/nvimtree.lua b/.config/nvim/lua/core/nvimtree.lua index 1e764c7..ff8db15 100644 --- a/.config/nvim/lua/core/nvimtree.lua +++ b/.config/nvim/lua/core/nvimtree.lua @@ -5,8 +5,23 @@ function M.config() options.builtin.nvimtree = { active = true, on_config_done = nil, - side = "left", - width = 30, + setup = { + auto_open = 0, + auto_close = 1, + tab_open = 0, + update_focused_file = { + enable = 1, + }, + lsp_diagnostics = 1, + view = { + width = 30, + side = "left", + auto_resize = false, + mappings = { + custom_only = false, + }, + }, + }, show_icons = { git = 1, folders = 1, @@ -15,16 +30,11 @@ function M.config() tree_width = 30, }, ignore = { ".git", "node_modules", ".cache" }, - auto_open = 0, - auto_close = 1, quit_on_open = 0, - follow = 1, hide_dotfiles = 1, git_hl = 1, root_folder_modifier = ":t", - tab_open = 0, allow_resize = 1, - lsp_diagnostics = 1, auto_ignore_ft = { "startify", "dashboard" }, icons = { default = "", @@ -52,7 +62,7 @@ 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") + Log:error "Failed to load nvim-tree.config" return end local g = vim.g @@ -63,17 +73,17 @@ function M.setup() -- Implicitly update nvim-tree when project module is active if options.builtin.project.active then - vim.g.nvim_tree_update_cwd = 1 - vim.g.nvim_tree_respect_buf_cwd = 1 - vim.g.nvim_tree_disable_netrw = 0 - vim.g.nvim_tree_hijack_netrw = 0 + options.builtin.nvimtree.respect_buf_cwd = 1 + options.builtin.nvimtree.setup.update_cwd = 1 + options.builtin.nvimtree.setup.disable_netrw = 0 + options.builtin.nvimtree.setup.hijack_netrw = 0 vim.g.netrw_banner = 0 end local tree_cb = nvim_tree_config.nvim_tree_callback - if not g.nvim_tree_bindings then - g.nvim_tree_bindings = { + if not options.builtin.nvimtree.setup.view.mappings.list then + options.builtin.nvimtree.setup.view.mappings.list = { { key = { "l", "<CR>", "o" }, cb = tree_cb "edit" }, { key = "h", cb = tree_cb "close_node" }, { key = "v", cb = tree_cb "vsplit" }, @@ -96,11 +106,18 @@ function M.setup() if options.builtin.nvimtree.on_config_done then options.builtin.nvimtree.on_config_done(nvim_tree_config) end + require("nvim-tree").setup(options.builtin.nvimtree.setup) end function M.on_open() - if package.loaded["bufferline.state"] and options.builtin.nvimtree.side == "left" then - require("bufferline.state").set_offset(options.builtin.nvimtree.width + 1, "") + if + package.loaded["bufferline.state"] + and options.builtin.nvimtree.setup.view.side == "left" + then + require("bufferline.state").set_offset( + options.builtin.nvimtree.setup.view.width + 1, + "" + ) end end diff --git a/.config/nvim/lua/core/project.lua b/.config/nvim/lua/core/project.lua index c7eacde..b2d4f5f 100644 --- a/.config/nvim/lua/core/project.lua +++ b/.config/nvim/lua/core/project.lua @@ -35,7 +35,7 @@ function M.config() ---@type string ---@usage path to store the project history for use in telescope - datapath = CACHE_PATH, + datapath = get_cache_dir(), } end diff --git a/.config/nvim/lua/core/terminal.lua b/.config/nvim/lua/core/terminal.lua index 01b7709..1a7b0bc 100644 --- a/.config/nvim/lua/core/terminal.lua +++ b/.config/nvim/lua/core/terminal.lua @@ -1,5 +1,5 @@ local M = {} -local utils = require "utils" +local Log = require "core.log" M.config = function() options.builtin["terminal"] = { @@ -81,8 +81,11 @@ end M._exec_toggle = function(exec) local binary = M._split(exec)[1] if vim.fn.executable(binary) ~= 1 then - local Log = require "core.log" - Log:error("Unable to run executable " .. binary .. ". Please make sure it is installed properly.") + Log:error( + "Unable to run executable " + .. binary + .. ". Please make sure it is installed properly." + ) return end local Terminal = require("toggleterm.terminal").Terminal @@ -90,29 +93,16 @@ M._exec_toggle = function(exec) exec_term:toggle() end -local function get_log_path(name) - --handle custom paths not managed by Plenary.log - local logger = require "core.log" - local file - if name == "nvim" then - file = CACHE_PATH .. "/log" - else - file = logger:new({ plugin = name }):get_path() - end - if utils.is_file(file) then - return file - end -end - ---Toggles a log viewer according to log.viewer.layout_config ----@param name can be the name of any of the managed logs, e,g. "lunarvim" or the default ones {"nvim", "lsp", "packer.nvim"} -M.toggle_log_view = function(name) - local logfile = get_log_path(name) - if not logfile then - return +---@param logfile string the fullpath to the logfile +M.toggle_log_view = function(logfile) + local log_viewer = options.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", options.builtin.terminal, { - cmd = options.log.viewer.cmd .. " " .. logfile, + cmd = log_viewer, open_mapping = options.log.viewer.layout_config.open_mapping, direction = options.log.viewer.layout_config.direction, -- TODO: this might not be working as expected @@ -122,7 +112,6 @@ M.toggle_log_view = function(name) local Terminal = require("toggleterm.terminal").Terminal local log_view = Terminal:new(term_opts) - -- require("core.log"):debug("term", vim.inspect(term_opts)) log_view:toggle() end diff --git a/.config/nvim/lua/core/which-key.lua b/.config/nvim/lua/core/which-key.lua index d4ef1a2..db67055 100644 --- a/.config/nvim/lua/core/which-key.lua +++ b/.config/nvim/lua/core/which-key.lua @@ -162,8 +162,14 @@ M.config = function() p = { name = "Peek", d = { "<cmd>lua require('lsp.peek').Peek('definition')<cr>", "Definition" }, - t = { "<cmd>lua require('lsp.peek').Peek('typeDefinition')<cr>", "Type Definition" }, - i = { "<cmd>lua require('lsp.peek').Peek('implementation')<cr>", "Implementation" }, + t = { + "<cmd>lua require('lsp.peek').Peek('typeDefinition')<cr>", + "Type Definition", + }, + i = { + "<cmd>lua require('lsp.peek').Peek('implementation')<cr>", + "Implementation", + }, }, q = { "<cmd>lua vim.lsp.diagnostic.set_loclist()<cr>", "Quickfix" }, r = { "<cmd>lua vim.lsp.buf.rename()<cr>", "Rename" }, @@ -179,23 +185,46 @@ M.config = function() "<cmd>edit ~/.config/nvim/config.lua<cr>", "Edit config.lua", }, - k = { "<cmd>lua require('keymappings').print()<cr>", "View LunarVim's default keymappings" }, + k = { + "<cmd>lua require('keymappings').print()<cr>", + "View LunarVim's default keymappings", + }, i = { "<cmd>lua require('core.info').toggle_popup(vim.bo.filetype)<cr>", "Toggle nvim Info", }, l = { name = "+logs", - D = { "<cmd>edit ~/.cache/nvim/lunarvim.log<cr>", "Open the default logfile" }, - n = { "<cmd>lua require('core.terminal').toggle_log_view('lsp')<cr>", "view lsp log" }, - N = { "<cmd>edit ~/.cache/nvim/log<cr>", "Open the Neovim logfile" }, - l = { "<cmd>lua require('core.terminal').toggle_log_view('nvim')<cr>", "view neovim log" }, - L = { "<cmd>edit ~/.cache/nvim/lsp.log<cr>", "Open the LSP logfile" }, + d = { + "<cmd>lua require('core.terminal').toggle_log_view(require('core.log').get_path())<cr>", + "view default log", + }, + D = { + "<cmd>lua vim.fn.execute('edit ' .. require('core.log').get_path())<cr>", + "Open the default logfile", + }, + l = { + "<cmd>lua require('core.terminal').toggle_log_view(vim.lsp.get_log_path())<cr>", + "view lsp log", + }, + L = { + "<cmd>lua vim.fn.execute('edit ' .. vim.lsp.get_log_path())<cr>", + "Open the LSP logfile", + }, + n = { + "<cmd>lua require('core.terminal').toggle_log_view(os.getenv('NVIM_LOG_FILE'))<cr>", + "view neovim log", + }, + N = { "<cmd>edit $NVIM_LOG_FILE<cr>", "Open the Neovim logfile" }, p = { "<cmd>lua require('core.terminal').toggle_log_view('packer.nvim')<cr>", "view packer log", }, - P = { "<cmd>edit ~/.cache/nvim/packer.nvim.log<cr>", "Open the Packer logfile" }, + P = { + "<cmd>exe 'edit '.stdpath('cache').'/packer.nvim.log'<cr>", + "Open the Packer logfile", + }, + r = { "<cmd>lua require('utils').reload_config()<cr>", "Reload configurations" }, }, }, s = { diff --git a/.config/nvim/lua/extra/json_schemas.lua b/.config/nvim/lua/extra/json_schemas.lua index 926de45..d48d932 100644 --- a/.config/nvim/lua/extra/json_schemas.lua +++ b/.config/nvim/lua/extra/json_schemas.lua @@ -1,102 +1,102 @@ --- https://www.schemastore.org/json/ -local M = {} +-- -- https://www.schemastore.org/json/ +-- local M = {} -M.setup = function() - local schemas = { - { - description = "Package JSON file", - fileMatch = { "package.json" }, - url = "https://json.schemastore.org/package.json", - }, - { - description = "TypeScript compiler configuration file", - fileMatch = { "tsconfig.json", "tsconfig.*.json" }, - url = "http://json.schemastore.org/tsconfig", - }, - { - description = "Lerna config", - fileMatch = { "lerna.json" }, - url = "http://json.schemastore.org/lerna", - }, - { - description = "Babel configuration", - fileMatch = { ".babelrc.json", ".babelrc", "babel.config.json" }, - url = "http://json.schemastore.org/lerna", - }, - { - description = "ESLint config", - fileMatch = { ".eslintrc.json", ".eslintrc" }, - url = "http://json.schemastore.org/eslintrc", - }, - { - description = "Bucklescript config", - fileMatch = { "bsconfig.json" }, - url = "https://bucklescript.github.io/bucklescript/docson/build-schema.json", - }, - { - description = "Prettier config", - fileMatch = { ".prettierrc", ".prettierrc.json", "prettier.config.json" }, - url = "http://json.schemastore.org/prettierrc", - }, - { - description = "Vercel Now config", - fileMatch = { "now.json" }, - url = "http://json.schemastore.org/now", - }, - { - description = "Stylelint config", - fileMatch = { ".stylelintrc", ".stylelintrc.json", "stylelint.config.json" }, - url = "http://json.schemastore.org/stylelintrc", - }, - { - name = "Helm Chart.yaml", - description = "The Chart.lock file locks dependencies from Chart.yaml", - fileMatch = { "Chart.lock" }, - url = "https://json.schemastore.org/chart-lock.json", - }, - { - name = "CircleCI config.yml", - description = "Schema for CircleCI 2.0 config files", - fileMatch = { ".circleci/config.yml" }, - url = "https://json.schemastore.org/circleciconfig.json", - }, - { - name = "yamllint", - description = "yamllint uses a set of rules to check source files for problems", - fileMatch = { "**/.yamllint", "**/.yamllint.yaml", "**/.yamllint.yml" }, - url = "https://json.schemastore.org/yamllint.json", - }, - { - name = "Hadolint", - description = "A smarter Dockerfile linter that helps you build best practice Docker images.", - fileMatch = { ".hadolint.yaml", "hadolint.yaml", ".hadolint.yml", "hadolint.yml" }, - url = "https://raw.githubusercontent.com/hadolint/hadolint/master/contrib/hadolint.json", - }, - { - name = "kustomization.yaml", - description = "Kubernetes native configuration management", - fileMatch = { "kustomization.yaml", "kustomization.yml" }, - url = "https://json.schemastore.org/kustomization.json", - }, - } +-- M.setup = function() +-- local schemas = { +-- { +-- description = "Package JSON file", +-- fileMatch = { "package.json" }, +-- url = "https://json.schemastore.org/package.json", +-- }, +-- { +-- description = "TypeScript compiler configuration file", +-- fileMatch = { "tsconfig.json", "tsconfig.*.json" }, +-- url = "http://json.schemastore.org/tsconfig", +-- }, +-- { +-- description = "Lerna config", +-- fileMatch = { "lerna.json" }, +-- url = "http://json.schemastore.org/lerna", +-- }, +-- { +-- description = "Babel configuration", +-- fileMatch = { ".babelrc.json", ".babelrc", "babel.config.json" }, +-- url = "http://json.schemastore.org/lerna", +-- }, +-- { +-- description = "ESLint config", +-- fileMatch = { ".eslintrc.json", ".eslintrc" }, +-- url = "http://json.schemastore.org/eslintrc", +-- }, +-- { +-- description = "Bucklescript config", +-- fileMatch = { "bsconfig.json" }, +-- url = "https://bucklescript.github.io/bucklescript/docson/build-schema.json", +-- }, +-- { +-- description = "Prettier config", +-- fileMatch = { ".prettierrc", ".prettierrc.json", "prettier.config.json" }, +-- url = "http://json.schemastore.org/prettierrc", +-- }, +-- { +-- description = "Vercel Now config", +-- fileMatch = { "now.json" }, +-- url = "http://json.schemastore.org/now", +-- }, +-- { +-- description = "Stylelint config", +-- fileMatch = { ".stylelintrc", ".stylelintrc.json", "stylelint.config.json" }, +-- url = "http://json.schemastore.org/stylelintrc", +-- }, +-- { +-- name = "Helm Chart.yaml", +-- description = "The Chart.lock file locks dependencies from Chart.yaml", +-- fileMatch = { "Chart.lock" }, +-- url = "https://json.schemastore.org/chart-lock.json", +-- }, +-- { +-- name = "CircleCI config.yml", +-- description = "Schema for CircleCI 2.0 config files", +-- fileMatch = { ".circleci/config.yml" }, +-- url = "https://json.schemastore.org/circleciconfig.json", +-- }, +-- { +-- name = "yamllint", +-- description = "yamllint uses a set of rules to check source files for problems", +-- fileMatch = { "**/.yamllint", "**/.yamllint.yaml", "**/.yamllint.yml" }, +-- url = "https://json.schemastore.org/yamllint.json", +-- }, +-- { +-- name = "Hadolint", +-- description = "A smarter Dockerfile linter that helps you build best practice Docker images.", +-- fileMatch = { ".hadolint.yaml", "hadolint.yaml", ".hadolint.yml", "hadolint.yml" }, +-- url = "https://raw.githubusercontent.com/hadolint/hadolint/master/contrib/hadolint.json", +-- }, +-- { +-- name = "kustomization.yaml", +-- description = "Kubernetes native configuration management", +-- fileMatch = { "kustomization.yaml", "kustomization.yml" }, +-- url = "https://json.schemastore.org/kustomization.json", +-- }, +-- } - local function extend(tab1, tab2) - for _, value in ipairs(tab2) do - table.insert(tab1, value) - end - return tab1 - end +-- local function extend(tab1, tab2) +-- for _, value in ipairs(tab2) do +-- table.insert(tab1, value) +-- end +-- return tab1 +-- end - local extended_schemas = extend( - schemas, - require("nlspsettings.jsonls").get_default_schemas() - ) +-- local extended_schemas = extend( +-- schemas, +-- require("nlspsettings.jsonls").get_default_schemas() +-- ) - options.lang.json.lsp.setup.settings = { - json = { - schemas = extended_schemas, - }, - } -end +-- options.lang.json.lsp.setup.settings = { +-- json = { +-- schemas = extended_schemas, +-- }, +-- } +-- end -return M +-- return M diff --git a/.config/nvim/lua/impatient.lua b/.config/nvim/lua/impatient.lua index 7d924d1..e428c7e 100644 --- a/.config/nvim/lua/impatient.lua +++ b/.config/nvim/lua/impatient.lua @@ -2,13 +2,12 @@ local vim = vim local uv = vim.loop -local impatient_start = uv.hrtime() +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 home_dir = uv.os_homedir() local impatient_dur @@ -16,7 +15,7 @@ local M = { cache = {}, profile = nil, dirty = false, - path = home_dir .. "/.local/share/nvim/cache", + path = nil, log = {}, } @@ -26,13 +25,17 @@ _G.__luacache = M local cachepack = {} -- using double for packing/unpacking numbers has no conversion overhead -local c_double = ffi.typeof "double[1]" -local sizeof_c_double = ffi.sizeof "double" +-- 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_double(num), sizeof_c_double) + buf[#buf + 1] = ffi.string(c_number_t(num), c_sizeof_number_t) end function out_buf.write_string(buf, str) @@ -50,8 +53,8 @@ function in_buf.read_number(buf) if buf.size < buf.pos then error "buffer access violation" end - local res = ffi.cast("double*", buf.ptr + buf.pos)[0] - buf.pos = buf.pos + sizeof_c_double + local res = ffi.cast("number_t*", buf.ptr + buf.pos)[0] + buf.pos = buf.pos + c_sizeof_number_t return res end @@ -270,7 +273,17 @@ function M.clear_cache() os.remove(M.path) end -local function setup() +impatient_dur = uv.hrtime() - impatient_load_start + +function M.setup(opts) + opts = opts or {} + M.path = opts.path or vim.fn.stdpath "cache" .. "/nvim_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) @@ -339,10 +352,8 @@ local function setup() command! LuaCacheClear lua _G.__luacache.clear_cache() command! LuaCacheLog lua _G.__luacache.print_log() ]] -end -setup() - -impatient_dur = uv.hrtime() - impatient_start + impatient_dur = impatient_dur + (uv.hrtime() - impatient_setup_start) +end return M diff --git a/.config/nvim/lua/impatient/cachepack.lua b/.config/nvim/lua/impatient/cachepack.lua deleted file mode 100644 index e69de29..0000000 --- a/.config/nvim/lua/impatient/cachepack.lua +++ /dev/null diff --git a/.config/nvim/lua/interface/text.lua b/.config/nvim/lua/interface/text.lua index f68cc49..c17d403 100644 --- a/.config/nvim/lua/interface/text.lua +++ b/.config/nvim/lua/interface/text.lua @@ -17,16 +17,35 @@ end -- @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(container, lines, alignment) +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_left(lines, indent_amount) + 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_left(lines, amount) +function M.shift_right(lines, amount) local output = {} local padding = string.rep(" ", amount) diff --git a/.config/nvim/lua/lsp/config.lua b/.config/nvim/lua/lsp/config.lua new file mode 100644 index 0000000..b748b3c --- /dev/null +++ b/.config/nvim/lua/lsp/config.lua @@ -0,0 +1,27 @@ +return { + templates_dir = join_paths(get_data_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, + popup_border = "single", + on_attach_callback = nil, + on_init_callback = nil, + automatic_servers_installation = true, + null_ls = { + setup = {}, + }, +} diff --git a/.config/nvim/lua/lsp/handlers.lua b/.config/nvim/lua/lsp/handlers.lua index 04b8477..6801045 100644 --- a/.config/nvim/lua/lsp/handlers.lua +++ b/.config/nvim/lua/lsp/handlers.lua @@ -19,11 +19,44 @@ function M.setup() end local diagnostics = result.diagnostics - vim.lsp.diagnostic.save(diagnostics, bufnr, ctx.client_id) - if not vim.api.nvim_buf_is_loaded(bufnr) then - return + 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(options.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 - vim.lsp.diagnostic.display(diagnostics, bufnr, ctx.client_id, config) end else vim.lsp.handlers["textDocument/publishDiagnostics"] = @@ -55,26 +88,53 @@ function M.setup() ) 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 diags = vim.deepcopy(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" } - local diagnostic_severities = { - "Error", - "Warning", - "Information", - "Hint", - } 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( @@ -82,34 +142,35 @@ function M.show_line_diagnostics() string.find(diagnostic.source, "([%w-_]+)$") ) end - diags[i].message = string.format("%s: %s", source, diagnostic.message) + diag_message = string.format("%d. %s: %s", i, source, diag_message) else - diags[i].message = string.format("%s", diagnostic.message) + diag_message = string.format("%d. %s", i, diag_message) end - if diagnostic.code then - diags[i].message = string.format("%s [%s]", diags[i].message, diagnostic.code) + diag_message = string.format("%s [%s]", diag_message, diagnostic.code) end - if diags[i].message:len() > width then - width = string.len(diags[i].message) + 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(diags) do - local message = diag.message:gsub("[\n\r]", " ") - vim.api.nvim_buf_set_lines(bufnr, i - 1, i - 1, 0, { message }) + 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, - "LspDiagnosticsFloating" .. diagnostic_severities[diag.severity], + severity_highlight[diag.severity], i - 1, 0, diag.message:len() diff --git a/.config/nvim/lua/lsp/init.lua b/.config/nvim/lua/lsp/init.lua index f0f7b45..8eebe0a 100644 --- a/.config/nvim/lua/lsp/init.lua +++ b/.config/nvim/lua/lsp/init.lua @@ -1,15 +1,6 @@ local M = {} local Log = require "core.log" - -function M.config() - vim.lsp.protocol.CompletionItemKind = options.lsp.completion.item_kind - - for _, sign in ipairs(options.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() -end +local utils = require "utils" local function lsp_highlight_document(client) if options.lsp.document_highlight == false then @@ -19,9 +10,6 @@ local function lsp_highlight_document(client) if client.resolved_capabilities.document_highlight then vim.api.nvim_exec( [[ - hi LspReferenceRead cterm=bold ctermbg=red guibg=#353d46 - hi LspReferenceText cterm=bold ctermbg=red guibg=#353d46 - hi LspReferenceWrite cterm=bold ctermbg=red guibg=#353d46 augroup lsp_document_highlight autocmd! * <buffer> autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight() @@ -65,35 +53,31 @@ function M.common_capabilities() "additionalTextEdits", }, } - return capabilities -end -function M.get_ls_capabilities(client_id) - local client - 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 + local status_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") + if status_ok then + capabilities = cmp_nvim_lsp.update_capabilities(capabilities) end - if not client_id then - error "Unable to determine client_id" - end - - client = vim.lsp.get_client_by_id(tonumber(client_id)) - local enabled_caps = {} + return capabilities +end - for k, v in pairs(client.resolved_capabilities) do - if v == true then - table.insert(enabled_caps, k) +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 not vim.tbl_isempty(lvim.lang[filetype].formatters) 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 + return end end - - return enabled_caps end function M.common_on_init(client, bufnr) @@ -102,55 +86,59 @@ function M.common_on_init(client, bufnr) Log:debug "Called lsp.on_init_callback" return end - - local formatters = options.lang[vim.bo.filetype].formatters - if not vim.tbl_isempty(formatters) and formatters[1]["exe"] ~= nil and formatters[1].exe ~= "" then - client.resolved_capabilities.document_formatting = false - Log:debug( - string.format("Overriding language server [%s] with format provider [%s]", client.name, formatters[1].exe) - ) - end + select_default_formater(client) end function M.common_on_attach(client, bufnr) if options.lsp.on_attach_callback then options.lsp.on_attach_callback(client, bufnr) - Log:debug "Called lsp.on_init_callback" + Log:debug "Called lsp.on_attach_callback" end lsp_highlight_document(client) add_lsp_buffer_keybindings(bufnr) - require("lsp.null-ls").setup(vim.bo.filetype) end -function M.setup(lang) - local lsp_utils = require "lsp.utils" - local lsp = options.lang[lang].lsp - if (lsp.active ~= nil and not lsp.active) or lsp_utils.is_client_active(lsp.provider) then +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 - local overrides = options.lsp.override - if type(overrides) == "table" then - if vim.tbl_contains(overrides, lang) then - return - end + for _, sign in ipairs(options.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(options.lsp.templates_dir) then + require("lsp.templates").generate_templates() end - if lsp.provider ~= nil and lsp.provider ~= "" then - local lspconfig = require "lspconfig" + bootstrap_nlsp { config_home = utils.join_paths(get_config_dir(), "lsp-settings") } - if not lsp.setup.on_attach then - lsp.setup.on_attach = M.common_on_attach - end - if not lsp.setup.on_init then - lsp.setup.on_init = M.common_on_init - end - if not lsp.setup.capabilities then - lsp.setup.capabilities = M.common_capabilities() - end + require("lsp.null-ls").setup() - lspconfig[lsp.provider].setup(lsp.setup) - end + require("utils").toggle_autoformat() end return M diff --git a/.config/nvim/lua/lsp/kind.lua b/.config/nvim/lua/lsp/kind.lua deleted file mode 100644 index b78fd31..0000000 --- a/.config/nvim/lua/lsp/kind.lua +++ /dev/null @@ -1,31 +0,0 @@ -local M = {} - -M.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 = " ", -} - -return M diff --git a/.config/nvim/lua/lsp/manager.lua b/.config/nvim/lua/lsp/manager.lua new file mode 100644 index 0000000..49771b2 --- /dev/null +++ b/.config/nvim/lua/lsp/manager.lua @@ -0,0 +1,92 @@ +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 options.lang[entry] then + options.lang[entry] = { + formatters = {}, + linters = {}, + lsp = {}, + } + end + end +end + +local function is_overridden(server) + local overrides = options.lsp.override + if type(overrides) == "table" then + if vim.tbl_contains(overrides, server) then + return true + end + end +end + +function M.setup_server(server_name) + vim.validate { + name = { server_name, "string" }, + } + + if lsp_utils.is_client_active(server_name) or is_overridden(server_name) then + return + end + + local lsp_installer_servers = require "nvim-lsp-installer.servers" + local server_available, requested_server = lsp_installer_servers.get_server( + server_name + ) + if server_available then + if not requested_server:is_installed() then + Log:debug(string.format("[%s] is not installed", server_name)) + if options.lsp.automatic_servers_installation then + Log:debug(string.format("Installing [%s]", server_name)) + requested_server:install() + else + return + end + end + end + + local default_config = { + on_attach = require("lsp").common_on_attach, + on_init = require("lsp").common_on_init, + capabilities = require("lsp").common_capabilities(), + } + + local status_ok, custom_config = pcall( + require, + "lsp/providers/" .. requested_server.name + ) + if status_ok then + local new_config = vim.tbl_deep_extend("force", default_config, custom_config) + Log:debug( + "Using custom configuration for requested server: " .. requested_server.name + ) + requested_server:setup(new_config) + else + Log:debug( + "Using the default configuration for requested server: " .. requested_server.name + ) + requested_server:setup(default_config) + end +end + +function M.setup(servers) + local status_ok, _ = pcall(require, "nvim-lsp-installer") + if not status_ok then + return + end + + --- allow using a single value + if type(servers) == "string" then + servers = { servers } + end + + for _, server in ipairs(servers) do + M.setup_server(server) + end +end + +return M diff --git a/.config/nvim/lua/lsp/null-ls/formatters.lua b/.config/nvim/lua/lsp/null-ls/formatters.lua index 651d6f1..0d3505f 100644 --- a/.config/nvim/lua/lsp/null-ls/formatters.lua +++ b/.config/nvim/lua/lsp/null-ls/formatters.lua @@ -1,29 +1,14 @@ local M = {} -local formatters_by_ft = {} local null_ls = require "null-ls" local services = require "lsp.null-ls.services" -local Log = require("core.log") - -local function list_names(formatters, option) - option = option or {} - local filter = option.filter or "supported" - - return vim.tbl_keys(formatters[filter]) -end +local Log = require "core.log" function M.list_supported_names(filetype) - if not formatters_by_ft[filetype] then - return {} - end - return list_names(formatters_by_ft[filetype], { filter = "supported" }) -end - -function M.list_unsupported_names(filetype) - if not formatters_by_ft[filetype] then - return {} - end - return list_names(formatters_by_ft[filetype], { filter = "unsupported" }) + 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) @@ -45,15 +30,15 @@ function M.list_configured(formatter_configs) local formatter = null_ls.builtins.formatting[fmt_config.exe] if not formatter then - Log:error("Not a valid formatter:" .. fmt_config.exe) + 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) + Log:warn("Not found: " .. formatter._opts.command) errors[fmt_config.exe] = {} -- Add data here when necessary else - Log:debug("Using formatter:" .. formatter_cmd) + Log:debug("Using formatter: " .. formatter_cmd) formatters[fmt_config.exe] = formatter.with { command = formatter_cmd, extra_args = fmt_config.args, @@ -65,12 +50,13 @@ function M.list_configured(formatter_configs) return { supported = formatters, unsupported = errors } end -function M.setup(filetype, option) - if not options.lang[filetype] or (formatters_by_ft[filetype] and not option.force_reload) then +function M.setup(formatter_configs, filetype) + if vim.tbl_isempty(formatter_configs) then return end - formatters_by_ft[filetype] = M.list_configured(options.lang[filetype].formatters) + local formatters_by_ft = {} + formatters_by_ft[filetype] = M.list_configured(formatter_configs) null_ls.register { sources = formatters_by_ft[filetype].supported } end diff --git a/.config/nvim/lua/lsp/null-ls/init.lua b/.config/nvim/lua/lsp/null-ls/init.lua index d12b40a..571fb6b 100644 --- a/.config/nvim/lua/lsp/null-ls/init.lua +++ b/.config/nvim/lua/lsp/null-ls/init.lua @@ -1,44 +1,26 @@ local M = {} -function M.list_supported_provider_names(filetype) - local names = {} - - local formatters = require "lsp.null-ls.formatters" - local linters = require "lsp.null-ls.linters" - - vim.list_extend(names, formatters.list_supported_names(filetype)) - vim.list_extend(names, linters.list_supported_names(filetype)) - - return names -end - -function M.list_unsupported_provider_names(filetype) - local names = {} - - local formatters = require "lsp.null-ls.formatters" - local linters = require "lsp.null-ls.linters" - - vim.list_extend(names, formatters.list_unsupported_names(filetype)) - vim.list_extend(names, linters.list_unsupported_names(filetype)) - - return names -end - --- TODO: for linters and formatters with spaces and '-' replace with '_' -function M.setup(filetype, option) - option = option or {} - - local ok, _ = pcall(require, "null-ls") - if not ok then - require("core.log"):error "Missing null-ls dependency" +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 - local formatters = require "lsp.null-ls.formatters" - local linters = require "lsp.null-ls.linters" - - formatters.setup(filetype, option) - linters.setup(filetype, option) + null_ls.config() + require("lspconfig")["null-ls"].setup(options.lsp.null_ls.setup) + for _, filetype in pairs(options.lang) do + if filetype.formatters then + formatters.setup(filetype.formatters, filetype) + end + if filetype.linters then + linters.setup(filetype.linters, filetype) + end + end end return M diff --git a/.config/nvim/lua/lsp/null-ls/linters.lua b/.config/nvim/lua/lsp/null-ls/linters.lua index 0f6cbc1..e9e92e9 100644 --- a/.config/nvim/lua/lsp/null-ls/linters.lua +++ b/.config/nvim/lua/lsp/null-ls/linters.lua @@ -1,29 +1,14 @@ local M = {} -local linters_by_ft = {} local null_ls = require "null-ls" local services = require "lsp.null-ls.services" -local Log = require("core.log") - -local function list_names(linters, option) - option = option or {} - local filter = option.filter or "supported" - - return vim.tbl_keys(linters[filter]) -end +local Log = require "core.log" function M.list_supported_names(filetype) - if not linters_by_ft[filetype] then - return {} - end - return list_names(linters_by_ft[filetype], { filter = "supported" }) -end - -function M.list_unsupported_names(filetype) - if not linters_by_ft[filetype] then - return {} - end - return list_names(linters_by_ft[filetype], { filter = "unsupported" }) + 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) @@ -65,12 +50,13 @@ function M.list_configured(linter_configs) return { supported = linters, unsupported = errors } end -function M.setup(filetype, option) - if not options.lang[filetype] or (linters_by_ft[filetype] and not option.force_reload) then +function M.setup(linter_configs, filetype) + if vim.tbl_isempty(linter_configs) then return end - linters_by_ft[filetype] = M.list_configured(options.lang[filetype].linters) + local linters_by_ft = {} + linters_by_ft[filetype] = M.list_configured(linter_configs) null_ls.register { sources = linters_by_ft[filetype].supported } end diff --git a/.config/nvim/lua/lsp/null-ls/services.lua b/.config/nvim/lua/lsp/null-ls/services.lua index a1e3a06..c62fc70 100644 --- a/.config/nvim/lua/lsp/null-ls/services.lua +++ b/.config/nvim/lua/lsp/null-ls/services.lua @@ -28,6 +28,7 @@ local local_providers = { 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) @@ -44,4 +45,19 @@ function M.find_command(command) 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/.config/nvim/lua/lsp/peek.lua b/.config/nvim/lua/lsp/peek.lua index dbc6741..151c967 100644 --- a/.config/nvim/lua/lsp/peek.lua +++ b/.config/nvim/lua/lsp/peek.lua @@ -12,7 +12,8 @@ local function create_floating_file(location, opts) -- Set some defaults opts = opts or {} - local close_events = opts.close_events or { "CursorMoved", "CursorMovedI", "BufHidden", "InsertCharPre" } + local close_events = opts.close_events + or { "CursorMoved", "CursorMovedI", "BufHidden", "InsertCharPre" } -- location may be LocationLink or Location local uri = location.targetUri or location.uri @@ -29,7 +30,10 @@ local function create_floating_file(location, opts) 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) + 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) @@ -47,16 +51,17 @@ local function create_floating_file(location, opts) -- Set some autocmds to close the window vim.api.nvim_command( - "autocmd QuitPre <buffer> ++nested ++once lua pcall(vim.api.nvim_win_close, " .. winnr .. ", true)" + "autocmd QuitPre <buffer> ++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(_, method, result) +local function preview_location_callback(result) if result == nil or vim.tbl_isempty(result) then - print("peek: No location found: " .. method) return nil end @@ -74,6 +79,14 @@ local function preview_location_callback(_, method, result) 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 "%:." @@ -129,10 +142,22 @@ function M.Peek(what) else -- Make a new request and then create the new window in the callback local params = vim.lsp.util.make_position_params() - local success, _ = pcall(vim.lsp.buf_request, 0, "textDocument/" .. what, params, preview_location_callback) + 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.' + 'peek: Error calling LSP method "textDocument/' + .. what + .. '". The current language lsp might not support it.' ) end end diff --git a/.config/nvim/lua/lsp/providers/jsonls.lua b/.config/nvim/lua/lsp/providers/jsonls.lua new file mode 100644 index 0000000..70ad7e1 --- /dev/null +++ b/.config/nvim/lua/lsp/providers/jsonls.lua @@ -0,0 +1,196 @@ + +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, + }, + }, + commands = { + Format = { + function() + vim.lsp.buf.range_formatting({}, { 0, 0 }, { vim.fn.line "$", 0 }) + end, + }, + }, +} + +return opts diff --git a/.config/nvim/lua/lsp/providers/sumneko_lua.lua b/.config/nvim/lua/lsp/providers/sumneko_lua.lua new file mode 100644 index 0000000..4fee1fd --- /dev/null +++ b/.config/nvim/lua/lsp/providers/sumneko_lua.lua @@ -0,0 +1,19 @@ +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/.config/nvim/lua/lsp/providers/vuels.lua b/.config/nvim/lua/lsp/providers/vuels.lua new file mode 100644 index 0000000..0d93c61 --- /dev/null +++ b/.config/nvim/lua/lsp/providers/vuels.lua @@ -0,0 +1,28 @@ +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/.config/nvim/lua/lsp/providers/yamlls.lua b/.config/nvim/lua/lsp/providers/yamlls.lua new file mode 100644 index 0000000..156a35b --- /dev/null +++ b/.config/nvim/lua/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/.config/nvim/lua/lsp/templates.lua b/.config/nvim/lua/lsp/templates.lua new file mode 100644 index 0000000..004187e --- /dev/null +++ b/.config/nvim/lua/lsp/templates.lua @@ -0,0 +1,99 @@ +local M = {} + +local Log = require "core.log" +local utils = require "utils" +local get_supported_filetypes = require("lsp.utils").get_supported_filetypes + +local ftplugin_dir = options.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" or server_name == "tailwindcss" 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(options.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/.config/nvim/lua/lsp/utils.lua b/.config/nvim/lua/lsp/utils.lua index e024a0c..e0046db 100644 --- a/.config/nvim/lua/lsp/utils.lua +++ b/.config/nvim/lua/lsp/utils.lua @@ -10,19 +10,65 @@ function M.is_client_active(name) return false end --- FIXME: this should return a list instead -function M.get_active_client_by_ft(filetype) - if not options.lang[filetype] or not options.lang[filetype].lsp then - return nil - end +function M.disable_formatting_capability(client) + -- FIXME: figure out a reasonable way to do this + client.resolved_capabilities.document_formatting = false + require("core.log"):debug( + string.format( + "Turning off formatting capability for language server [%s] ", + client.name + ) + ) +end +function M.get_active_client_by_ft(filetype) + local matches = {} local clients = vim.lsp.get_active_clients() for _, client in pairs(clients) do - if client.name == options.lang[filetype].lsp.provider then - return client + 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_ls_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 - return nil end return M diff --git a/.config/nvim/lua/plugin-loader.lua b/.config/nvim/lua/plugin-loader.lua index fed4995..f2c1dad 100644 --- a/.config/nvim/lua/plugin-loader.lua +++ b/.config/nvim/lua/plugin-loader.lua @@ -1,11 +1,23 @@ local plugin_loader = {} -function plugin_loader:init() - local install_path = "~/.local/share/nvim/site/pack/packer/start/packer.nvim" +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, } @@ -17,15 +29,13 @@ function plugin_loader:init() return end - local util = require "packer.util" - packer.init { - package_root = util.join_paths "~/.local/share/nvim/site/pack/", - compile_path = util.join_paths("~/.config/nvim", "plugin", "packer_compiled.lua"), + package_root = package_root, + compile_path = compile_path, git = { clone_timeout = 300 }, display = { open_fn = function() - return util.float { border = "rounded" } + return require("packer.util").float { border = "rounded" } end, }, } @@ -34,6 +44,20 @@ function plugin_loader:init() 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 @@ -44,8 +68,4 @@ function plugin_loader:load(configurations) end) end -return { - init = function() - return plugin_loader:init() - end, -} +return plugin_loader diff --git a/.config/nvim/lua/plugins.lua b/.config/nvim/lua/plugins.lua index 20bcb4c..99a9cfa 100644 --- a/.config/nvim/lua/plugins.lua +++ b/.config/nvim/lua/plugins.lua @@ -6,17 +6,11 @@ return { { "jose-elias-alvarez/null-ls.nvim" }, { "antoinemadec/FixCursorHold.nvim" }, -- Needed while issue https://github.com/neovim/neovim/issues/12587 is still open { - "kabouzeid/nvim-lspinstall", - event = "VimEnter", - config = function() - local lspinstall = require "core.lspinstall" - lspinstall.setup() - end, + "williamboman/nvim-lsp-installer", }, { "nvim-lua/popup.nvim" }, { "nvim-lua/plenary.nvim" }, - -- Telescope { "nvim-telescope/telescope.nvim", @@ -25,7 +19,7 @@ return { end, disable = not options.builtin.telescope.active, }, - -- Completion & Snippets + -- Install nvim-cmp, and buffer source as a dependency { "hrsh7th/nvim-cmp", config = function() @@ -39,6 +33,12 @@ return { "hrsh7th/cmp-path", "hrsh7th/cmp-nvim-lua", }, + run = function() + -- cmp's config requires cmp to be installed to run the first time + if not options.builtin.cmp then + require("core.cmp").config() + end + end, }, { "rafamadriz/friendly-snippets", @@ -78,6 +78,7 @@ return { end, disable = not options.builtin.nvimtree.active, }, + { "lewis6991/gitsigns.nvim", diff --git a/.config/nvim/lua/utils/init.lua b/.config/nvim/lua/utils/init.lua index 1695d19..e86b798 100644 --- a/.config/nvim/lua/utils/init.lua +++ b/.config/nvim/lua/utils/init.lua @@ -90,16 +90,18 @@ function utils.reload_config() config:load() require("keymappings").setup() -- this should be done before loading the plugins - vim.cmd "source ~/.config/nvim/lua/plugins.lua" + vim.cmd( + "source " .. utils.join_paths(get_runtime_dir(), "lua", "plugins.lua") + ) local plugins = require "plugins" - local plugin_loader = require("plugin-loader").init() utils.toggle_autoformat() + local plugin_loader = require "plugin-loader" + plugin_loader:cache_reset() plugin_loader:load { plugins, options.plugins } - vim.cmd ":PackerCompile" vim.cmd ":PackerInstall" + vim.cmd ":PackerCompile" -- vim.cmd ":PackerClean" - local null_ls = require "lsp.null-ls" - null_ls.setup(vim.bo.filetype, { force_reload = true }) + require("lsp").setup() Log:info "Reloaded configuration" end @@ -119,12 +121,119 @@ function utils.gsub_args(args) 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 filename (string) path to check +--@param path (string) path to check --@returns (bool) -function utils.is_file(filename) - local stat = uv.fs_stat(filename) +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/.config/nvim/spell/en.utf-8.add b/.config/nvim/spell/en.utf-8.add index 18b8b6e..a4f2f9c 100644 --- a/.config/nvim/spell/en.utf-8.add +++ b/.config/nvim/spell/en.utf-8.add @@ -2,3 +2,5 @@ emnist json num np +#qvae +#qvae |