refactor: auto-generate language configuration (#1584)

Refactor the monolithic `lvim.lang` design into a more modular approach.

IMPORTANT: run `:LvimUpdate` in order to generate the new ftplugin template files.
This commit is contained in:
kylo252 2021-10-03 16:13:46 +02:00 committed by GitHub
parent 3e1cd1ec23
commit d01ba08eae
WARNING! Although there is a key with this ID in the database it does not verify this commit! This commit is SUSPICIOUS.
GPG key ID: 4AEE18F83AFDEB23
98 changed files with 1127 additions and 1567 deletions

View file

@ -1 +0,0 @@
require("lsp").setup "asm"

View file

@ -1 +0,0 @@
require("lsp").setup "beancount"

View file

@ -1 +0,0 @@
require("lsp").setup "bicep"

View file

@ -1,4 +0,0 @@
require("lsp").setup "c"
-- TODO get from dap
-- require("lang.c").dap()

View file

@ -1 +0,0 @@
require("lsp").setup "clojure"

View file

@ -1 +0,0 @@
require("lsp").setup "cmake"

View file

@ -1 +0,0 @@
require("lsp").setup "cpp"

View file

@ -1 +0,0 @@
require("lsp").setup "crystal"

View file

@ -1 +0,0 @@
require("lsp").setup "cs"

View file

@ -1 +0,0 @@
require("lsp").setup "css"

View file

@ -1 +0,0 @@
require("lsp").setup "d"

View file

@ -1 +0,0 @@
require("lsp").setup "dart"

View file

@ -1 +0,0 @@
require("lsp").setup "dockerfile"

View file

@ -1,10 +0,0 @@
require("lsp").setup "elixir"
vim.api.nvim_buf_set_option(0, "commentstring", "# %s")
-- TODO: do we need this?
-- needed for the LSP to recognize elixir files (alternatively just use elixir-editors/vim-elixir)
-- vim.cmd [[
-- au BufRead,BufNewFile *.ex,*.exs set filetype=elixir
-- au BufRead,BufNewFile *.eex,*.leex,*.sface set filetype=eelixir
-- au BufRead,BufNewFile mix.lock set filetype=elixir
-- ]]

View file

@ -1 +0,0 @@
require("lsp").setup "elm"

View file

@ -1 +0,0 @@
require("lsp").setup "erlang"

View file

@ -1,9 +0,0 @@
require("lsp").setup "erlang"
-- TODO: do we need this?
-- needed for the LSP to recognize elixir files (alternatively just use elixir-editors/vim-elixir)
-- vim.cmd [[
-- au BufRead,BufNewFile *.ex,*.exs set filetype=elixir
-- au BufRead,BufNewFile *.eex,*.leex,*.sface set filetype=eelixir
-- au BufRead,BufNewFile mix.lock set filetype=elixir
-- ]]

View file

@ -1 +0,0 @@
require("lsp").setup "fish"

View file

@ -1 +0,0 @@
require("lsp").setup "fortran"

View file

@ -1 +0,0 @@
require("lsp").setup "gdscript"

View file

@ -1 +0,0 @@
require("lsp").setup "go"

View file

@ -1 +0,0 @@
require("lsp").setup "graphql"

View file

@ -1 +0,0 @@
require("lsp").setup "haskell"

View file

@ -1,2 +0,0 @@
require("lsp").setup "html"
require("lsp").setup "tailwindcss"

View file

@ -1 +0,0 @@
require("lsp").setup "java"

View file

@ -1 +0,0 @@
require("lsp").setup "javascript"

View file

@ -1,2 +0,0 @@
require("lsp").setup "javascriptreact"
require("lsp").setup "tailwindcss"

View file

@ -1 +0,0 @@
require("lsp").setup "json"

View file

@ -1 +0,0 @@
require("lsp").setup "julia"

View file

@ -1 +0,0 @@
require("lsp").setup "kotlin"

View file

@ -1 +0,0 @@
css.lua

View file

@ -1 +0,0 @@
require("lsp").setup "lua"

View file

@ -1,2 +0,0 @@
vim.cmd [[nmap <buffer> h -]]
vim.cmd [[nmap <buffer> l <cr>]]

View file

@ -1 +0,0 @@
require("lsp").setup "nix"

View file

@ -1 +0,0 @@
require("lsp").setup "perl"

View file

@ -1 +0,0 @@
require("lsp").setup "php"

View file

@ -1,3 +0,0 @@
require("lsp").setup "ps1"
vim.cmd [[setlocal ts=4 sw=4]]

View file

@ -1 +0,0 @@
require("lsp").setup "puppet"

View file

@ -1,3 +0,0 @@
require("lsp").setup "python"
-- TODO get from dap
-- require("lang.python").dap()

View file

@ -1,2 +0,0 @@
-- R -e 'install.packages("languageserver",repos = "http://cran.us.r-project.org")'
require("lsp").setup "r"

View file

@ -1 +0,0 @@
r.lua

View file

@ -1,2 +0,0 @@
-- also support sorbet
require("lsp").setup "ruby"

View file

@ -1,4 +0,0 @@
require("lsp").setup "rust"
-- TODO get from dap
-- require("lang.rust").dap()

View file

@ -1 +0,0 @@
css.lua

View file

@ -1 +0,0 @@
scala.lua

View file

@ -1 +0,0 @@
require("lsp").setup "scala"

View file

@ -1 +0,0 @@
css.lua

View file

@ -1 +0,0 @@
require("lsp").setup "sh"

View file

@ -1 +0,0 @@
require("lsp").setup "solidity"

View file

@ -1 +0,0 @@
require("lsp").setup "sql"

View file

@ -1,2 +0,0 @@
require("lsp").setup "svelte"
require("lsp").setup "tailwindcss"

View file

@ -1 +0,0 @@
require("lsp").setup "swift"

View file

@ -1 +0,0 @@
require("lsp").setup "terraform"

View file

@ -1 +0,0 @@
require("lsp").setup "tex"

View file

View file

@ -1 +0,0 @@
vim.cmd [[setlocal commentstring=#%s]]

View file

@ -1 +0,0 @@
require("lsp").setup "typescript"

View file

@ -1,2 +0,0 @@
require("lsp").setup "typescript"
require("lsp").setup "tailwindcss"

View file

@ -1 +0,0 @@
require("lsp").setup "vim"

View file

@ -1,2 +0,0 @@
require("lsp").setup "vue"
require("lsp").setup "tailwindcss"

View file

@ -1 +0,0 @@
require("lsp").setup "yaml"

View file

@ -1 +0,0 @@
require("lsp").setup "zig"

View file

@ -1 +0,0 @@
require("lsp").setup "sh"

View file

@ -18,10 +18,9 @@ Log:debug "Starting LunarVim"
vim.g.colors_name = lvim.colorscheme -- Colorscheme must get called after plugins are loaded or it will break new installs.
vim.cmd("colorscheme " .. lvim.colorscheme)
require("utils").toggle_autoformat()
local commands = require "core.commands"
commands.load(commands.defaults)
require("lsp").global_setup()
require("keymappings").setup()
require("lsp").setup()

View file

@ -85,9 +85,10 @@ function M:init()
vim.cmd("set spellfile=" .. join_paths(self.config_dir, "spell", "en.utf-8.add"))
end
vim.fn.mkdir(vim.fn.stdpath "cache", "p")
-- FIXME: currently unreliable in unit-tests
if not os.getenv "LVIM_TEST_ENV" then
vim.fn.mkdir(vim.fn.stdpath "cache", "p")
require("impatient").setup {
path = vim.fn.stdpath "cache" .. "/lvim_cache",
enable_profiling = true,
@ -112,6 +113,7 @@ end
function M:update()
M:update_repo()
M:reset_cache()
require("lsp.templates").generate_templates()
vim.schedule(function()
-- TODO: add a changelog
vim.notify("Update complete", vim.log.levels.INFO)

File diff suppressed because it is too large Load diff

View file

@ -22,6 +22,106 @@ function M:init(opts)
local settings = require "config.settings"
settings.load_options()
local lvim_lsp_config = require "lsp.config"
lvim.lsp = vim.deepcopy(lvim_lsp_config)
local supported_languages = {
"asm",
"bash",
"beancount",
"bibtex",
"bicep",
"c",
"c_sharp",
"clojure",
"cmake",
"comment",
"commonlisp",
"cpp",
"crystal",
"cs",
"css",
"cuda",
"d",
"dart",
"dockerfile",
"dot",
"elixir",
"elm",
"emmet",
"erlang",
"fennel",
"fish",
"fortran",
"gdscript",
"glimmer",
"go",
"gomod",
"graphql",
"haskell",
"hcl",
"heex",
"html",
"java",
"javascript",
"javascriptreact",
"jsdoc",
"json",
"json5",
"jsonc",
"julia",
"kotlin",
"latex",
"ledger",
"less",
"lua",
"markdown",
"nginx",
"nix",
"ocaml",
"ocaml_interface",
"perl",
"php",
"pioasm",
"ps1",
"puppet",
"python",
"ql",
"query",
"r",
"regex",
"rst",
"ruby",
"rust",
"scala",
"scss",
"sh",
"solidity",
"sparql",
"sql",
"supercollider",
"surface",
"svelte",
"swift",
"tailwindcss",
"terraform",
"tex",
"tlaplus",
"toml",
"tsx",
"turtle",
"typescript",
"typescriptreact",
"verilog",
"vim",
"vue",
"yaml",
"yang",
"zig",
}
require("lsp.manager").init_defaults(supported_languages)
end
--- Override the configuration with a user provided one

View file

@ -15,7 +15,6 @@ local builtins = {
"core.bufferline",
"core.autopairs",
"core.comment",
"core.lspinstall",
"core.lualine",
}

View file

@ -35,9 +35,35 @@ M.config = function()
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 = lvim.builtin.cmp.formatting.kind_icons[vim_item.kind]
vim_item.menu = ({
nvim_lsp = "(LSP)",
emoji = "(Emoji)",

View file

@ -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, ", "))
@ -65,32 +66,14 @@ local function tbl_set_highlight(terms, highlight_group)
end
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 header = {
fmt("Detected filetype: %s", ft),
fmt("Treesitter active: %s", tostring(next(vim.treesitter.highlighter.active) ~= nil)),
}
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),
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
@ -99,10 +82,39 @@ function M.toggle_popup(ft)
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(lsp_info, enabled_caps)
vim.list_extend(client_info, enabled_caps)
end
local null_ls = require "lsp.null-ls"
local registered_providers = null_ls.list_supported_provider_names(ft)
return client_info
end
function M.toggle_popup(ft)
local lsp_utils = require "lsp.utils"
local clients = lsp_utils.get_active_client_by_ft(ft)
local client_names = {}
local header = {
fmt("Detected filetype: %s", ft),
fmt("Treesitter active: %s", tostring(next(vim.treesitter.highlighter.active) ~= nil)),
}
local lsp_info = {
"Language Server Protocol (LSP) info",
fmt "* Associated server(s):",
}
for _, client in pairs(clients) do
vim.list_extend(lsp_info, make_client_info(client))
table.insert(client_names, client.name)
end
local null_formatters = require "lsp.null-ls.formatters"
local null_linters = require "lsp.null-ls.linters"
local registered_formatters = null_formatters.list_supported_names(ft)
local registered_linters = null_linters.list_supported_names(ft)
local registered_providers = {}
vim.list_extend(registered_providers, registered_formatters)
vim.list_extend(registered_providers, registered_linters)
local registered_count = vim.tbl_count(registered_providers)
local null_ls_info = {
"Formatters and linters",
@ -113,24 +125,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 = {}
@ -143,8 +137,6 @@ function M.toggle_popup(ft)
lsp_info,
{ "" },
null_ls_info,
missing_formatters_status,
missing_linters_status,
{ "" },
{ "" },
get_formatter_suggestion_msg(ft),
@ -167,11 +159,8 @@ function M.toggle_popup(ft)
vim.cmd 'let m=matchadd("string", "true")'
vim.cmd 'let m=matchadd("error", "false")'
tbl_set_highlight(registered_providers, "LvimInfoIdentifier")
tbl_set_highlight(missing_formatters, "LvimInfoIdentifier")
tbl_set_highlight(missing_linters, "LvimInfoIdentifier")
-- tbl_set_highlight(require("lsp.null-ls.formatters").list_available(ft), "LvimInfoIdentifier")
-- tbl_set_highlight(require("lsp.null-ls.linters").list_available(ft), "LvimInfoIdentifier")
vim.cmd('let m=matchadd("LvimInfoIdentifier", "' .. client_name .. '")')
end
local Popup = require("interface.popup"):new {

View file

@ -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

View file

@ -1,19 +0,0 @@
local M = {}
M.config = function()
lvim.builtin.lspinstall = {
active = true,
on_config_done = nil,
}
end
M.setup = function()
local lspinstall = require "lspinstall"
lspinstall.setup()
if lvim.builtin.lspinstall.on_config_done then
lvim.builtin.lspinstall.on_config_done(lspinstall)
end
end
return M

View file

@ -96,14 +96,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"

View file

@ -148,9 +148,9 @@ M.config = function()
"<cmd>Telescope lsp_workspace_diagnostics<cr>",
"Workspace Diagnostics",
},
-- f = { "<cmd>silent FormatWrite<cr>", "Format" },
f = { "<cmd>lua vim.lsp.buf.formatting()<cr>", "Format" },
i = { "<cmd>LspInfo<cr>", "Info" },
I = { "<cmd>LspInstallInfo<cr>", "Installer Info" },
j = {
"<cmd>lua vim.lsp.diagnostic.goto_next({popup_opts = {border = lvim.lsp.popup_border}})<cr>",
"Next Diagnostic",

27
lua/lsp/config.lua Normal file
View file

@ -0,0 +1,27 @@
return {
templates_dir = join_paths(get_runtime_dir(), "site", "after", "ftplugin"),
diagnostics = {
signs = {
active = true,
values = {
{ name = "LspDiagnosticsSignError", text = "" },
{ name = "LspDiagnosticsSignWarning", text = "" },
{ name = "LspDiagnosticsSignHint", text = "" },
{ name = "LspDiagnosticsSignInformation", text = "" },
},
},
virtual_text = {
prefix = "",
spacing = 0,
},
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,
}

View file

@ -1,5 +1,6 @@
local M = {}
local Log = require "core.log"
local utils = require "utils"
local function lsp_highlight_document(client)
if lvim.lsp.document_highlight == false then
@ -61,48 +62,12 @@ function M.common_capabilities()
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
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 = {}
for k, v in pairs(client.resolved_capabilities) do
if v == true then
table.insert(enabled_caps, k)
end
end
return enabled_caps
end
function M.common_on_init(client, bufnr)
if lvim.lsp.on_init_callback then
lvim.lsp.on_init_callback(client, bufnr)
Log:debug "Called lsp.on_init_callback"
return
end
local formatters = lvim.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
end
function M.common_on_attach(client, bufnr)
@ -112,63 +77,46 @@ function M.common_on_attach(client, bufnr)
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 = lvim.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 = lvim.lsp.override
if type(overrides) == "table" then
if vim.tbl_contains(overrides, lang) then
return
end
end
if lsp.provider ~= nil and lsp.provider ~= "" then
local lspconfig = require "lspconfig"
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
lspconfig[lsp.provider].setup(lsp.setup)
end
end
function M.global_setup()
vim.lsp.protocol.CompletionItemKind = lvim.lsp.completion.item_kind
for _, sign in ipairs(lvim.lsp.diagnostics.signs.values) do
vim.fn.sign_define(sign.name, { texthl = sign.name, text = sign.text, numhl = sign.name })
end
require("lsp.handlers").setup()
local null_status_ok, null_ls = pcall(require, "null-ls")
if null_status_ok then
null_ls.config()
require("lspconfig")["null-ls"].setup(lvim.lsp.null_ls.setup)
if not utils.is_directory(lvim.lsp.templates_dir) then
require("lsp.templates").generate_templates()
end
local utils = require "utils"
bootstrap_nlsp { config_home = utils.join_paths(get_config_dir(), "lsp-settings") }
local lsp_settings_status_ok, lsp_settings = pcall(require, "nlspsettings")
if lsp_settings_status_ok then
lsp_settings.setup {
config_home = utils.join_paths(get_config_dir(), "lsp-settings"),
}
end
require("lsp.null-ls").setup()
require("utils").toggle_autoformat()
end
return M

View file

@ -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

82
lua/lsp/manager.lua Normal file
View file

@ -0,0 +1,82 @@
local M = {}
local Log = require "core.log"
local lsp_utils = require "lsp.utils"
function M.init_defaults(languages)
for _, entry in ipairs(languages) do
if not lvim.lang[entry] then
lvim.lang[entry] = {
formatters = {},
linters = {},
}
end
end
end
local function is_overridden(server)
local overrides = lvim.lsp.override
if type(overrides) == "table" then
if vim.tbl_contains(overrides, server) then
return
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 lvim.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

View file

@ -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, options)
options = options or {}
local filter = options.filter or "supported"
return vim.tbl_keys(formatters[filter])
end
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)
@ -62,12 +47,13 @@ function M.list_configured(formatter_configs)
return { supported = formatters, unsupported = errors }
end
function M.setup(filetype, options)
if not lvim.lang[filetype] or (formatters_by_ft[filetype] and not options.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(lvim.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

View file

@ -1,44 +1,26 @@
local M = {}
function M.list_supported_provider_names(filetype)
local names = {}
local Log = require "core.log"
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, options)
options = options or {}
local ok, _ = pcall(require, "null-ls")
if not ok then
require("core.log"):error "Missing null-ls dependency"
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, options)
linters.setup(filetype, options)
null_ls.config()
require("lspconfig")["null-ls"].setup {}
for _, filetype in pairs(lvim.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

View file

@ -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, options)
options = options or {}
local filter = options.filter or "supported"
return vim.tbl_keys(linters[filter])
end
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)
@ -62,12 +47,13 @@ function M.list_configured(linter_configs)
return { supported = linters, unsupported = errors }
end
function M.setup(filetype, options)
if not lvim.lang[filetype] or (linters_by_ft[filetype] and not options.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(lvim.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

View file

@ -45,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

View file

@ -0,0 +1,30 @@
local schemas = nil
local status_ok, jsonls_settings = pcall(require, "nlspsettings.jsonls")
if status_ok then
schemas = jsonls_settings.get_default_schemas()
end
local opts = {
setup = {
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,
},
},
},
}
return opts

View file

@ -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

View file

@ -0,0 +1,26 @@
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

98
lua/lsp/templates.lua Normal file
View file

@ -0,0 +1,98 @@
local M = {}
local Log = require "core.log"
local utils = require "utils"
local get_supported_filetypes = require("lsp.utils").get_supported_filetypes
local ftplugin_dir = lvim.lsp.templates_dir
local join_paths = _G.join_paths
function M.remove_template_files()
-- remove any outdated files
for _, file in ipairs(vim.fn.glob(ftplugin_dir .. "/*.lua", 1, 1)) do
vim.fn.delete(file)
end
end
---Checks if a server is ignored by default because of a conflict
---Only TSServer is enabled by default for the javascript-family
---@param server_name string
function M.is_ignored(server_name, filetypes)
--TODO: this is easy to be made configurable once stable
filetypes = filetypes or get_supported_filetypes(server_name)
if vim.tbl_contains(filetypes, "javascript") then
if server_name == "tsserver" 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(lvim.lsp.templates_dir) then
vim.fn.mkdir(ftplugin_dir, "p")
end
for _, server in ipairs(servers_names) do
M.generate_ftplugin(server, ftplugin_dir)
end
Log:debug "Templates installation is complete"
end
return M

View file

@ -10,19 +10,60 @@ 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 lvim.lang[filetype] or not lvim.lang[filetype].lsp then
return nil
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 == lvim.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

View file

@ -6,12 +6,7 @@ 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" },

View file

@ -99,8 +99,7 @@ function utils.reload_lv_config()
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
@ -133,15 +132,106 @@ function utils.apply_defaults(config, default_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

View file

@ -25,17 +25,4 @@ a.describe("initial start", function()
a.it("should be able to run treesitter without errors", function()
assert.truthy(vim.treesitter.highlighter.active)
end)
a.it("should be able to load default packages without errors", function()
-- TODO: maybe there's a way to avoid hard-coding the names of the modules?
local startup_plugins = {
"packer",
"lspconfig",
"nlspsettings",
"null-ls",
}
for _, plugin in pairs(startup_plugins) do
assert.truthy(package.loaded[tostring(plugin)])
end
end)
end)

98
tests/lsp_spec.lua Normal file
View file

@ -0,0 +1,98 @@
local a = require "plenary.async_lib.tests"
local utils = require "utils"
lvim.lsp.templates_dir = join_paths(get_runtime_dir(), "lvim", "tests", "artifacts")
a.describe("lsp workflow", function()
local Log = require "core.log"
local logfile = Log:get_path()
a.it("shoud be able to delete ftplugin templates", function()
if utils.is_directory(lvim.lsp.templates_dir) then
assert.equal(vim.fn.delete(lvim.lsp.templates_dir, "rf"), 0)
end
assert.False(utils.is_directory(lvim.lsp.templates_dir))
end)
a.it("shoud be able to generate ftplugin templates", function()
if utils.is_directory(lvim.lsp.templates_dir) then
assert.equal(vim.fn.delete(lvim.lsp.templates_dir, "rf"), 0)
end
require("lsp").setup()
-- we need to delay this check until the generation is completed
vim.schedule(function()
assert.True(utils.is_directory(lvim.lsp.templates_dir))
end)
end)
a.it("shoud not attempt to re-generate ftplugin templates", function()
lvim.log.level = "debug"
local plugins = require "plugins"
require("plugin-loader"):load { plugins, lvim.plugins }
if utils.is_file(logfile) then
assert.equal(vim.fn.delete(logfile), 0)
end
assert.True(utils.is_directory(lvim.lsp.templates_dir))
require("lsp").setup()
-- we need to delay this check until the log gets populated
vim.schedule(function()
assert.False(utils.log_contains "templates")
end)
end)
a.it("shoud retrieve supported filetypes correctly", function()
local ocaml = {
name = "ocamlls",
filetypes = { "ocaml", "reason" },
}
local ocaml_fts = require("lsp.utils").get_supported_filetypes(ocaml.name)
assert.True(vim.deep_equal(ocaml.filetypes, ocaml_fts))
local tsserver = {
name = "tsserver",
filetypes = {
"javascript",
"javascriptreact",
"javascript.jsx",
"typescript",
"typescriptreact",
"typescript.tsx",
},
}
local tsserver_fts = require("lsp.utils").get_supported_filetypes(tsserver.name)
assert.True(vim.deep_equal(tsserver.filetypes, tsserver_fts))
end)
a.it("shoud ignore all javascript servers except tsserver and tailwindcss when generating templates", function()
local test_server = { name = "denols", filetypes = {} }
test_server.filetypes = require("lsp.utils").get_supported_filetypes(test_server.name)
assert.True(vim.tbl_contains(test_server.filetypes, "javascript"))
local is_ignored = require("lsp.templates").is_ignored(test_server.name)
assert.True(is_ignored)
local ts_template = utils.join_paths(lvim.lsp.templates_dir, "typescript.lua")
assert.True(utils.file_contains(ts_template, "tsserver"))
assert.True(utils.file_contains(ts_template, "tailwindcss"))
assert.False(utils.file_contains(ts_template, test_server.name))
end)
a.it("shoud not include blacklisted servers in the generated templates", function()
assert.True(utils.is_directory(lvim.lsp.templates_dir))
require("lsp").setup()
local blacklisted = { "jedi_language_server", "pylsp", "sqlls", "sqls", "angularls", "ansiblels" }
for _, file in ipairs(vim.fn.glob(lvim.lsp.templates_dir .. "/*.lua", 1, 1)) do
for _, server in ipairs(blacklisted) do
assert.False(utils.file_contains(file, server))
end
end
end)
end)

9
tests/minimal_init.lua Normal file
View file

@ -0,0 +1,9 @@
local path_sep = vim.loop.os_uname().version:match "Windows" and "\\" or "/"
vim.opt.rtp:append(os.getenv "LUNARVIM_RUNTIME_DIR" .. path_sep .. "lvim")
require("bootstrap"):init()
local config = require "config"
-- config:init()
config:load()

View file

@ -0,0 +1,34 @@
local a = require "plenary.async_lib.tests"
a.describe("plugin-loader", function()
a.it("should be able to load default packages without errors", function()
local plugins = require "plugins"
require("plugin-loader"):load { plugins, lvim.plugins }
-- TODO: maybe there's a way to avoid hard-coding the names of the modules?
local startup_plugins = {
"packer",
}
for _, plugin in ipairs(startup_plugins) do
assert.truthy(package.loaded[plugin])
end
end)
a.it("should be able to load lsp packages without errors", function()
local plugins = require "plugins"
require("plugin-loader"):load { plugins, lvim.plugins }
require("lsp").setup()
local lsp_packages = {
"lspconfig",
"nlspsettings",
"null-ls",
}
for _, plugin in ipairs(lsp_packages) do
assert.truthy(package.loaded[plugin])
end
end)
end)

9
utils/bin/lvim.ps1 Normal file
View file

@ -0,0 +1,9 @@
$env:XDG_DATA_HOME = ($env:XDG_DATA_HOME, "$env:APPDATA", 1 -ne $null)[0]
$env:XDG_CONFIG_HOME = ($env:XDG_CONFIG_HOME, "$LOCALAPPDATA", 1 -ne $null)[0]
$env:XDG_CACHE_HOME = ($env:XDG_CACHE_HOME, "$TEMP", 1 -ne $null)[0]
$env:LUNARVIM_RUNTIME_DIR = ($env:LUNARVIM_RUNTIME_DIR, "$env:XDG_DATA_HOME\lunarvim", 1 -ne $null)[0]
$env:LUNARVIM_CONFIG_DIR = ($env:LUNARVIM_CONFIG_DIR, "$env:XDG_CONFIG_HOME\lvim", 1 -ne $null)[0]
$env:LUNARVIM_CACHE_DIR = ($env:LUNARVIM_CACHE_DIR, "$env:XDG_CACHE_HOME\lvim", 1 -ne $null)[0]
nvim -u "$env:LUNARVIM_RUNTIME_DIR\lvim\init.lua"

View file

@ -10,11 +10,11 @@ rm -f "$LUNARVIM_CONFIG_DIR/plugin/packer_compiled.lua"
lvim() {
# TODO: allow running with a minimal_init.lua
nvim -u "$LUNARVIM_RUNTIME_DIR/lvim/init.lua" --cmd "set runtimepath+=$LUNARVIM_RUNTIME_DIR/lvim" "$@"
nvim -u "$LUNARVIM_RUNTIME_DIR/lvim/tests/minimal_init.lua" --cmd "set runtimepath+=$LUNARVIM_RUNTIME_DIR/lvim" "$@"
}
if [ -n "$1" ]; then
lvim --headless -c "lua require('plenary.busted').run('$1')"
else
lvim --headless -c "PlenaryBustedDirectory tests/ { minimal_init = './init.lua' }"
lvim --headless -c "PlenaryBustedDirectory tests/ { minimal_init = './tests/minimal_init.lua' }"
fi

View file

@ -55,7 +55,20 @@ lvim.builtin.nvimtree.setup.view.side = "left"
lvim.builtin.nvimtree.show_icons.git = 0
-- if you don't want all the parsers change this to a table of the ones you want
lvim.builtin.treesitter.ensure_installed = "maintained"
lvim.builtin.treesitter.ensure_installed = {
"bash",
"c",
"javascript",
"json",
"lua",
"python",
"typescript",
"css",
"rust",
"java",
"yaml",
}
lvim.builtin.treesitter.ignore_install = { "haskell" }
lvim.builtin.treesitter.highlight.enabled = true

280
utils/installer/install.ps1 Normal file
View file

@ -0,0 +1,280 @@
$ErrorActionPreference = "Stop" # exit when command fails
# set script variables
# FIXME: temporarily set the branch to the new one
$LV_BRANCH = ($LV_BRANCH, "lang-refactor", 1 -ne $null)[0]
$LV_REMOTE = ($LV_REMOTE, "lunarvim/lunarvim.git", 1 -ne $null)[0]
$INSTALL_PREFIX = ($INSTALL_PREFIX, "$HOME\.local", 1 -ne $null)[0]
$env:XDG_DATA_HOME = ($env:XDG_DATA_HOME, "$env:APPDATA", 1 -ne $null)[0]
$env:XDG_CONFIG_HOME = ($env:XDG_CONFIG_HOME, "$LOCALAPPDATA", 1 -ne $null)[0]
$env:XDG_CACHE_HOME = ($env:XDG_CACHE_HOME, "$TEMP", 1 -ne $null)[0]
$env:LUNARVIM_RUNTIME_DIR = ($env:LUNARVIM_RUNTIME_DIR, "$env:XDG_DATA_HOME\lunarvim", 1 -ne $null)[0]
$env:LUNARVIM_CONFIG_DIR = ($env:LUNARVIM_CONFIG_DIR, "$env:XDG_CONFIG_HOME\lvim", 1 -ne $null)[0]
$env:LUNARVIM_CACHE_DIR = ($env:LUNARVIM_CACHE_DIR, "$env:XDG_CACHE_HOME\lvim", 1 -ne $null)[0]
$__lvim_dirs = (
"$env:LUNARVIM_CONFIG_DIR",
"$env:LUNARVIM_RUNTIME_DIR",
"$env:LUNARVIM_CACHE_DIR"
)
function main($cliargs) {
Write-Output "
88\ 88\
88 | \__|
88 |88\ 88\ 888888$\ 888888\ 888888\ 88\ 88\ 88\ 888888\8888\
88 |88 | 88 |88 __88\ \____88\ 88 __88\\88\ 88 |88 |88 _88 _88\
88 |88 | 88 |88 | 88 | 888888$ |88 | \__|\88\88 / 88 |88 / 88 / 88 |
88 |88 | 88 |88 | 88 |88 __88 |88 | \88$ / 88 |88 | 88 | 88 |
88 |\888888 |88 | 88 |\888888$ |88 | \$ / 88 |88 | 88 | 88 |
\__| \______/ \__| \__| \_______|\__| \_/ \__|\__| \__| \__|
"
__add_separator "80"
# skip this in a Github workflow
if ( $null -eq "$GITHUB_ACTIONS" ) {
install_packer
setup_shim
exit
}
__add_separator "80"
check_system_deps
Write-Output "Would you like to check lunarvim's NodeJS dependencies?"
$answer = Read-Host "[y]es or [n]o (default: no) "
if ("$answer" -eq "y" -or "$answer" -eq "Y") {
install_nodejs_deps
}
Write-Output "Would you like to check lunarvim's Python dependencies?"
$answer = Read-Host "[y]es or [n]o (default: no) "
if ("$answer" -eq "y" -or "$answer" -eq "Y") {
install_python_deps
}
__add_separator "80"
Write-Output "Backing up old LunarVim configuration"
backup_old_config
__add_separator "80"
if ($cliargs.Contains("--overwrite")) {
Write-Output "!!Warning!! -> Removing all lunarvim related config because of the --overwrite flag"
$answer = Read-Host "Would you like to continue? [y]es or [n]o "
if ("$answer" -ne "y" -and "$answer" -ne "Y") {
exit 1
}
foreach ($dir in $__lvim_dirs) {
if (Test-Path "$dir") {
Remove-Item -Force -Recurse "$dir"
}
}
}
if (Test-Path "$env:LUNARVIM_RUNTIME_DIR\site\pack\packer\start\packer.nvim") {
Write-Output "Packer already installed"
}
else {
install_packer
}
__add_separator "80"
if (Test-Path "$env:LUNARVIM_RUNTIME_DIR\lvim\init.lua" ) {
Write-Output "Updating LunarVim"
update_lvim
}
else {
if ($cliargs.Contains("--testing")) {
copy_local_lvim_repository
}
else {
clone_lvim
}
setup_lvim
}
__add_separator "80"
}
function print_missing_dep_msg($dep) {
Write-Output "[ERROR]: Unable to find dependency [$dep]"
Write-Output "Please install it first and re-run the installer. Try: $RECOMMEND_INSTALL $dep"
}
function install_system_package($dep) {
if (Get-Command -Name "winget" -ErrorAction SilentlyContinue) {
Write-Output "[INFO]: Attempting to install dependency [$dep] with winget"
$install_cmd = "winget install --interactive"
}
elseif (Get-Command -Name "scoop" -ErrorAction SilentlyContinue) {
Write-Output "[INFO]: Attempting to install dependency [$dep] with scoop"
# TODO: check if it's fine to not run it with --global
$install_cmd = "scoop install"
}
else {
print_missing_dep_msg "$dep"
exit 1
}
try {
Invoke-Command $install_cmd $dep -ErrorAction Stop
}
catch {
print_missing_dep_msg "$dep"
exit 1
}
}
function check_system_dep($dep) {
try {
Get-Command -Name $dep -ErrorAction Stop | Out-Null
}
catch {
install_system_package "$dep"
}
}
function check_system_deps() {
Write-Output "[INFO]: Checking dependencies.."
check_system_dep "git"
check_system_dep "nvim"
}
function install_nodejs_deps() {
try {
check_system_dep "node"
Invoke-Command npm install -g neovim tree-sitter-cli -ErrorAction Break
}
catch {
print_missing_dep_msg "$dep"
}
}
function install_python_deps() {
try {
check_system_dep "pip"
Invoke-Command python -m pip install --user pynvim -ErrorAction Break
}
catch {
print_missing_dep_msg "$dep"
}
}
function backup_old_config() {
foreach ($dir in $__lvim_dirs) {
# we create an empty folder for subsequent commands \
# that require an existing directory
if ( Test-Path "$dir") {
New-Item "$dir.bak" -ItemType Directory -Force
Copy-Item -Recurse "$dir\*" "$dir.bak\."
}
}
Write-Output "Backup operation complete"
}
function install_packer() {
Invoke-Command -ErrorAction Stop -ScriptBlock { git clone --progress --depth 1 "https://github.com/wbthomason/packer.nvim" "$env:LUNARVIM_RUNTIME_DIR\site\pack\packer\start\packer.nvim" }
}
function copy_local_lvim_repository() {
Write-Output "Copy local LunarVim configuration"
Copy-Item -Path "$((Get-Item $PWD).Parent.Parent.FullName)" -Destination "$env:LUNARVIM_RUNTIME_DIR/lvim" -Recurse
}
function clone_lvim() {
Write-Output "Cloning LunarVim configuration"
try {
Invoke-Command -ErrorAction Stop -ScriptBlock { git clone --progress --branch "$LV_BRANCH" --depth 1 "https://github.com/$LV_REMOTE" "$env:LUNARVIM_RUNTIME_DIR/lvim" }
}
catch {
Write-Output "Failed to clone repository. Installation failed."
exit 1
}
}
function setup_shim() {
if ((Test-Path "$INSTALL_PREFIX\bin") -eq $false) {
New-Item "$INSTALL_PREFIX\bin" -ItemType Directory
}
Copy-Item "$env:LUNARVIM_RUNTIME_DIR\lvim\utils\bin\lvim.ps1" -Destination "$INSTALL_PREFIX\bin\lvim.ps1" -Force
}
function setup_lvim() {
Write-Output "Installing LunarVim shim"
setup_shim
Write-Output "Preparing Packer setup"
if ((Test-Path "$env:LUNARVIM_CONFIG_DIR") -eq $false) {
New-Item "$env:LUNARVIM_CONFIG_DIR" -ItemType Directory
}
Copy-Item "$env:LUNARVIM_RUNTIME_DIR\lvim\utils\installer\config.example-no-ts.lua" `
"$env:LUNARVIM_CONFIG_DIR\config.lua"
Write-Output "Packer setup complete"
__add_separator "80"
Copy-Item "$env:LUNARVIM_RUNTIME_DIR\lvim\utils\installer\config.example.lua" "$env:LUNARVIM_CONFIG_DIR\config.lua"
$answer = Read-Host $(`
"Would you like to create an alias inside your Powershell profile?`n" +`
"(This enables you to start lvim with the command 'lvim') [y]es or [n]o (default: no)" )
if ("$answer" -eq "y" -and "$answer" -eq "Y") {
create_alias
}
__add_separator "80"
Write-Output "Thank you for installing LunarVim!!"
Write-Output "You can start it by running: $INSTALL_PREFIX\bin\lvim.ps1"
Write-Output "Do not forget to use a font with glyphs (icons) support [https://github.com/ryanoasis/nerd-fonts]"
}
function update_lvim() {
try {
Invoke-Command git -C "$env:LUNARVIM_RUNTIME_DIR/lvim" status -uno
}
catch {
git -C "$env:LUNARVIM_RUNTIME_DIR/lvim" pull --ff-only --progress -or
Write-Output "Unable to guarantee data integrity while updating. Please do that manually instead."
exit 1
}
Write-Output "Your LunarVim installation is now up to date!"
}
function __add_separator($div_width) {
"-" * $div_width
Write-Output ""
}
function create_alias {
if($null -eq $(Get-Alias | Select-String "lvim")){
Add-Content -Path $PROFILE -Value $(-join @('Set-Alias lvim "', "$INSTALL_PREFIX", '\bin\lvim.ps1"'))
Write-Output ""
Write-Host 'To use the new alias in this window reload your profile with ". $PROFILE".' -ForegroundColor Yellow
}else {
Write-Output "Alias is already set and will not be reset."
}
}
main "$args"

View file

@ -0,0 +1 @@
Remove-Item -Path "$HOME/.local/share/lunarvim" -Recurse -Force