aboutsummaryrefslogtreecommitdiffstats
path: root/lua/nvim-lsp-installer/ui/status-win/init.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/nvim-lsp-installer/ui/status-win/init.lua')
-rw-r--r--lua/nvim-lsp-installer/ui/status-win/init.lua109
1 files changed, 82 insertions, 27 deletions
diff --git a/lua/nvim-lsp-installer/ui/status-win/init.lua b/lua/nvim-lsp-installer/ui/status-win/init.lua
index 3eb7b206..1e4ffab3 100644
--- a/lua/nvim-lsp-installer/ui/status-win/init.lua
+++ b/lua/nvim-lsp-installer/ui/status-win/init.lua
@@ -11,6 +11,7 @@ local HELP_KEYMAP = "?"
local CLOSE_WINDOW_KEYMAP_1 = "<Esc>"
local CLOSE_WINDOW_KEYMAP_2 = "q"
+---@param props {title: string, count: number}
local function ServerGroupHeading(props)
return Ui.HlTextNode {
{ { props.title, props.highlight or "LspInstallerHeading" }, { (" (%d)"):format(props.count), "Comment" } },
@@ -18,10 +19,12 @@ local function ServerGroupHeading(props)
end
local function Indent(children)
- return Ui.CascadingStyleNode({ Ui.CascadingStyle.INDENT }, children)
+ return Ui.CascadingStyleNode({ "INDENT" }, children)
end
-local create_vader = Data.memoize(function(saber_ticks)
+local create_vader = Data.memoize(
+ ---@param saber_ticks number
+ function(saber_ticks)
-- stylua: ignore start
return {
{ { [[ _______________________________________________________________________ ]], "LspInstallerMuted" } },
@@ -37,9 +40,12 @@ local create_vader = Data.memoize(function(saber_ticks)
{ { [[ Cowth Vader (alleged Neovim user) ]], "LspInstallerMuted" } },
{ { [[ ]], "LspInstallerMuted" } },
}
- -- stylua: ignore end
-end)
+ -- stylua: ignore end
+ end
+)
+---@param is_current_settings_expanded boolean
+---@param vader_saber_ticks number
local function Help(is_current_settings_expanded, vader_saber_ticks)
local keymap_tuples = {
{ "Toggle help", HELP_KEYMAP },
@@ -108,8 +114,9 @@ local function Help(is_current_settings_expanded, vader_saber_ticks)
}
end
+---@param props {is_showing_help: boolean, help_command_text: string}
local function Header(props)
- return Ui.CascadingStyleNode({ Ui.CascadingStyle.CENTERED }, {
+ return Ui.CascadingStyleNode({ "CENTERED" }, {
Ui.HlTextNode {
{
{ props.is_showing_help and props.help_command_text or "", "LspInstallerHighlighted" },
@@ -139,6 +146,7 @@ local Seconds = {
YEAR = 29030400, -- 60 * 60 * 24 * 7 * 4 * 12
}
+---@param time number
local function get_relative_install_time(time)
local now = os.time()
local delta = math.max(now - time, 0)
@@ -157,6 +165,7 @@ local function get_relative_install_time(time)
end
end
+---@param server ServerState
local function ServerMetadata(server)
return Ui.Node(Data.list_not_nil(
Data.lazy(server.is_installed and server.deprecated, function()
@@ -202,6 +211,8 @@ local function ServerMetadata(server)
))
end
+---@param servers ServerState[]
+---@param props ServerGroupProps
local function InstalledServers(servers, props)
return Ui.Node(Data.list_map(function(server)
local is_expanded = props.expanded_server == server.name
@@ -225,12 +236,15 @@ local function InstalledServers(servers, props)
end, servers))
end
+---@param server ServerState
local function TailedOutput(server)
return Ui.HlTextNode(Data.list_map(function(line)
return { { line, "LspInstallerMuted" } }
end, server.installer.tailed_output))
end
+---@param output string[]
+---@return string
local function get_last_non_empty_line(output)
for i = #output, 1, -1 do
local line = output[i]
@@ -241,8 +255,11 @@ local function get_last_non_empty_line(output)
return ""
end
+---@param servers ServerState[]
local function PendingServers(servers)
- return Ui.Node(Data.list_map(function(server)
+ return Ui.Node(Data.list_map(function(_server)
+ ---@type ServerState
+ local server = _server
local has_failed = server.installer.has_run or server.uninstaller.has_run
local note = has_failed and "(failed)" or (server.installer.is_queued and "(queued)" or "(installing)")
return Ui.Node {
@@ -274,6 +291,8 @@ local function PendingServers(servers)
end, servers))
end
+---@param servers ServerState[]
+---@param props ServerGroupProps
local function UninstalledServers(servers, props)
return Ui.Node(Data.list_map(function(server)
local is_prioritized = props.prioritized_servers[server.name]
@@ -301,6 +320,9 @@ local function UninstalledServers(servers, props)
end, servers))
end
+---@alias ServerGroupProps {title: string, hide_when_empty: boolean|nil, servers: ServerState[][], expanded_server: string|nil, renderer: fun(servers: ServerState[], props: ServerGroupProps)}
+
+---@param props ServerGroupProps
local function ServerGroup(props)
local total_server_count = 0
local chunks = props.servers
@@ -323,6 +345,9 @@ local function ServerGroup(props)
end)
end
+---@param servers table<string, ServerState>
+---@param expanded_server string|nil
+---@param prioritized_servers string[]
local function Servers(servers, expanded_server, prioritized_servers)
local grouped_servers = {
installed = {},
@@ -398,8 +423,10 @@ local function Servers(servers, expanded_server, prioritized_servers)
}
end
+---@param server Server
local function create_initial_server_state(server)
- return {
+ ---@class ServerState
+ local server_state = {
name = server.name,
is_installed = server:is_installed(),
deprecated = server.deprecated,
@@ -415,8 +442,12 @@ local function create_initial_server_state(server)
has_run = false,
tailed_output = { "" },
},
- uninstaller = { has_run = false, error = nil },
+ uninstaller = {
+ has_run = false,
+ error = nil,
+ },
}
+ return server_state
end
local function normalize_chunks_line_endings(chunk, dest)
@@ -430,39 +461,53 @@ end
local function init(all_servers)
local window = display.new_view_only_win "LSP servers"
- window.view(function(state)
- return Indent {
- Ui.Keybind(HELP_KEYMAP, "TOGGLE_HELP", nil, true),
- Ui.Keybind(CLOSE_WINDOW_KEYMAP_1, "CLOSE_WINDOW", nil, true),
- Ui.Keybind(CLOSE_WINDOW_KEYMAP_2, "CLOSE_WINDOW", nil, true),
- Header {
- is_showing_help = state.is_showing_help,
- help_command_text = state.help_command_text,
- },
- Ui.When(state.is_showing_help, function()
- return Help(state.is_current_settings_expanded, state.vader_saber_ticks)
- end),
- Ui.When(not state.is_showing_help, function()
- return Servers(state.servers, state.expanded_server, state.prioritized_servers)
- end),
- }
- end)
+ window.view(
+ --- @param state StatusWinState
+ function(state)
+ return Indent {
+ Ui.Keybind(HELP_KEYMAP, "TOGGLE_HELP", nil, true),
+ Ui.Keybind(CLOSE_WINDOW_KEYMAP_1, "CLOSE_WINDOW", nil, true),
+ Ui.Keybind(CLOSE_WINDOW_KEYMAP_2, "CLOSE_WINDOW", nil, true),
+ Header {
+ is_showing_help = state.is_showing_help,
+ help_command_text = state.help_command_text,
+ },
+ Ui.When(state.is_showing_help, function()
+ return Help(state.is_current_settings_expanded, state.vader_saber_ticks)
+ end),
+ Ui.When(not state.is_showing_help, function()
+ return Servers(state.servers, state.expanded_server, state.prioritized_servers)
+ end),
+ }
+ end
+ )
+ ---@type table<string, ServerState>
local servers = {}
for i = 1, #all_servers do
local server = all_servers[i]
servers[server.name] = create_initial_server_state(server)
end
- local mutate_state, get_state = window.init {
+ ---@class StatusWinState
+ ---@field prioritized_servers string[]
+ local initial_state = {
servers = servers,
is_showing_help = false,
+ is_current_settings_expanded = false,
prioritized_servers = {},
expanded_server = nil,
help_command_text = "", -- for "animating" the ":help" text when toggling the help window
vader_saber_ticks = 0, -- for "animating" the cowthvader lightsaber
}
+ local mutate_state_generic, get_state_generic = window.init(initial_state)
+ -- Generics don't really work with higher-order functions so we cast it here.
+ ---@type fun(mutate_fn: fun(current_state: StatusWinState))
+ local mutate_state = mutate_state_generic
+ ---@type fun(): StatusWinState
+ local get_state = get_state_generic
+
-- TODO: memoize or throttle.. or cache. Do something. Also, as opposed to what the naming currently suggests, this
-- is not really doing anything async stuff, but will very likely do so in the future :tm:.
local async_populate_server_metadata = vim.schedule_wrap(function(server_name)
@@ -488,8 +533,12 @@ local function init(all_servers)
end)
end
+ ---@alias ServerInstallTuple {[1]:Server, [2]: string|nil}
+
+ ---@param server_tuple ServerInstallTuple
+ ---@param on_complete fun()
local function start_install(server_tuple, on_complete)
- local server, requested_version = unpack(server_tuple)
+ local server, requested_version = server_tuple[1], server_tuple[2]
mutate_state(function(state)
state.servers[server.name].installer.is_queued = false
state.servers[server.name].installer.is_running = true
@@ -533,6 +582,7 @@ local function init(all_servers)
local queue
do
local max_running = settings.current.max_concurrent_installers
+ ---@type ServerInstallTuple[]
local q = {}
local r = 0
@@ -548,12 +598,16 @@ local function init(all_servers)
end
end)
+ ---@param server Server
+ ---@param version string|nil
queue = function(server, version)
q[#q + 1] = { server, version }
check_queue()
end
end
+ ---@param server Server
+ ---@param version string|nil
local function install_server(server, version)
log.debug("Installing server", server, version)
local server_state = get_state().servers[server.name]
@@ -569,6 +623,7 @@ local function init(all_servers)
queue(server, version)
end
+ ---@param server Server
local function uninstall_server(server)
local server_state = get_state().servers[server.name]
if server_state and (server_state.installer.is_running or server_state.installer.is_queued) then