summaryrefslogtreecommitdiff
path: root/.config/nvim/lua/lsp
diff options
context:
space:
mode:
authorGustaf Rydholm <gustaf.rydholm@gmail.com>2021-08-10 23:15:04 +0200
committerGustaf Rydholm <gustaf.rydholm@gmail.com>2021-08-10 23:15:04 +0200
commit540268d618627079c9b958a955b586e1888b46a8 (patch)
tree1a22a5feb457135178b9d4fe8b6c1755f5ca66bc /.config/nvim/lua/lsp
parente79bd3273f58ba38e8fcd716090b89326791afbb (diff)
Major refactor of nvim
Diffstat (limited to '.config/nvim/lua/lsp')
-rw-r--r--.config/nvim/lua/lsp/emmet-ls.lua23
-rw-r--r--.config/nvim/lua/lsp/handlers.lua63
-rw-r--r--.config/nvim/lua/lsp/init.lua313
-rw-r--r--.config/nvim/lua/lsp/null-ls.lua141
-rw-r--r--.config/nvim/lua/lsp/peek.lua140
-rw-r--r--.config/nvim/lua/lsp/tailwindcss-ls.lua13
-rw-r--r--.config/nvim/lua/lsp/ts-fmt-lint.lua72
-rw-r--r--.config/nvim/lua/lsp/tsserver-ls.lua83
8 files changed, 442 insertions, 406 deletions
diff --git a/.config/nvim/lua/lsp/emmet-ls.lua b/.config/nvim/lua/lsp/emmet-ls.lua
deleted file mode 100644
index e38747a..0000000
--- a/.config/nvim/lua/lsp/emmet-ls.lua
+++ /dev/null
@@ -1,23 +0,0 @@
--- if not package.loaded['lspconfig'] then
--- return
--- end
-
-local nvim_lsp = require "lspconfig"
-local configs = require "lspconfig/configs"
-local capabilities = vim.lsp.protocol.make_client_capabilities()
-capabilities.textDocument.completion.completionItem.snippetSupport = true
-
-configs.emmet_ls = {
- default_config = {
- cmd = { "emmet-ls", "--stdio" },
- filetypes = { "html", "css", "javascript", "typescript", "vue" },
- root_dir = function()
- return vim.loop.cwd()
- end,
- settings = {},
- },
-}
-
-nvim_lsp.emmet_ls.setup {
- -- on_attach = on_attach;
-}
diff --git a/.config/nvim/lua/lsp/handlers.lua b/.config/nvim/lua/lsp/handlers.lua
new file mode 100644
index 0000000..c869d79
--- /dev/null
+++ b/.config/nvim/lua/lsp/handlers.lua
@@ -0,0 +1,63 @@
+-- Set Default Prefix.
+-- Note: You can set a prefix per lsp server in the lv-globals.lua file
+local M = {}
+
+function M.setup()
+ vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
+ virtual_text = options.lsp.diagnostics.virtual_text,
+ signs = options.lsp.diagnostics.signs.active,
+ underline = options.lsp.document_highlight,
+ })
+
+ vim.lsp.handlers["textDocument/publishDiagnostics"] = function(_, _, params, client_id, _)
+ local config = { -- your config
+ virtual_text = options.lsp.diagnostics.virtual_text,
+ signs = options.lsp.diagnostics.signs,
+ underline = options.lsp.diagnostics.underline,
+ update_in_insert = options.lsp.diagnostics.update_in_insert,
+ severity_sort = options.lsp.diagnostics.severity_sort,
+ }
+ local uri = params.uri
+ local bufnr = vim.uri_to_bufnr(uri)
+
+ if not bufnr then
+ return
+ end
+
+ local diagnostics = params.diagnostics
+
+ for i, v in ipairs(diagnostics) do
+ local source = v.source
+ if source then
+ if string.find(source, "/") then
+ source = string.sub(v.source, string.find(v.source, "([%w-_]+)$"))
+ end
+ diagnostics[i].message = string.format("%s: %s", source, v.message)
+ else
+ diagnostics[i].message = string.format("%s", v.message)
+ end
+
+ if vim.tbl_contains(vim.tbl_keys(v), "code") then
+ diagnostics[i].message = diagnostics[i].message .. string.format(" [%s]", v.code)
+ end
+ end
+
+ vim.lsp.diagnostic.save(diagnostics, bufnr, client_id)
+
+ if not vim.api.nvim_buf_is_loaded(bufnr) then
+ return
+ end
+
+ vim.lsp.diagnostic.display(diagnostics, bufnr, client_id, config)
+ end
+
+ vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, {
+ border = options.lsp.popup_border,
+ })
+
+ vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, {
+ border = options.lsp.popup_border,
+ })
+end
+
+return M
diff --git a/.config/nvim/lua/lsp/init.lua b/.config/nvim/lua/lsp/init.lua
index 6a52b9d..0c830f5 100644
--- a/.config/nvim/lua/lsp/init.lua
+++ b/.config/nvim/lua/lsp/init.lua
@@ -1,118 +1,17 @@
--- TODO: figure out why this don't work
-vim.fn.sign_define(
- "LspDiagnosticsSignError",
- { texthl = "LspDiagnosticsSignError", text = "", numhl = "LspDiagnosticsSignError" }
-)
-vim.fn.sign_define(
- "LspDiagnosticsSignWarning",
- { texthl = "LspDiagnosticsSignWarning", text = "", numhl = "LspDiagnosticsSignWarning" }
-)
-vim.fn.sign_define(
- "LspDiagnosticsSignHint",
- { texthl = "LspDiagnosticsSignHint", text = "", numhl = "LspDiagnosticsSignHint" }
-)
-vim.fn.sign_define(
- "LspDiagnosticsSignInformation",
- { texthl = "LspDiagnosticsSignInformation", text = "", numhl = "LspDiagnosticsSignInformation" }
-)
+local M = {}
+local Log = require "core.log"
+function M.config()
+ vim.lsp.protocol.CompletionItemKind = options.lsp.completion.item_kind
--- local opts = { border = "single" }
--- TODO revisit this
--- local border = {
--- { "🭽", "FloatBorder" },
--- { "▔", "FloatBorder" },
--- { "🭾", "FloatBorder" },
--- { "▕", "FloatBorder" },
--- { "🭿", "FloatBorder" },
--- { "▁", "FloatBorder" },
--- { "🭼", "FloatBorder" },
--- { "▏", "FloatBorder" },
--- }
-
--- My font didn't like this :/
--- vim.api.nvim_set_keymap(
--- "n",
--- "gl",
--- '<cmd>lua vim.lsp.diagnostic.show_line_diagnostics({ show_header = false, border = { { "🭽", "FloatBorder" }, { "▔", "FloatBorder" }, { "🭾", "FloatBorder" }, { "▕", "FloatBorder" }, { "🭿", "FloatBorder" }, { "▁", "FloatBorder" }, { "🭼", "FloatBorder" }, { "▏", "FloatBorder" }, } })<CR>',
--- { noremap = true, silent = true }
--- )
-
-if O.lsp.default_keybinds then
- vim.cmd "nnoremap <silent> gd <cmd>lua vim.lsp.buf.definition()<CR>"
- vim.cmd "nnoremap <silent> gD <cmd>lua vim.lsp.buf.declaration()<CR>"
- vim.cmd "nnoremap <silent> gr <cmd>lua vim.lsp.buf.references()<CR>"
- vim.cmd "nnoremap <silent> gi <cmd>lua vim.lsp.buf.implementation()<CR>"
- vim.api.nvim_set_keymap(
- "n",
- "gl",
- '<cmd>lua vim.lsp.diagnostic.show_line_diagnostics({ show_header = false, border = "single" })<CR>',
- { noremap = true, silent = true }
- )
+ 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
- vim.cmd "nnoremap <silent> gp <cmd>lua require'lsp'.PeekDefinition()<CR>"
- vim.cmd "nnoremap <silent> K :lua vim.lsp.buf.hover()<CR>"
- vim.cmd "nnoremap <silent> <C-p> :lua vim.lsp.diagnostic.goto_prev({popup_opts = {border = O.lsp.popup_border}})<CR>"
- vim.cmd "nnoremap <silent> <C-n> :lua vim.lsp.diagnostic.goto_next({popup_opts = {border = O.lsp.popup_border}})<CR>"
- vim.cmd "nnoremap <silent> <tab> <cmd>lua vim.lsp.buf.signature_help()<CR>"
- -- scroll down hover doc or scroll in definition preview
- -- scroll up hover doc
- vim.cmd 'command! -nargs=0 LspVirtualTextToggle lua require("lsp/virtual_text").toggle()'
+ require("lsp.handlers").setup()
end
--- Set Default Prefix.
--- Note: You can set a prefix per lsp server in the lv-globals.lua file
-vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
- virtual_text = O.lsp.diagnostics.virtual_text,
- signs = O.lsp.diagnostics.signs,
- underline = O.lsp.document_highlight,
-})
-
-vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, {
- border = O.lsp.popup_border,
-})
-
-vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, {
- border = O.lsp.popup_border,
-})
-
--- symbols for autocomplete
-vim.lsp.protocol.CompletionItemKind = {
- "  (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)",
-}
-
---[[ " autoformat
-autocmd BufWritePre *.js lua vim.lsp.buf.formatting_sync(nil, 100)
-autocmd BufWritePre *.jsx lua vim.lsp.buf.formatting_sync(nil, 100)
-autocmd BufWritePre *.lua lua vim.lsp.buf.formatting_sync(nil, 100) ]]
--- Java
--- autocmd FileType java nnoremap ca <Cmd>lua require('jdtls').code_action()<CR>
-
local function lsp_highlight_document(client)
- if O.lsp.document_highlight == false then
+ if options.lsp.document_highlight == false then
return -- we don't need further
end
-- Set autocommands conditional on server_capabilities
@@ -132,133 +31,117 @@ local function lsp_highlight_document(client)
)
end
end
-local lsp_config = {}
--- Taken from https://www.reddit.com/r/neovim/comments/gyb077/nvimlsp_peek_defination_javascript_ttserver/
-function lsp_config.preview_location(location, context, before_context)
- -- location may be LocationLink or Location (more useful for the former)
- context = context or 15
- before_context = before_context or 0
- local uri = location.targetUri or location.uri
- if uri == nil then
- return
- end
- local bufnr = vim.uri_to_bufnr(uri)
- if not vim.api.nvim_buf_is_loaded(bufnr) then
- vim.fn.bufload(bufnr)
+local function add_lsp_buffer_keybindings(bufnr)
+ local wk = require "which-key"
+ local keys = {
+ ["K"] = { "<cmd>lua vim.lsp.buf.hover()<CR>", "Show hover" },
+ ["gd"] = { "<cmd>lua vim.lsp.buf.definition()<CR>", "Goto Definition" },
+ ["gD"] = { "<cmd>lua vim.lsp.buf.declaration()<CR>", "Goto declaration" },
+ ["gr"] = { "<cmd>lua vim.lsp.buf.references()<CR>", "Goto references" },
+ ["gi"] = { "<cmd>lua vim.lsp.buf.implementation()<CR>", "Goto implementation" },
+ ["gs"] = { "<cmd>lua vim.lsp.buf.signature_help()<CR>", "show signature help" },
+ ["gp"] = { "<cmd>lua require'lsp.peek'.Peek('definition')<CR>", "Peek definition" },
+ ["gl"] = {
+ "<cmd>lua vim.lsp.diagnostic.show_line_diagnostics({ show_header = false, border = 'single' })<CR>",
+ "Show line diagnostics",
+ },
+ }
+ wk.register(keys, { mode = "n", buffer = bufnr })
+end
+
+local function set_smart_cwd(client)
+ local proj_dir = client.config.root_dir
+ if options.lsp.smart_cwd and proj_dir ~= "/" then
+ vim.api.nvim_set_current_dir(proj_dir)
+ require("core.nvimtree").change_tree_dir(proj_dir)
end
+end
- local range = location.targetRange or location.range
- local contents = vim.api.nvim_buf_get_lines(
- bufnr,
- range.start.line - before_context,
- range["end"].line + 1 + context,
- false
- )
- local filetype = vim.api.nvim_buf_get_option(bufnr, "filetype")
- return vim.lsp.util.open_floating_preview(contents, filetype, { border = O.lsp.popup_border })
+function M.common_capabilities()
+ local capabilities = vim.lsp.protocol.make_client_capabilities()
+ capabilities.textDocument.completion.completionItem.snippetSupport = true
+ capabilities.textDocument.completion.completionItem.resolveSupport = {
+ properties = {
+ "documentation",
+ "detail",
+ "additionalTextEdits",
+ },
+ }
+ return capabilities
end
-function lsp_config.preview_location_callback(_, method, result)
- local context = 15
- if result == nil or vim.tbl_isempty(result) then
- print("No location found: " .. method)
- return nil
+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 vim.tbl_islist(result) then
- lsp_config.floating_buf, lsp_config.floating_win = lsp_config.preview_location(result[1], context)
- else
- lsp_config.floating_buf, lsp_config.floating_win = lsp_config.preview_location(result, context)
+ if not client_id then
+ error "Unable to determine client_id"
end
-end
-function lsp_config.PeekDefinition()
- if vim.tbl_contains(vim.api.nvim_list_wins(), lsp_config.floating_win) then
- vim.api.nvim_set_current_win(lsp_config.floating_win)
- else
- local params = vim.lsp.util.make_position_params()
- return vim.lsp.buf_request(0, "textDocument/definition", params, lsp_config.preview_location_callback)
+ 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 lsp_config.PeekTypeDefinition()
- if vim.tbl_contains(vim.api.nvim_list_wins(), lsp_config.floating_win) then
- vim.api.nvim_set_current_win(lsp_config.floating_win)
- else
- local params = vim.lsp.util.make_position_params()
- return vim.lsp.buf_request(0, "textDocument/typeDefinition", params, lsp_config.preview_location_callback)
+function M.common_on_init(client, bufnr)
+ if options.lsp.on_init_callback then
+ options.lsp.on_init_callback(client, bufnr)
+ Log:get_default().info "Called lsp.on_init_callback"
+ return
end
-end
-function lsp_config.PeekImplementation()
- if vim.tbl_contains(vim.api.nvim_list_wins(), lsp_config.floating_win) then
- vim.api.nvim_set_current_win(lsp_config.floating_win)
- else
- local params = vim.lsp.util.make_position_params()
- return vim.lsp.buf_request(0, "textDocument/implementation", params, lsp_config.preview_location_callback)
+ 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:get_default().info(
+ string.format("Overriding language server [%s] with format provider [%s]", client.name, formatters[1].exe)
+ )
end
end
-function lsp_config.common_on_attach(client, bufnr)
- if O.lsp.on_attach_callback then
- O.lsp.on_attach_callback(client, bufnr)
+function M.common_on_attach(client, bufnr)
+ if options.lsp.on_attach_callback then
+ options.lsp.on_attach_callback(client, bufnr)
+ Log:get_default().info "Called lsp.on_init_callback"
end
lsp_highlight_document(client)
+ add_lsp_buffer_keybindings(bufnr)
+ set_smart_cwd(client)
+ require("lsp.null-ls").setup(vim.bo.filetype)
end
-function lsp_config.tsserver_on_attach(client, _)
- -- lsp_config.common_on_attach(client, bufnr)
- client.resolved_capabilities.document_formatting = false
-
- local ts_utils = require "nvim-lsp-ts-utils"
-
- -- defaults
- ts_utils.setup {
- debug = false,
- disable_commands = false,
- enable_import_on_completion = false,
- import_all_timeout = 5000, -- ms
-
- -- eslint
- eslint_enable_code_actions = true,
- eslint_enable_disable_comments = true,
- -- eslint_bin = O.lang.tsserver.linter,
- eslint_config_fallback = nil,
- eslint_enable_diagnostics = true,
-
- -- formatting
- enable_formatting = O.lang.tsserver.autoformat,
- formatter = O.lang.tsserver.formatter.exe,
- formatter_config_fallback = nil,
-
- -- parentheses completion
- complete_parens = false,
- signature_help_in_parens = false,
+function M.setup(lang)
+ local lsp = options.lang[lang].lsp
+ if require("utils").check_lsp_client_active(lsp.provider) then
+ return
+ end
- -- update imports on file move
- update_imports_on_move = false,
- require_confirmation_on_move = false,
- watch_dir = nil,
- }
+ local overrides = options.lsp.override
- -- required to fix code action ranges
- ts_utils.setup_client(client)
+ if type(overrides) == "table" then
+ if vim.tbl_contains(overrides, lang) then
+ return
+ end
+ end
- -- TODO: keymap these?
- -- vim.api.nvim_buf_set_keymap(bufnr, "n", "gs", ":TSLspOrganize<CR>", {silent = true})
- -- vim.api.nvim_buf_set_keymap(bufnr, "n", "qq", ":TSLspFixCurrent<CR>", {silent = true})
- -- vim.api.nvim_buf_set_keymap(bufnr, "n", "gr", ":TSLspRenameFile<CR>", {silent = true})
- -- vim.api.nvim_buf_set_keymap(bufnr, "n", "gi", ":TSLspImportAll<CR>", {silent = true})
+ local lspconfig = require "lspconfig"
+ lspconfig[lsp.provider].setup(lsp.setup)
end
-require("utils").define_augroups {
- _general_lsp = {
- { "FileType", "lspinfo", "nnoremap <silent> <buffer> q :q<CR>" },
- },
-}
-
--- Use a loop to conveniently both setup defined servers
--- and map buffer local keybindings when the language server attaches
--- local servers = {"pyright", "tsserver"}
--- for _, lsp in ipairs(servers) do nvim_lsp[lsp].setup {on_attach = on_attach} end
-return lsp_config
+return M
diff --git a/.config/nvim/lua/lsp/null-ls.lua b/.config/nvim/lua/lsp/null-ls.lua
new file mode 100644
index 0000000..81c6648
--- /dev/null
+++ b/.config/nvim/lua/lsp/null-ls.lua
@@ -0,0 +1,141 @@
+local M = {}
+local Log = require "core.log"
+
+local null_ls = require "null-ls"
+
+local nodejs_local_providers = { "prettier", "prettierd", "prettier_d_slim", "eslint_d", "eslint" }
+
+M.requested_providers = {}
+
+function M.get_registered_providers_by_filetype(ft)
+ local matches = {}
+ for _, provider in pairs(M.requested_providers) do
+ if vim.tbl_contains(provider.filetypes, ft) then
+ local provider_name = provider.name
+ -- special case: show "eslint_d" instead of eslint
+ -- https://github.com/jose-elias-alvarez/null-ls.nvim/blob/9b8458bd1648e84169a7e8638091ba15c2f20fc0/doc/BUILTINS.md#eslint
+ if string.find(provider._opts.command, "eslint_d") then
+ provider_name = "eslint_d"
+ end
+ table.insert(matches, provider_name)
+ end
+ end
+
+ return matches
+end
+
+function M.get_missing_providers_by_filetype(ft)
+ local matches = {}
+ for _, provider in pairs(M.requested_providers) do
+ if vim.tbl_contains(provider.filetypes, ft) then
+ local provider_name = provider.name
+
+ table.insert(matches, provider_name)
+ end
+ end
+
+ return matches
+end
+
+local function register_failed_request(ft, provider, operation)
+ if not options.lang[ft][operation]._failed_requests then
+ options.lang[ft][operation]._failed_requests = {}
+ end
+ table.insert(options.lang[ft][operation]._failed_requests, provider)
+end
+
+local function validate_nodejs_provider(provider)
+ local command_path
+ local root_dir
+ if options.builtin.rooter.active then
+ --- use vim-rooter to set root_dir
+ vim.cmd "let root_dir = FindRootDirectory()"
+ root_dir = vim.api.nvim_get_var "root_dir"
+ else
+ --- use LSP to set root_dir
+ local ts_client = require("utils").get_active_client_by_ft "typescript"
+ if ts_client == nil then
+ Log:get_default().error "Unable to determine root directory since tsserver didn't start correctly"
+ return
+ end
+ root_dir = ts_client.config.root_dir
+ end
+ local local_nodejs_command = root_dir .. "/node_modules/.bin/" .. provider._opts.command
+ Log:get_default().debug("checking for local node module: ", vim.inspect(provider))
+
+ if vim.fn.executable(local_nodejs_command) == 1 then
+ command_path = local_nodejs_command
+ elseif vim.fn.executable(provider._opts.command) == 1 then
+ Log:get_default().debug("checking in global path instead for node module", provider._opts.command)
+ command_path = provider._opts.command
+ else
+ Log:get_default().debug("Unable to find node module", provider._opts.command)
+ end
+ return command_path
+end
+
+local function validate_provider_request(provider)
+ if provider == "" or provider == nil then
+ return
+ end
+ -- NOTE: we can't use provider.name because eslint_d uses eslint name
+ if vim.tbl_contains(nodejs_local_providers, provider._opts.command) then
+ return validate_nodejs_provider(provider)
+ end
+ if vim.fn.executable(provider._opts.command) ~= 1 then
+ Log:get_default().warn("Unable to find the path for", vim.inspect(provider))
+ return
+ end
+ return provider._opts.command
+end
+
+-- TODO: for linters and formatters with spaces and '-' replace with '_'
+function M.setup(filetype)
+ for _, formatter in pairs(options.lang[filetype].formatters) do
+ Log:get_default().debug("validating format provider: ", formatter.exe)
+ local builtin_formatter = null_ls.builtins.formatting[formatter.exe]
+ if not vim.tbl_contains(M.requested_providers, builtin_formatter) then
+ -- FIXME: why doesn't this work?
+ -- builtin_formatter._opts.args = formatter.args or builtin_formatter._opts.args
+ -- builtin_formatter._opts.to_stdin = formatter.stdin or builtin_formatter._opts.to_stdin
+ local resolved_path = validate_provider_request(builtin_formatter)
+ if resolved_path then
+ builtin_formatter._opts.command = resolved_path
+ table.insert(M.requested_providers, builtin_formatter)
+ Log:get_default().info("Using format provider", builtin_formatter.name)
+ else
+ -- mark it here to avoid re-doing the lookup again
+ register_failed_request(filetype, formatter.exe, "formatters")
+ end
+ end
+ end
+
+ for _, linter in pairs(options.lang[filetype].linters) do
+ local builtin_diagnoser = null_ls.builtins.diagnostics[linter.exe]
+ Log:get_default().debug("validating lint provider: ", linter.exe)
+ -- special case: fallback to "eslint"
+ -- https://github.com/jose-elias-alvarez/null-ls.nvim/blob/9b8458bd1648e84169a7e8638091ba15c2f20fc0/doc/BUILTINS.md#eslint
+ -- if provider.exe
+ if linter.exe == "eslint_d" then
+ builtin_diagnoser = null_ls.builtins.diagnostics.eslint.with { command = "eslint_d" }
+ end
+ if not vim.tbl_contains(M.requested_providers, builtin_diagnoser) then
+ -- FIXME: why doesn't this work?
+ -- builtin_diagnoser._opts.args = linter.args or builtin_diagnoser._opts.args
+ -- builtin_diagnoser._opts.to_stdin = linter.stdin or builtin_diagnoser._opts.to_stdin
+ local resolved_path = validate_provider_request(builtin_diagnoser)
+ if resolved_path then
+ builtin_diagnoser._opts.command = resolved_path
+ table.insert(M.requested_providers, builtin_diagnoser)
+ Log:get_default().info("Using linter provider", builtin_diagnoser.name)
+ else
+ -- mark it here to avoid re-doing the lookup again
+ register_failed_request(filetype, linter.exe, "linters")
+ end
+ end
+ end
+
+ null_ls.register { sources = M.requested_providers }
+end
+
+return M
diff --git a/.config/nvim/lua/lsp/peek.lua b/.config/nvim/lua/lsp/peek.lua
new file mode 100644
index 0000000..cc8e57a
--- /dev/null
+++ b/.config/nvim/lua/lsp/peek.lua
@@ -0,0 +1,140 @@
+local M = {
+ floating_buf = nil,
+ floating_win = nil,
+ prev_result = nil,
+}
+
+local function create_floating_file(location, opts)
+ vim.validate {
+ location = { location, "t" },
+ opts = { opts, "t", true },
+ }
+
+ -- Set some defaults
+ opts = opts or {}
+ local close_events = opts.close_events or { "CursorMoved", "CursorMovedI", "BufHidden", "InsertCharPre" }
+
+ -- location may be LocationLink or Location
+ local uri = location.targetUri or location.uri
+ if uri == nil then
+ return
+ end
+ local bufnr = vim.uri_to_bufnr(uri)
+ if not vim.api.nvim_buf_is_loaded(bufnr) then
+ vim.fn.bufload(bufnr)
+ end
+
+ local range = location.targetRange or location.range
+
+ local contents = vim.api.nvim_buf_get_lines(
+ bufnr,
+ range.start.line,
+ math.min(range["end"].line + 1 + (opts.context or 10), range.start.line + (opts.max_height or 15)), -- Don't let the window be more that 15 lines long(height)
+ false
+ )
+ local width, height = vim.lsp.util._make_floating_popup_size(contents, opts)
+ opts = vim.lsp.util.make_floating_popup_options(width, height, opts)
+ -- Don't make it minimal as it is meant to be fully featured
+ opts["style"] = nil
+
+ vim.api.nvim_buf_set_option(bufnr, "bufhidden", "wipe")
+
+ local winnr = vim.api.nvim_open_win(bufnr, false, opts)
+ vim.api.nvim_win_set_option(winnr, "winblend", 0)
+
+ vim.api.nvim_buf_set_var(bufnr, "lsp_floating_window", winnr)
+
+ -- 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)"
+ )
+ vim.lsp.util.close_preview_autocmd(close_events, winnr)
+
+ return bufnr, winnr
+end
+
+local function preview_location_callback(_, method, result)
+ if result == nil or vim.tbl_isempty(result) then
+ print("peek: No location found: " .. method)
+ return nil
+ end
+
+ local opts = {
+ border = "rounded",
+ context = 10,
+ }
+
+ if vim.tbl_islist(result) then
+ M.prev_result = result[1]
+ M.floating_buf, M.floating_win = create_floating_file(result[1], opts)
+ else
+ M.prev_result = result
+ M.floating_buf, M.floating_win = create_floating_file(result, opts)
+ end
+end
+
+function M.open_file()
+ -- Get the file currently open in the floating window
+ local filepath = vim.fn.expand "%:."
+
+ if not filepath then
+ print "peek: Unable to open the file!"
+ return
+ end
+
+ -- Close the floating window
+ pcall(vim.api.nvim_win_close, M.floating_win, true)
+
+ -- Edit the file
+ vim.cmd("edit " .. filepath)
+
+ local winnr = vim.api.nvim_get_current_win()
+
+ -- Set the cursor at the right position
+ M.set_cursor_to_prev_pos(winnr)
+end
+
+function M.set_cursor_to_prev_pos(winnr)
+ -- Get position of the thing to peek at
+ local location = M.prev_result
+ local range = location.targetRange or location.range
+ local cursor_pos = { range.start.line + 1, range.start.character }
+
+ -- Set the winnr to the floating window if none was passed in
+ winnr = winnr or M.floating_win
+ -- Set the cursor at the correct position in the floating window
+ vim.api.nvim_win_set_cursor(winnr, cursor_pos)
+end
+
+function M.Peek(what)
+ -- If a window already exists, focus it at the right position!
+ if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then
+ local success_1, _ = pcall(vim.api.nvim_set_current_win, M.floating_win)
+ if not success_1 then
+ print "peek: You cannot edit the current file in a preview!"
+ return
+ end
+
+ -- Set the cursor at the correct position in the floating window
+ M.set_cursor_to_prev_pos()
+
+ vim.api.nvim_buf_set_keymap(
+ M.floating_buf,
+ "n",
+ "<CR>",
+ ":lua require('lsp.peek').open_file()<CR>",
+ { noremap = true, silent = true }
+ )
+ else
+ -- Make a new request and then create the new window in the callback
+ local params = vim.lsp.util.make_position_params()
+ local success, _ = pcall(vim.lsp.buf_request, 0, "textDocument/" .. what, params, preview_location_callback)
+ if not success then
+ print(
+ 'peek: Error calling LSP method "textDocument/' .. what .. '". The current language lsp might not support it.'
+ )
+ end
+ end
+end
+
+return M
diff --git a/.config/nvim/lua/lsp/tailwindcss-ls.lua b/.config/nvim/lua/lsp/tailwindcss-ls.lua
deleted file mode 100644
index 38c1e7c..0000000
--- a/.config/nvim/lua/lsp/tailwindcss-ls.lua
+++ /dev/null
@@ -1,13 +0,0 @@
--- TODO: what is a tailwindcss filetype
-local lspconfig = require "lspconfig"
-
-lspconfig.tailwindcss.setup {
- cmd = {
- "node",
- DATA_PATH .. "/lspinstall/tailwindcss/tailwindcss-intellisense/extension/dist/server/tailwindServer.js",
- "--stdio",
- },
- filetypes = O.lang.tailwindcss.filetypes,
- root_dir = require("lspconfig/util").root_pattern("tailwind.config.js", "postcss.config.ts", ".postcssrc"),
- on_attach = require("lsp").common_on_attach,
-}
diff --git a/.config/nvim/lua/lsp/ts-fmt-lint.lua b/.config/nvim/lua/lsp/ts-fmt-lint.lua
deleted file mode 100644
index 7cebfd8..0000000
--- a/.config/nvim/lua/lsp/ts-fmt-lint.lua
+++ /dev/null
@@ -1,72 +0,0 @@
--- Example configuations here: https://github.com/mattn/efm-langserver
-local M = {}
-
-M.setup = function()
- vim.cmd "let proj = FindRootDirectory()"
- local root_dir = vim.api.nvim_get_var "proj"
-
- local get_linter_instance = function()
- -- prioritize local instance over global
- local local_instance = root_dir .. "/node_modules/.bin/" .. O.lang.tsserver.linter
- if vim.fn.executable(local_instance) == 1 then
- return local_instance
- end
- return O.lang.tsserver.linter
- end
-
- local tsserver_args = {}
- local formattingSupported = false
-
- if O.lang.tsserver.linter == "eslint" or O.lang.tsserver.linter == "eslint_d" then
- local eslint = {
- lintCommand = get_linter_instance() .. " -f visualstudio --stdin --stdin-filename ${INPUT}",
- lintStdin = true,
- lintFormats = {
- "%f(%l,%c): %tarning %m",
- "%f(%l,%c): %trror %m",
- },
- lintSource = O.lang.tsserver.linter,
- lintIgnoreExitCode = true,
- }
- table.insert(tsserver_args, eslint)
- -- Only eslint_d supports --fix-to-stdout
- if string.find(get_linter_instance(), "eslint_d") then
- formattingSupported = true
- local eslint_fix = {
- formatCommand = get_linter_instance() .. " --fix-to-stdout --stdin --stdin-filename ${INPUT}",
- formatStdin = true,
- }
- table.insert(tsserver_args, eslint_fix)
- end
- end
-
- require("lspconfig").efm.setup {
- -- init_options = {initializationOptions},
- cmd = { DATA_PATH .. "/lspinstall/efm/efm-langserver" },
- init_options = { documentFormatting = formattingSupported, codeAction = false },
- root_dir = require("lspconfig").util.root_pattern(".git/", "package.json"),
- filetypes = {
- "vue",
- "javascript",
- "javascriptreact",
- "typescript",
- "typescriptreact",
- "javascript.jsx",
- "typescript.tsx",
- },
- settings = {
- rootMarkers = { ".git/", "package.json" },
- languages = {
- vue = tsserver_args,
- javascript = tsserver_args,
- javascriptreact = tsserver_args,
- ["javascript.jsx"] = tsserver_args,
- typescript = tsserver_args,
- ["typescript.tsx"] = tsserver_args,
- typescriptreact = tsserver_args,
- },
- },
- }
-end
-
-return M
diff --git a/.config/nvim/lua/lsp/tsserver-ls.lua b/.config/nvim/lua/lsp/tsserver-ls.lua
deleted file mode 100644
index c687dfc..0000000
--- a/.config/nvim/lua/lsp/tsserver-ls.lua
+++ /dev/null
@@ -1,83 +0,0 @@
-vim.cmd "let proj = FindRootDirectory()"
-local root_dir = vim.api.nvim_get_var "proj"
-
--- use the global prettier if you didn't find the local one
-local prettier_instance = root_dir .. "/node_modules/.bin/prettier"
-if vim.fn.executable(prettier_instance) ~= 1 then
- prettier_instance = O.lang.tsserver.formatter.exe
-end
-
-O.formatters.filetype["javascriptreact"] = {
- function()
- local args = { "--stdin-filepath", vim.fn.fnameescape(vim.api.nvim_buf_get_name(0)) }
- local extend_args = O.lang.tsserver.formatter.args
-
- if extend_args then
- for i = 1, #extend_args do
- table.insert(args, extend_args[i])
- end
- end
-
- return {
- exe = prettier_instance,
- args = args,
- stdin = true,
- }
- end,
-}
-O.formatters.filetype["javascript"] = O.formatters.filetype["javascriptreact"]
-O.formatters.filetype["typescript"] = O.formatters.filetype["javascriptreact"]
-O.formatters.filetype["typescriptreact"] = O.formatters.filetype["javascriptreact"]
-
-require("formatter.config").set_defaults {
- logging = false,
- filetype = O.formatters.filetype,
-}
-
-if require("utils").check_lsp_client_active "tsserver" then
- return
-end
-
--- npm install -g typescript typescript-language-server
--- require'snippets'.use_suggested_mappings()
--- local capabilities = vim.lsp.protocol.make_client_capabilities()
--- capabilities.textDocument.completion.completionItem.snippetSupport = true;
--- local on_attach_common = function(client)
--- print("LSP Initialized")
--- require'completion'.on_attach(client)
--- require'illuminate'.on_attach(client)
--- end
-
-local on_attach = function(client, bufnr)
- local lsp = require "lsp"
- lsp.common_on_attach(client, bufnr)
- lsp.tsserver_on_attach(client, bufnr)
-end
-
-require("lspconfig").tsserver.setup {
- cmd = {
- DATA_PATH .. "/lspinstall/typescript/node_modules/.bin/typescript-language-server",
- "--stdio",
- },
- filetypes = {
- "javascript",
- "javascriptreact",
- "javascript.jsx",
- "typescript",
- "typescriptreact",
- "typescript.tsx",
- },
- on_attach = on_attach,
- -- This makes sure tsserver is not used for formatting (I prefer prettier)
- settings = { documentFormatting = false },
- handlers = {
- -- ["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
- -- virtual_text = O.lang.tsserver.diagnostics.virtual_text,
- -- signs = O.lang.tsserver.diagnostics.signs,
- -- underline = O.lang.tsserver.diagnostics.underline,
- -- update_in_insert = true,
- -- }),
- },
-}
-
-require("lsp.ts-fmt-lint").setup()