local configs = require "lspconfig/configs" local lspui = require "lspconfig/_lspui" return function() -- These options need to be cached before switching to the floating -- buffer. local buf_clients = vim.lsp.buf_get_clients() local clients = vim.lsp.get_active_clients() local buffer_filetype = vim.bo.filetype local buffer_dir = vim.fn.expand "%:p:h" local win_info = lspui.percentage_range_window(0.8, 0.7) local bufnr, win_id = win_info.bufnr, win_info.win_id local buf_lines = {} local buf_client_names = {} for _, client in pairs(buf_clients) do table.insert(buf_client_names, client.name) end local header = { "Configured servers: " .. table.concat(vim.tbl_keys(configs), ", "), "Neovim logs at: " .. (vim.lsp.get_log_path()), "", tostring(#vim.tbl_keys(buf_clients)) .. " client(s) attached to this buffer: " .. table.concat( buf_client_names, ", " ), } vim.list_extend(buf_lines, header) local function trim_whitespace(cmd) local trimmed_cmd = {} for _, str in pairs(cmd) do table.insert(trimmed_cmd, str:match "^%s*(.*)") end return trimmed_cmd end local function remove_newlines(cmd) cmd = trim_whitespace(cmd) cmd = table.concat(cmd, " ") cmd = vim.split(cmd, "\n") cmd = trim_whitespace(cmd) cmd = table.concat(cmd, " ") return cmd end local indent = " " local function make_client_info(client) local server_specific_info = "" if client.config.lspinfo then server_specific_info = client.config.lspinfo(client.config) end return { "", indent .. "Client: " .. client.name .. " (id " .. tostring(client.id) .. ")", indent .. "\troot: " .. client.workspaceFolders[1].name, indent .. "\tfiletypes: " .. table.concat(client.config.filetypes or {}, ", "), indent .. "\tcmd: " .. remove_newlines(client.config.cmd), indent .. "\t" .. server_specific_info, "", } end for _, client in pairs(buf_clients) do local client_info = make_client_info(client) vim.list_extend(buf_lines, client_info) end local active_section_header = { "", tostring(#clients) .. " active client(s): ", } vim.list_extend(buf_lines, active_section_header) for _, client in pairs(clients) do local client_info = make_client_info(client) vim.list_extend(buf_lines, client_info) end local matching_config_header = { "", "Clients that match the filetype " .. buffer_filetype .. ":", } local cmd_not_found_msg = "False. Please check your path and ensure the server is installed" vim.list_extend(buf_lines, matching_config_header) for _, config in pairs(configs) do local cmd_is_executable, cmd if config.cmd then cmd = remove_newlines(config.cmd) if vim.fn.executable(config.cmd[1]) == 1 then cmd_is_executable = "True" else cmd_is_executable = cmd_not_found_msg end else cmd = "cmd not defined" cmd_is_executable = cmd end if config.filetypes then for _, filetype_match in pairs(config.filetypes) do if buffer_filetype == filetype_match then local matching_config_info = { indent .. "", indent .. "Config: " .. config.name, indent .. "\tcmd: " .. cmd, indent .. "\tcmd is executable: " .. cmd_is_executable, indent .. "\tidentified root: " .. (config.get_root_dir(buffer_dir) or "None"), indent .. "\tcustom handlers: " .. table.concat(vim.tbl_keys(config.handlers), ", "), } vim.list_extend(buf_lines, matching_config_info) end end else local matching_config_info = { "", "Config: " .. config.name, "\tfiletype: " .. "No filetypes defined, please define filetypes in setup().", } vim.list_extend(buf_lines, matching_config_info) end end buf_lines = vim.lsp.util._trim(buf_lines, {}) vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, buf_lines) vim.api.nvim_buf_set_option(bufnr, "modifiable", false) vim.api.nvim_buf_set_option(bufnr, "filetype", "lspinfo") local configs_pattern = "\\%(" .. table.concat(vim.tbl_keys(configs), "\\|") .. "\\)" vim.cmd("syntax match Title /\\%(Client\\|Config\\):.*\\zs" .. configs_pattern .. "/") vim.cmd("syntax match Identifier /filetypes:.*\\zs\\<" .. buffer_filetype .. "\\>/") vim.fn.matchadd( "Error", "No filetypes defined, please define filetypes in setup().\\|" .. "cmd not defined\\|" .. cmd_not_found_msg ) vim.api.nvim_buf_set_keymap(bufnr, "n", "", "bd", { noremap = true }) vim.lsp.util.close_preview_autocmd({ "BufHidden", "BufLeave" }, win_id) end