aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2022-12-01 19:36:27 +0100
committerGitHub <noreply@github.com>2022-12-01 19:36:27 +0100
commit05041145c490faad4e64ddd7ab65a7286edfaee1 (patch)
tree65f7e78be8fc4b0ab9315f6ba32225a553b13fb8
parentchore: update generated code (#710) (diff)
downloadmason-05041145c490faad4e64ddd7ab65a7286edfaee1.tar
mason-05041145c490faad4e64ddd7ab65a7286edfaee1.tar.gz
mason-05041145c490faad4e64ddd7ab65a7286edfaee1.tar.bz2
mason-05041145c490faad4e64ddd7ab65a7286edfaee1.tar.lz
mason-05041145c490faad4e64ddd7ab65a7286edfaee1.tar.xz
mason-05041145c490faad4e64ddd7ab65a7286edfaee1.tar.zst
mason-05041145c490faad4e64ddd7ab65a7286edfaee1.zip
feat(ui): hoist "Installing" and "Failed" package groups to the top (#712)
Also improve how logs are displayed.
-rw-r--r--lua/mason-core/managers/npm/init.lua1
-rw-r--r--lua/mason/ui/components/main/package_list.lua86
-rw-r--r--lua/mason/ui/instance.lua77
3 files changed, 90 insertions, 74 deletions
diff --git a/lua/mason-core/managers/npm/init.lua b/lua/mason-core/managers/npm/init.lua
index 96571420..7bfa74b4 100644
--- a/lua/mason-core/managers/npm/init.lua
+++ b/lua/mason-core/managers/npm/init.lua
@@ -20,6 +20,7 @@ local function ensure_npm_root(ctx)
if not (ctx.fs:dir_exists "node_modules" or ctx.fs:file_exists "package.json") then
-- Create a package.json to set a boundary for where npm installs packages.
ctx.spawn.npm { "init", "--yes", "--scope=mason" }
+ ctx.stdio_sink.stdout "Initialized npm root\n"
end
end
diff --git a/lua/mason/ui/components/main/package_list.lua b/lua/mason/ui/components/main/package_list.lua
index 5b4600cf..870fe890 100644
--- a/lua/mason/ui/components/main/package_list.lua
+++ b/lua/mason/ui/components/main/package_list.lua
@@ -5,13 +5,13 @@ local settings = require "mason.settings"
local JsonSchema = require "mason.ui.components.json-schema"
----@param props { state: InstallerUiState, heading: INode, packages: Package[], list_item_renderer: (fun(package: Package): INode), hide_when_empty: boolean }
+---@param props { state: InstallerUiState, heading: INode, packages: Package[], list_item_renderer: (fun(package: Package, state: InstallerUiState): INode), hide_when_empty: boolean }
local function PackageListContainer(props)
local items = {}
for i = 1, #props.packages do
local pkg = props.packages[i]
if props.state.packages.visible[pkg.name] then
- items[#items + 1] = props.list_item_renderer(pkg)
+ items[#items + 1] = props.list_item_renderer(pkg, props.state)
end
end
@@ -189,6 +189,42 @@ local function Installed(state)
}
end
+---@param pkg Package
+---@param state InstallerUiState
+local function InstallingPackageComponent(pkg, state)
+ ---@type UiPackageState
+ local pkg_state = state.packages.states[pkg.name]
+ local current_state = pkg_state.is_terminated and p.Comment " (cancelling)" or p.none ""
+ local tail = pkg_state.short_tailed_output
+ and ("▶ (#" .. #pkg_state.tailed_output .. ") " .. pkg_state.short_tailed_output)
+ or ""
+ return Ui.Node {
+ Ui.HlTextNode {
+ {
+ pkg_state.has_failed and p.error(settings.current.ui.icons.package_uninstalled)
+ or p.highlight(settings.current.ui.icons.package_pending),
+ p.none(" " .. pkg.name),
+ current_state,
+ pkg_state.latest_spawn and p.Comment((" $ %s"):format(pkg_state.latest_spawn)) or p.none "",
+ },
+ },
+ Ui.StickyCursor { id = ("%s-installing"):format(pkg.spec.name) },
+ Ui.Keybind(settings.current.ui.keymaps.cancel_installation, "TERMINATE_PACKAGE_HANDLE", pkg),
+ Ui.Keybind(settings.current.ui.keymaps.install_package, "INSTALL_PACKAGE", pkg),
+ Ui.CascadingStyleNode({ "INDENT" }, {
+ Ui.HlTextNode(pkg_state.is_log_expanded and p.Bold "▼ Displaying full log" or p.muted(tail)),
+ Ui.Keybind("<CR>", "TOGGLE_INSTALL_LOG", pkg),
+ }),
+ Ui.When(pkg_state.is_log_expanded, function()
+ return Ui.CascadingStyleNode({ "INDENT", "INDENT" }, {
+ Ui.HlTextNode(_.map(function(line)
+ return { p.muted(line) }
+ end, pkg_state.tailed_output)),
+ })
+ end),
+ }
+end
+
---@param state InstallerUiState
local function Installing(state)
local packages = state.packages.installing
@@ -202,28 +238,7 @@ local function Installing(state)
hide_when_empty = true,
packages = packages,
---@param pkg Package
- list_item_renderer = function(pkg)
- ---@type UiPackageState
- local pkg_state = state.packages.states[pkg.name]
- local current_state = pkg_state.is_terminated and p.Comment " (cancelling)" or p.none ""
- return Ui.Node {
- Ui.HlTextNode {
- {
- p.highlight(settings.current.ui.icons.package_pending),
- p.none(" " .. pkg.name),
- current_state,
- pkg_state.latest_spawn and p.Comment((" $ %s"):format(pkg_state.latest_spawn)) or p.none "",
- },
- },
- Ui.StickyCursor { id = ("%s-installing"):format(pkg.spec.name) },
- Ui.Keybind(settings.current.ui.keymaps.cancel_installation, "TERMINATE_PACKAGE_HANDLE", pkg),
- Ui.CascadingStyleNode({ "INDENT" }, {
- Ui.HlTextNode(_.map(function(line)
- return { p.muted(line) }
- end, pkg_state.short_tailed_output)),
- }),
- }
- end,
+ list_item_renderer = InstallingPackageComponent,
}
end
@@ -263,24 +278,7 @@ local function Failed(state)
heading = Ui.HlTextNode(p.heading "Failed"),
packages = packages,
---@param pkg Package
- list_item_renderer = function(pkg)
- ---@type UiPackageState
- local pkg_state = state.packages.states[pkg.name]
- return Ui.Node {
- PackageComponent(state, pkg, {
- icon = p.error(settings.current.ui.icons.package_pending),
- keybinds = {
- Ui.Keybind(settings.current.ui.keymaps.install_package, "INSTALL_PACKAGE", pkg),
- },
- sticky = Ui.StickyCursor { id = ("%s-installing"):format(pkg.name) },
- }),
- Ui.CascadingStyleNode({ "INDENT" }, {
- Ui.HlTextNode(_.map(function(line)
- return { p.muted(line) }
- end, pkg_state.tailed_output)),
- }),
- }
- end,
+ list_item_renderer = InstallingPackageComponent,
}
end
@@ -307,10 +305,10 @@ end
---@param state InstallerUiState
return function(state)
return Ui.CascadingStyleNode({ "INDENT" }, {
- Installed(state),
+ Failed(state),
Installing(state),
Queued(state),
- Failed(state),
+ Installed(state),
Uninstalled(state),
})
end
diff --git a/lua/mason/ui/instance.lua b/lua/mason/ui/instance.lua
index 4b2f43e4..c7000bc5 100644
--- a/lua/mason/ui/instance.lua
+++ b/lua/mason/ui/instance.lua
@@ -45,11 +45,13 @@ end
---@field is_checking_new_version boolean
---@field is_checking_version boolean
---@field is_terminated boolean
+---@field is_log_expanded boolean
+---@field has_failed boolean
---@field latest_spawn string?
---@field linked_executables table<string, string>?
---@field lsp_settings_schema table?
---@field new_version NewPackageVersion?
----@field short_tailed_output string[]
+---@field short_tailed_output string?
---@field tailed_output string[]
---@field version string?
@@ -179,6 +181,28 @@ local function mutate_package_visibility(mutate_fn)
end)
end
+---@return UiPackageState
+local function create_initial_package_state()
+ return {
+ expanded_json_schema_keys = {},
+ expanded_json_schemas = {},
+ has_expanded_before = false,
+ has_transitioned = false,
+ is_checking_new_version = false,
+ is_checking_version = false,
+ is_terminated = false,
+ is_log_expanded = false,
+ has_failed = false,
+ latest_spawn = nil,
+ linked_executables = nil,
+ lsp_settings_schema = nil,
+ new_version = nil,
+ short_tailed_output = nil,
+ tailed_output = {},
+ version = nil,
+ }
+end
+
---@param handle InstallHandle
local function setup_handle(handle)
local function handle_state_change()
@@ -199,20 +223,20 @@ local function setup_handle(handle)
---@param chunk string
local function handle_output(chunk)
mutate_state(function(state)
- -- TODO: improve this
local pkg_state = state.packages.states[handle.package.name]
- for idx, line in ipairs(vim.split(chunk, "\n")) do
- if idx == 1 and pkg_state.tailed_output[#pkg_state.tailed_output] then
+ local lines = vim.split(chunk, "\n")
+ for i = 1, #lines do
+ local line = lines[i]
+ if i == 1 and pkg_state.tailed_output[#pkg_state.tailed_output] then
pkg_state.tailed_output[#pkg_state.tailed_output] = pkg_state.tailed_output[#pkg_state.tailed_output]
.. line
else
pkg_state.tailed_output[#pkg_state.tailed_output + 1] = line
end
+ if not line:match "^%s*$" then
+ pkg_state.short_tailed_output = line:gsub("^%s+", "")
+ end
end
- pkg_state.short_tailed_output = {
- pkg_state.tailed_output[#pkg_state.tailed_output - 1] or "",
- pkg_state.tailed_output[#pkg_state.tailed_output] or "",
- }
end)
end
@@ -239,7 +263,8 @@ local function setup_handle(handle)
handle_state_change()
handle_spawnhandle_change()
mutate_state(function(state)
- state.packages.states[handle.package.name].tailed_output = {}
+ state.packages.states[handle.package.name] = create_initial_package_state()
+ state.packages.states[handle.package.name].short_tailed_output = "Installing…"
end)
end
@@ -272,26 +297,6 @@ local function hydrate_detailed_package_state(pkg)
)
end
----@return UiPackageState
-local function create_initial_package_state()
- return {
- expanded_json_schema_keys = {},
- expanded_json_schemas = {},
- has_expanded_before = false,
- has_transitioned = false,
- is_checking_new_version = false,
- is_checking_version = false,
- is_terminated = false,
- latest_spawn = nil,
- linked_executables = nil,
- lsp_settings_schema = nil,
- new_version = nil,
- short_tailed_output = {},
- tailed_output = {},
- version = nil,
- }
-end
-
local help_animation
do
local help_command = ":help"
@@ -543,6 +548,14 @@ local function update_all_packages()
)
end
+local function toggle_install_log(event)
+ ---@type Package
+ local pkg = event.payload
+ mutate_state(function(state)
+ state.packages.states[pkg.name].is_log_expanded = not state.packages.states[pkg.name].is_log_expanded
+ end)
+end
+
local effects = {
["CHECK_NEW_PACKAGE_VERSION"] = a.scope(_.compose(_.partial(pcall, check_new_package_version), _.prop "payload")),
["CHECK_NEW_VISIBLE_PACKAGE_VERSIONS"] = a.scope(check_new_visible_package_versions),
@@ -551,11 +564,12 @@ local effects = {
["INSTALL_PACKAGE"] = install_package,
["LANGUAGE_FILTER"] = filter,
["SET_VIEW"] = set_view,
- ["TERMINATE_PACKAGE_HANDLES"] = terminate_all_package_handles,
["TERMINATE_PACKAGE_HANDLE"] = terminate_package_handle,
+ ["TERMINATE_PACKAGE_HANDLES"] = terminate_all_package_handles,
["TOGGLE_EXPAND_CURRENT_SETTINGS"] = toggle_expand_current_settings,
["TOGGLE_EXPAND_PACKAGE"] = toggle_expand_package,
["TOGGLE_HELP"] = toggle_help,
+ ["TOGGLE_INSTALL_LOG"] = toggle_install_log,
["TOGGLE_JSON_SCHEMA"] = toggle_json_schema,
["TOGGLE_JSON_SCHEMA_KEY"] = toggle_json_schema_keys,
["UNINSTALL_PACKAGE"] = uninstall_package,
@@ -596,6 +610,9 @@ for _, pkg in ipairs(packages) do
mutate_package_grouping(pkg, pkg:is_installed() and "installed" or "uninstalled")
else
mutate_package_grouping(pkg, "failed")
+ mutate_state(function(state)
+ state.packages.states[pkg.name].has_failed = true
+ end)
end
end
)