From e09947a267fb96ce141b1785e8ba29f88b81af29 Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Sat, 14 Dec 2024 09:06:30 -0600 Subject: [PATCH] fix: improve output of `mise tasks` --- src/cli/mod.rs | 2 +- src/cli/tasks/ls.rs | 65 +++++++++++++++------------------------------ src/task/mod.rs | 13 +++++++++ src/ui/style.rs | 14 ---------- src/ui/table.rs | 6 ----- 5 files changed, 36 insertions(+), 64 deletions(-) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 93f83a1ab..f90edb169 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -342,7 +342,7 @@ impl Cli { Ok(cmd) } else { if let Some(task) = self.task { - if Config::get().tasks()?.contains_key(&task) { + if Config::get().tasks()?.iter().any(|(_, t)| t.is_match(&task)) { return Ok(Commands::Run(run::Run { task, args: self.task_args.unwrap_or_default(), diff --git a/src/cli/tasks/ls.rs b/src/cli/tasks/ls.rs index a79b32c47..331f12422 100644 --- a/src/cli/tasks/ls.rs +++ b/src/cli/tasks/ls.rs @@ -1,13 +1,11 @@ -use console::truncate_str; +use comfy_table::{Attribute, Cell, Row}; use eyre::Result; use itertools::Itertools; -use tabled::Tabled; use crate::config::Config; -use crate::file::display_path; +use crate::file::{display_path, display_rel_path}; use crate::task::Task; -use crate::ui::info::trim_line_end_whitespace; -use crate::ui::{style, table}; +use crate::ui::table::MiseTable; /// List available tasks to execute /// These may be included from the config file or from the project's .mise/tasks directory @@ -83,16 +81,18 @@ impl TasksLs { } fn display(&self, tasks: Vec) -> Result<()> { - let rows = tasks.iter().map(|t| t.into()).collect::>(); - let mut table = tabled::Table::new(rows); - table::default_style(&mut table, self.no_header); - // hide columns alias - if !self.extended { - table::disable_columns(&mut table, vec![1]); + let mut table = MiseTable::new( + self.no_header, + if self.extended { + &["Name", "Aliases", "Source", "Description"] + } else { + &["Name", "Description"] + }, + ); + for task in tasks { + table.add_row(self.task_to_row(&task)); } - let table = format!("{table}"); - miseprintln!("{}", trim_line_end_whitespace(&table)); - Ok(()) + table.print() } fn display_usage(&self, tasks: Vec) -> Result<()> { @@ -117,7 +117,7 @@ impl TasksLs { .filter(|t| self.hidden || !t.hide) .map(|task| { let mut inner = serde_json::Map::new(); - inner.insert("name".to_string(), task.name.into()); + inner.insert("name".to_string(), task.display_name().into()); if !task.aliases.is_empty() { inner.insert("aliases".to_string(), task.aliases.join(", ").into()); } @@ -149,39 +149,18 @@ impl TasksLs { _ => cmp, } } -} - -#[derive(Tabled)] -#[tabled(rename_all = "PascalCase")] -struct Row { - name: String, - alias: String, - description: String, - // command: String, - source: String, -} -impl From<&Task> for Row { - fn from(task: &Task) -> Self { - // let cmd = tasks.command_string().unwrap_or_default(); - Self { - name: style::nbold(&task.name).bright().to_string(), - alias: style::ndim(&task.aliases.join(", ")).dim().to_string(), - description: style::nblue(truncate(&task.description, 40)).to_string(), - // command: style::ndim(truncate(&cmd, 20)).dim().to_string(), - source: display_path(&task.config_source), + fn task_to_row(&self, task: &Task) -> Row { + let mut row = vec![Cell::new(task.display_name()).add_attribute(Attribute::Bold)]; + if self.extended { + row.push(Cell::new(task.aliases.join(", "))); + row.push(Cell::new(display_rel_path(&task.config_source))); } + row.push(Cell::new(&task.description).add_attribute(Attribute::Dim)); + row.into() } } -fn first_line(s: &str) -> &str { - s.lines().next().unwrap_or_default() -} - -fn truncate(s: &str, len: usize) -> String { - first_line(&truncate_str(s, len, "…")).to_string() -} - // TODO: fill this out static AFTER_LONG_HELP: &str = color_print::cstr!( r#"Examples: diff --git a/src/task/mod.rs b/src/task/mod.rs index 8656e1e57..e9374f87a 100644 --- a/src/task/mod.rs +++ b/src/task/mod.rs @@ -181,6 +181,19 @@ impl Task { task.render(config_root)?; Ok(task) } + + /// prints the task name without an extension + pub fn display_name(&self) -> String { + self.name.rsplitn(2, '.').last().unwrap_or_default().to_string() + } + + pub fn is_match(&self, pat: &str) -> bool { + if self.name == pat || self.aliases.contains(&pat.to_string()) { + return true; + } + let pat = pat.rsplitn(2, '.').last().unwrap_or_default(); + self.name == pat || self.aliases.contains(&pat.to_string()) + } pub fn task_dir() -> PathBuf { let config = Config::get(); diff --git a/src/ui/style.rs b/src/ui/style.rs index 064c28521..2136e22c7 100644 --- a/src/ui/style.rs +++ b/src/ui/style.rs @@ -1,6 +1,5 @@ use std::path::Path; -use crate::env::TERM_WIDTH; use crate::file::display_path; use console::{style, StyledObject}; @@ -64,18 +63,10 @@ pub fn nstyle(val: D) -> StyledObject { style(val).for_stdout() } -pub fn nblue(val: D) -> StyledObject { - nstyle(val).blue() -} - pub fn ncyan(val: D) -> StyledObject { nstyle(val).cyan() } -pub fn nbold(val: D) -> StyledObject { - nstyle(val).bold() -} - pub fn nunderline(val: D) -> StyledObject { nstyle(val).underlined() } @@ -91,8 +82,3 @@ pub fn nred(val: D) -> StyledObject { pub fn ndim(val: D) -> StyledObject { nstyle(val).dim() } - -#[allow(unused)] -pub fn truncate_str(s: impl AsRef) -> String { - console::truncate_str(s.as_ref(), *TERM_WIDTH - 14, "…").to_string() -} diff --git a/src/ui/table.rs b/src/ui/table.rs index cae462b4c..a4b0a4d4f 100644 --- a/src/ui/table.rs +++ b/src/ui/table.rs @@ -41,12 +41,6 @@ pub fn default_style(table: &mut Table, no_headers: bool) { .with(Modify::new(Columns::last()).with(Padding::zero())); } -pub fn disable_columns(table: &mut Table, col_idxs: Vec) { - for idx in col_idxs { - table.with(Remove::column(Columns::single(idx))); - } -} - pub struct MiseTable { table: comfy_table::Table, truncate: bool,