diff options
| -rw-r--r-- | lua/core/info.lua | 180 | ||||
| -rw-r--r-- | lua/core/which-key.lua | 4 | ||||
| -rw-r--r-- | lua/lsp/init.lua | 30 | ||||
| -rw-r--r-- | lua/lsp/null-ls.lua | 26 | ||||
| -rw-r--r-- | lua/utils/init.lua | 28 | 
5 files changed, 268 insertions, 0 deletions
| diff --git a/lua/core/info.lua b/lua/core/info.lua new file mode 100644 index 00000000..7f8a0a33 --- /dev/null +++ b/lua/core/info.lua @@ -0,0 +1,180 @@ +local M = {} +local u = require "utils" +local null_ls_handler = require "lsp.null-ls" +local indent = "  " + +M.banner = { +  "", +  "", +  "⠀⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀   ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀  ⠀⠀     ⠀⠀⠀   ⠀⠀ ⣺⡿⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀", +  "⠀⣿⠇⠀⠀⠀⠀⠀⣤⡄⠀⠀⢠⣤⡄⠀.⣠⣤⣤⣤⡀⠀⠀⢀⣤⣤⣤⣤⡄⠀⠀⠀⣤⣄⣤⣤⣤⠀⠀ ⣿⣯  ⣿⡟⠀   ⣤⣤⠀⠀⠀⠀⣠⣤⣤⣤⣄⣤⣤", +  "⢠⣿⠀⠀⠀⠀⠀⠀⣿⠃⠀⠀⣸⣿⠁⠀⣿⣿⠉⠀⠈⣿⡇⠀⠀⠛⠋⠀⠀⢹⣿⠀⠀⠀⣿⠏⠀⠸⠿⠃⠀⣿⣿⠀⣰⡟⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⣿⡟⢸⣿⡇⢀⣿", +  "⣸⡇⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⣿⡟⠀⢠⣿⡇⠀⠀⢰⣿⡇⠀⣰⣾⠟⠛⠛⣻⡇⠀⠀⢸⡿⠀⠀⠀⠀⠀⠀⢻⣿⢰⣿⠀⠀⠀⠀⠀⠀⣾⡇⠀⠀⠀⢸⣿⠇⢸⣿⠀⢸⡏", +  "⣿⣧⣤⣤⣤⡄⠀⠘⣿⣤⣤⡤⣿⠇⠀⢸⣿⠁⠀⠀⣼⣿⠀⠀⢿⣿⣤⣤⠔⣿⠃⠀⠀⣾⡇⠀⠀⠀⠀⠀⠀⢸⣿⣿⠋⠀⠀⠀⢠⣤⣤⣿⣥⣤⡄⠀⣼⣿⠀⣸⡏⠀⣿⠃", +  "⠉⠉⠉⠉⠉⠁⠀⠀⠈⠉⠉⠀⠉⠀⠀⠈⠉⠀⠀⠀⠉⠉⠀⠀⠀⠉⠉⠁⠈⠉⠀⠀⠀⠉⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠀⠀⠀⠀⠈⠉⠉⠉⠉⠉⠁⠀⠉⠁⠀⠉⠁⠀⠉⠀", +  "", +  "", +} + +local function str_list(list) +  return "[ " .. table.concat(list, ", ") .. " ]" +end + +local function get_formatter_suggestion_msg(ft) +  local supported_formatters = u.get_supported_formatters_by_filetype(ft) +  return { +    "-------------------------------------------------------------------", +    "", +    "  HINT ", +    "", +    indent .. "* List of supported formatters: " .. str_list(supported_formatters), +    "", +    indent .. "You can enable a supported formatter by adding this to your config.lua", +    "", +    indent +      .. "lvim.lang." +      .. tostring(ft) +      .. [[.formatting = { { exe = ']] +      .. table.concat(supported_formatters, "|") +      .. [[' } }]], +    "", +    "-------------------------------------------------------------------", +  } +end + +local function get_linter_suggestion_msg(ft) +  local supported_linters = u.get_supported_linters_by_filetype(ft) +  return { +    "-------------------------------------------------------------------", +    "", +    "  HINT ", +    "", +    indent .. "* List of supported linters: " .. str_list(supported_linters), +    "", +    indent .. "You can enable a supported linter by adding this to your config.lua", +    "", +    indent +      .. "lvim.lang." +      .. tostring(ft) +      .. [[.linters = { { exe = ']] +      .. table.concat(supported_linters, "|") +      .. [[' } }]], +    "", +    "-------------------------------------------------------------------", +  } +end + +---creates an average size popup +---@param buf_lines a list of lines to print +---@param callback could be used to set syntax highlighting rules for example +---@return bufnr buffer number of the created buffer +---@return win_id window ID of the created popup +function M.create_simple_popup(buf_lines, callback) +  -- runtime/lua/vim/lsp/util.lua +  local bufnr = vim.api.nvim_create_buf(false, true) +  local height_percentage = 0.7 +  local width_percentage = 0.8 +  local row_start_percentage = (1 - height_percentage) / 2 +  local col_start_percentage = (1 - width_percentage) / 2 +  local opts = {} +  opts.relative = "editor" +  opts.height = math.ceil(vim.o.lines * height_percentage) +  opts.row = math.ceil(vim.o.lines * row_start_percentage) +  opts.col = math.floor(vim.o.columns * col_start_percentage) +  opts.width = math.floor(vim.o.columns * width_percentage) +  opts.border = { +    "┌", +    "-", +    "┐", +    "|", +    "┘", +    "-", +    "└", +    "|", +  } + +  local win_id = vim.api.nvim_open_win(bufnr, true, opts) + +  vim.api.nvim_win_set_buf(win_id, bufnr) +  -- this needs to be window option! +  vim.api.nvim_win_set_option(win_id, "number", false) +  vim.cmd "setlocal nocursorcolumn" +  vim.cmd "setlocal wrap" +  -- set buffer options +  vim.api.nvim_buf_set_option(bufnr, "filetype", "lspinfo") +  vim.lsp.util.close_preview_autocmd({ "BufHidden", "BufLeave" }, win_id) +  buf_lines = vim.lsp.util._trim(buf_lines, {}) +  vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, buf_lines) +  vim.api.nvim_buf_set_option(bufnr, "modifiable", false) +  if type(callback) == "function" then +    callback() +  end +  return bufnr, win_id +end + +function M.toggle_popup(ft) +  local client = u.get_active_client_by_ft(ft) +  local is_client_active = not client.is_stopped() +  local client_enabled_caps = require("lsp").get_ls_capabilities(client.id) +  local num_caps = vim.tbl_count(client_enabled_caps) +  local null_ls_providers = null_ls_handler.get_registered_providers_by_filetype(ft) + +  local missing_linters = lvim.lang[ft].linters._failed_requests or {} +  local missing_formatters = lvim.lang[ft].formatters._failed_requests or {} + +  local buf_lines = {} +  vim.list_extend(buf_lines, M.banner) + +  local header = { +    "Detected filetype is: " .. tostring(ft), +    "", +    "Treesitter active: " .. tostring(next(vim.treesitter.highlighter.active) ~= nil), +    "", +    "", +  } +  vim.list_extend(buf_lines, header) + +  local lsp_info = { +    "Associated language-server: " .. client.name, +    indent .. "* Active: " .. tostring(is_client_active) .. ", id: " .. tostring(client.id), +    indent .. "* Formatting support: " .. tostring(client.resolved_capabilities.document_formatting), +    indent .. "* Capabilities list: " .. table.concat(vim.list_slice(client_enabled_caps, 1, num_caps / 2), ", "), +    indent .. indent .. indent .. table.concat(vim.list_slice(client_enabled_caps, ((num_caps / 2) + 1)), ", "), +    "", +  } +  vim.list_extend(buf_lines, lsp_info) + +  local null_ls_info = { +    "Configured providers: " .. table.concat(null_ls_providers, "  , ") .. "  ", +    "", +  } +  vim.list_extend(buf_lines, null_ls_info) + +  local missing_formatters_status +  if vim.tbl_count(missing_formatters) > 0 then +    missing_formatters_status = { "Missing formatters: " .. table.concat(missing_formatters, "  , ") .. "  ", "" } +    vim.list_extend(buf_lines, missing_formatters_status) +  end + +  local missing_linters_status +  if vim.tbl_count(missing_linters) > 0 then +    missing_linters_status = { "Missing linters: " .. table.concat(missing_linters, "  , ") .. "  ", "" } +    vim.list_extend(buf_lines, missing_linters_status) +  end + +  vim.list_extend(buf_lines, get_formatter_suggestion_msg(ft)) + +  vim.list_extend(buf_lines, get_linter_suggestion_msg(ft)) + +  local function set_syntax_hl() +    --TODO: highlighting is either inconsistent or not working :\ +    vim.cmd("syntax match Identifier /filetype is: .*\\zs\\<" .. ft .. "\\>/") +    vim.cmd("syntax match Identifier /server: .*\\zs\\<" .. client.name .. "\\>/") +    vim.cmd("syntax match Identifier /providers: .*\\zs\\<" .. table.concat(null_ls_providers, ", ") .. "\\>/") +    vim.cmd("syntax match Identifier /formatters: .*\\zs\\<" .. table.concat(missing_formatters, ", ") .. "\\>/") +    vim.cmd("syntax match Identifier /linters: .*\\zs\\<" .. table.concat(missing_linters, ", ") .. "\\>/") +  end + +  return M.create_simple_popup(buf_lines, set_syntax_hl) +end +return M diff --git a/lua/core/which-key.lua b/lua/core/which-key.lua index 6e0cbd8e..268243e4 100644 --- a/lua/core/which-key.lua +++ b/lua/core/which-key.lua @@ -169,6 +169,10 @@ M.config = function()        L = {          name = "+LunarVim",          k = { "<cmd>lua require('keymappings').print()<cr>", "View LunarVim's default keymappings" }, +        i = { +          "<cmd>lua require('core.info').toggle_popup(vim.bo.filetype)<cr>", +          "Toggle LunarVim Info", +        },        },        s = { diff --git a/lua/lsp/init.lua b/lua/lsp/init.lua index a219fb1b..29676214 100644 --- a/lua/lsp/init.lua +++ b/lua/lsp/init.lua @@ -64,6 +64,36 @@ 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 +      -- print("got cap: ", vim.inspect(caps)) +      table.insert(enabled_caps, k) +      -- vim.list_extend(enabled_caps, cap) +    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) diff --git a/lua/lsp/null-ls.lua b/lua/lsp/null-ls.lua index 7adfa218..19727e15 100644 --- a/lua/lsp/null-ls.lua +++ b/lua/lsp/null-ls.lua @@ -23,6 +23,26 @@ function M.get_registered_providers_by_filetype(ft)    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 lvim.lang[ft][operation]._failed_requests then +    lvim.lang[ft][operation]._failed_requests = {} +  end +  table.insert(lvim.lang[ft][operation]._failed_requests, provider) +end +  local function validate_nodejs_provider(provider)    local command_path    local root_dir @@ -80,6 +100,9 @@ function M.setup(filetype)          builtin_formatter._opts.command = resolved_path          table.insert(M.requested_providers, builtin_formatter)          u.lvim_log(string.format("Using format provider: [%s]", builtin_formatter.name)) +      else +        -- mark it here to avoid re-doing the lookup again +        register_failed_request(filetype, formatter.exe, "formatters")        end      end    end @@ -101,6 +124,9 @@ function M.setup(filetype)          builtin_diagnoser._opts.command = resolved_path          table.insert(M.requested_providers, builtin_diagnoser)          u.lvim_log(string.format("Using linter provider: [%s]", builtin_diagnoser.name)) +      else +        -- mark it here to avoid re-doing the lookup again +        register_failed_request(filetype, linter.exe, "linters")        end      end    end diff --git a/lua/utils/init.lua b/lua/utils/init.lua index 16ad5e4a..df472c66 100644 --- a/lua/utils/init.lua +++ b/lua/utils/init.lua @@ -113,6 +113,34 @@ function utils.get_active_client_by_ft(filetype)    return nil  end +-- TODO: consider porting this logic to null-ls instead +function utils.get_supported_linters_by_filetype(filetype) +  local null_ls = require "null-ls" +  local matches = {} +  for _, provider in pairs(null_ls.builtins.diagnostics) do +    if vim.tbl_contains(provider.filetypes, filetype) then +      local provider_name = provider.name + +      table.insert(matches, provider_name) +    end +  end + +  return matches +end + +function utils.get_supported_formatters_by_filetype(filetype) +  local null_ls = require "null-ls" +  local matches = {} +  for _, provider in pairs(null_ls.builtins.formatting) do +    if provider.filetypes and vim.tbl_contains(provider.filetypes, filetype) then +      -- table.insert(matches, { provider.name, ft }) +      table.insert(matches, provider.name) +    end +  end + +  return matches +end +  function utils.unrequire(m)    package.loaded[m] = nil    _G[m] = nil | 
