diff --git a/home/.config/nvim/lua/lsp/autoformat.lua b/home/.config/nvim/lua/lsp/autoformat.lua new file mode 100644 index 0000000..e4363c1 --- /dev/null +++ b/home/.config/nvim/lua/lsp/autoformat.lua @@ -0,0 +1,5 @@ +local vim = require("vim") +local cmd = vim.cmd + +-- Always automatically format on write for given filenames +cmd[[autocmd BufWritePre *.js lua vim.lsp.buf.formatting_sync(nil, 100)]] diff --git a/home/.config/nvim/lua/lsp/init.lua b/home/.config/nvim/lua/lsp/init.lua new file mode 100644 index 0000000..1e26feb --- /dev/null +++ b/home/.config/nvim/lua/lsp/init.lua @@ -0,0 +1,31 @@ +-- Neovim has built in support for the language server protocol (LSP). For +-- which reason I decided to utilize it directly instead of relying on plugins +-- such as COC, which reimplement it completely just to support default vim +-- too, since I don't need pure vim support, utilizing this built in support +-- makes a lot more sense and will be faster. +-- +-- By default, setting up LSP doesn't technically require any plugins, however +-- I still do use the recommended neovim/nvim-lspconfig plugin, along with +-- williamboman/nvim-lsp-installer, because it makes things a lot easier to get +-- working. The lspconfig holds the default configurations for the individual +-- language servers, avoiding the need of tediously configuring them manually, +-- and the lspinstaller gives us a way to automatically install selected +-- language servers locally for nvim only, which means we won't need to look at +-- the install instructions for each language server and install it user or +-- system wide. +-- +-- However, since this configuration shouldn't be plugin dependant, as it is +-- outside of the plugins/ directory and LSP is supported by neovim directly, +-- this folder is here to provide the non-plugin dependant LSP configuration, +-- but I do not manually define the configuration for each language server, +-- since I do actually utilize those plugins, but sturcturing like this still +-- does give space for completely custom configurations written from scratch +-- without relying on any external plugins at all. If you do want to do that, +-- this would be the place to set this up. +-- +-- NOTE: With my current configuration, this file is only ran by being required +-- in the lsp plugin config file, if you don't wish to run with plugins, you'll +-- want to require this file from init.lua directly. + +require("lsp.keymaps") +require("lsp.autoformat") diff --git a/home/.config/nvim/lua/lsp/keymaps.lua b/home/.config/nvim/lua/lsp/keymaps.lua new file mode 100644 index 0000000..4a31dcf --- /dev/null +++ b/home/.config/nvim/lua/lsp/keymaps.lua @@ -0,0 +1,57 @@ +local m = require("utility.mappings") + +-- See `:help vim.lsp.*` for documentation on any of the below mapped functions + +-- Check if certain plugins are installed, if so, they should be used +-- to define some mappings +local telescope_installed, _ = pcall(require, "telescope") +local lsp_signature_installed, _ = pcall(require, "lsp_signature") + +-- Lookups +m.keymap("n", "gd", "lua vim.lsp.buf.definition()") +m.keymap('n', 'gD', 'lua vim.lsp.buf.declaration()') +m.keymap("n", "gr", "lua vim.lsp.buf.references()") +m.keymap("n", "gi", "lua vim.lsp.buf.implementation()") +m.keymap("n", "gt", "lua vim.lsp.buf.type_definition()") + +if telescope_installed then + m.keymap('n', 'gd', 'lua require("telescope.builtin").lsp_definitions()') + m.keymap('n', 'gr', 'lua require("telescope.builtin").lsp_references()') + m.keymap('n', 'gi', 'lua require("telescope.builtin").lsp_implementations()') + m.keymap('n', 'gt', 'lua require("telescope.builtin").lsp_type_definitions()') +end + +-- Formatting +m.keymap('n', 'gf', 'lua vim.lsp.buf.formatting()') +m.keymap('v', 'gf', 'lua vim.lsp.buf.range_formatting()') + +-- Hover info +m.keymap("n", "", "lua vim.lsp.buf.signature_help()") +m.keymap("n", "M", "lua vim.lsp.buf.hover()") + +if lsp_signature_installed then + m.keymap('n', '', 'lua require("lsp_signature").signature()') +end + +-- Diagnostics +m.keymap('n', '[g', 'lua vim.diagnostic.goto_prev()') +m.keymap('n', ']g', 'lua vim.diagnostic.goto_next()') +m.keymap('n', 'ge', 'lua vim.diagnostic.open_float(nil, { scope = "line", })') + +if telescope_installed then + m.keymap('n', 'ge', 'lua require("telescope.builtin").lsp_document_diagnostics()') +end + +-- LSP Workspace +m.keymap('n', 'wa', 'lua vim.lsp.buf.add_workspace_folder()') +m.keymap('n', 'wr', 'lua vim.lsp.buf.remove_workspace_folder()') +m.keymap('n', 'wl', 'lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))') + +--Actions +if telescope_installed then + m.keymap('n', 'ga', 'lua require("telescope.builtin").lsp_code_actions()') + m.keymap('v', 'ga', 'lua require("telescope.builtin").lsp_range_code_actions()') +end + +-- Use custom implementation for renaming all references +m.keymap('n', 'gn', 'lua require("lsp/rename").rename()') diff --git a/home/.config/nvim/lua/lsp/rename.lua b/home/.config/nvim/lua/lsp/rename.lua new file mode 100644 index 0000000..908724f --- /dev/null +++ b/home/.config/nvim/lua/lsp/rename.lua @@ -0,0 +1,3 @@ +-- Nvim's LSP lacks rename-all functionality which plugins like Coc provide +-- this is a manual implementation of this feature +-- TODO: Actually implement this diff --git a/home/.config/nvim/lua/plugins/plugin_list.lua b/home/.config/nvim/lua/plugins/plugin_list.lua index b2eae55..f8df119 100644 --- a/home/.config/nvim/lua/plugins/plugin_list.lua +++ b/home/.config/nvim/lua/plugins/plugin_list.lua @@ -62,11 +62,11 @@ local plugin_list = { config = get_plugin_file("firenvim.lua"), run = function() vim.fn['firenvim#install'](0) end }, - -- { - -- "neovim/nvim-lspconfig", - -- "williamboman/nvim-lsp-installer", - -- config = get_plugin_file("lspconfig.lua") - -- }, + { + "williamboman/nvim-lsp-installer", + config = get_plugin_file("lsp.lua"), + requires = { "neovim/nvim-lspconfig" }, + }, --{ -- "nvim-telescope/telescope.nvim", -- --config = get_plugin_file("telescope.lua") @@ -77,12 +77,12 @@ local plugin_list = { -- { "nvim-lua/plenary.nvim" }, -- } --}, - { - "neoclide/coc.nvim", - branch = "release", - config = get_plugin_file("coc.vim"), - requires = { "antoinemadec/coc-fzf", opt = true }, - }, + -- { + -- "neoclide/coc.nvim", + -- branch = "release", + -- config = get_plugin_file("coc.vim"), + -- requires = { "antoinemadec/coc-fzf", opt = true }, + -- }, } return plugin_list diff --git a/home/.config/nvim/lua/plugins/settings/lsp.lua b/home/.config/nvim/lua/plugins/settings/lsp.lua new file mode 100644 index 0000000..238529f --- /dev/null +++ b/home/.config/nvim/lua/plugins/settings/lsp.lua @@ -0,0 +1,73 @@ +local vim = require("vim") +local fn = vim.fn + +-- Load in our default plugin independant LSP settings. +-- These are loaded from here, because we don't need them if we aren't using +-- these plugins, which actually load in the LSP configurations and install the +-- individual language servers. However it is possible to configure nvim +-- without these plugins and so this config is separated from the plugin +-- config. for more info, check the comments in lsp/init.lua +require("lsp") + + +-- Load in the needed settigns for nvim-lsp-installer plugin. +-- This ensures automatic installation for the individual language servers. +local lsp_installer = require("nvim-lsp-installer") + +-- Define some settings for the UI and installation path for the language +-- servers. +lsp_installer.settings({ + ui = { + icons = { + server_installed = "✓", + server_pending = "➜", + server_uninstalled = "✗" + }, + keymaps = { + toggle_server_expand = "", + install_server = "i", + update_server = "u", + uninstall_server = "X", + }, + }, + install_root_dir = fn.stdpath("data") .. "/lsp_servers", +}) + +-- Define a table of requested language servers which should be automatically +-- installed. +-- +-- NOTE: pylsp requires external installaion with +-- :PylspInstall pyls-flake8 pyls-mypy pyls-isort +local requested_servers = { + "clangd", "cmake", "omnisharp", + "cssls", "dockerls", "gopls", "html", + "hls", "jsonls", "jdtls", "tsserver", + "sumneko_lua", "pyright", "pylsp", + "sqlls", "vimls", "yamlls" +} + +-- Go through the requested servers and ensure installation +-- Once the servers are ready, run setup() on them. This setup is basically +-- running the lspconfig.server.setup() which means lspconfig is needed to do +-- this. +local lsp_installer_servers = require('nvim-lsp-installer.servers') +for _, requested_server in pairs(requested_servers) do + local server_available, server = lsp_installer_servers.get_server(requested_server) + if server_available then + -- Setup the server once it will become ready + server:on_ready(function() + local opts = {} + server:setup(opts) + end) + -- If the server isn't yet installed, schedule the installation + if not server:is_installed() then + server:install() + end + else + vim.notify( + "Can't install: Language server " .. server .. " was not found - SKIPPED", + vim.log.levels.WARN, + { title = "Notification" } + ) + end +end