mirror of
https://github.com/nukesor/pueue
synced 2024-10-07 00:09:10 +00:00
refactor: Add TableBuilder
This commit is contained in:
parent
b0e6c35ebc
commit
196d5bec09
24
Cargo.lock
generated
24
Cargo.lock
generated
|
@ -885,9 +885,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.3.0"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b0560d531d1febc25a3c9398a62a71256c0178f2e3443baedd9ad4bb8c9deb4"
|
||||
checksum = "cb779fcf4bb850fbbb0edc96ff6cf34fd90c4b1a112ce042653280d9a7364048"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"ucd-trie",
|
||||
|
@ -895,9 +895,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.3.0"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "905708f7f674518498c1f8d644481440f476d39ca6ecae83319bba7c6c12da91"
|
||||
checksum = "502b62a6d0245378b04ffe0a7fb4f4419a4815fce813bd8a0ec89a56e07d67b1"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
|
@ -905,9 +905,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.3.0"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5803d8284a629cc999094ecd630f55e91b561a1d1ba75e233b00ae13b91a69ad"
|
||||
checksum = "451e629bf49b750254da26132f1a5a9d11fd8a95a3df51d15c4abd1ba154cb6c"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
|
@ -918,13 +918,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.3.0"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1538eb784f07615c6d9a8ab061089c6c54a344c5b4301db51990ca1c241e8c04"
|
||||
checksum = "bcec162c71c45e269dfc3fc2916eaeb97feab22993a21bcce4721d08cd7801a6"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"pest",
|
||||
"sha-1",
|
||||
"sha1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1425,10 +1425,10 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.10.0"
|
||||
name = "sha1"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
|
||||
checksum = "006769ba83e921b3085caa8334186b00cf92b4cb1a6cf4632fbccc8eff5c7549"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
|
|
|
@ -1,30 +1,8 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use pueue_lib::task::{Task, TaskStatus};
|
||||
use chrono::Local;
|
||||
|
||||
/// This is a helper function for working with tables when calling `pueue status`.
|
||||
///
|
||||
/// By default, several columns aren't shown until there's at least one task with relevant data.
|
||||
/// This function determines whether any of those columns should be shown.
|
||||
pub fn has_special_columns(tasks: &[Task]) -> (bool, bool, bool) {
|
||||
// Check whether there are any delayed tasks.
|
||||
let has_delayed_tasks = tasks.iter().any(|task| {
|
||||
matches!(
|
||||
task.status,
|
||||
TaskStatus::Stashed {
|
||||
enqueue_at: Some(_)
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
// Check whether there are any tasks with dependencies.
|
||||
let has_dependencies = tasks.iter().any(|task| !task.dependencies.is_empty());
|
||||
|
||||
// Check whether there are any tasks a label.
|
||||
let has_labels = tasks.iter().any(|task| task.label.is_some());
|
||||
|
||||
(has_delayed_tasks, has_dependencies, has_labels)
|
||||
}
|
||||
use pueue_lib::{settings::Settings, task::Task};
|
||||
|
||||
/// Sort given tasks by their groups.
|
||||
/// This is needed to print a table for each group.
|
||||
|
@ -40,3 +18,50 @@ pub fn sort_tasks_by_group(tasks: Vec<Task>) -> BTreeMap<String, Vec<Task>> {
|
|||
|
||||
sorted_task_groups
|
||||
}
|
||||
|
||||
/// Returns the formatted `start` and `end` text for a given task.
|
||||
///
|
||||
/// 1. If the start || end is today, skip the date.
|
||||
/// 2. Otherwise show the date in both.
|
||||
///
|
||||
/// If the task doesn't have a start and/or end yet, an empty string will be returned
|
||||
/// for the respective field.
|
||||
pub fn formatted_start_end(task: &Task, settings: &Settings) -> (String, String) {
|
||||
// Get the start time.
|
||||
// If the task didn't start yet, just return two empty strings.
|
||||
let start = match task.start {
|
||||
Some(start) => start,
|
||||
None => return ("".into(), "".into()),
|
||||
};
|
||||
|
||||
// If the task started today, just show the time.
|
||||
// Otherwise show the full date and time.
|
||||
let started_today = start >= Local::today().and_hms(0, 0, 0);
|
||||
let formatted_start = if started_today {
|
||||
start
|
||||
.format(&settings.client.status_time_format)
|
||||
.to_string()
|
||||
} else {
|
||||
start
|
||||
.format(&settings.client.status_datetime_format)
|
||||
.to_string()
|
||||
};
|
||||
|
||||
// Get finish time, if already set. Otherwise only return the formatted start.
|
||||
let end = match task.end {
|
||||
Some(end) => end,
|
||||
None => return (formatted_start, "".into()),
|
||||
};
|
||||
|
||||
// If the task ended today we only show the time.
|
||||
// In all other circumstances, we show the full date.
|
||||
let finished_today = end >= Local::today().and_hms(0, 0, 0);
|
||||
let formatted_end = if finished_today {
|
||||
end.format(&settings.client.status_time_format).to_string()
|
||||
} else {
|
||||
end.format(&settings.client.status_datetime_format)
|
||||
.to_string()
|
||||
};
|
||||
|
||||
(formatted_start, formatted_end)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ pub mod helper;
|
|||
mod log;
|
||||
mod state;
|
||||
pub mod style;
|
||||
mod table_builder;
|
||||
|
||||
use crossterm::style::Color;
|
||||
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
use std::string::ToString;
|
||||
|
||||
use chrono::{Duration, Local};
|
||||
use comfy_table::presets::UTF8_HORIZONTAL_ONLY;
|
||||
use comfy_table::*;
|
||||
|
||||
use pueue_lib::settings::Settings;
|
||||
use pueue_lib::state::{State, PUEUE_DEFAULT_GROUP};
|
||||
use pueue_lib::task::{Task, TaskResult, TaskStatus};
|
||||
use pueue_lib::task::Task;
|
||||
|
||||
use super::{helper::*, OutputStyle};
|
||||
use super::{helper::*, table_builder::TableBuilder, OutputStyle};
|
||||
use crate::cli::SubCommand;
|
||||
use crate::display::group::get_group_headline;
|
||||
|
||||
|
@ -17,12 +11,12 @@ use crate::display::group::get_group_headline;
|
|||
///
|
||||
/// We pass the tasks as a separate parameter and as a list.
|
||||
/// This allows us to print the tasks in any user-defined order.
|
||||
pub fn print_state(
|
||||
pub fn print_state<'a>(
|
||||
state: State,
|
||||
tasks: Vec<Task>,
|
||||
cli_command: &SubCommand,
|
||||
style: &OutputStyle,
|
||||
settings: &Settings,
|
||||
style: &'a OutputStyle,
|
||||
settings: &'a Settings,
|
||||
) {
|
||||
let (json, group_only) = match cli_command {
|
||||
SubCommand::Status { json, group } => (*json, group.clone()),
|
||||
|
@ -36,12 +30,14 @@ pub fn print_state(
|
|||
return;
|
||||
}
|
||||
|
||||
let table_builder = TableBuilder::new(settings, style);
|
||||
|
||||
if let Some(group) = group_only {
|
||||
print_single_group(state, tasks, settings, style, group);
|
||||
print_single_group(state, tasks, style, group, table_builder);
|
||||
return;
|
||||
}
|
||||
|
||||
print_all_groups(state, tasks, settings, style);
|
||||
print_all_groups(state, tasks, style, table_builder);
|
||||
}
|
||||
|
||||
/// The user requested only a single group to be displayed.
|
||||
|
@ -50,9 +46,9 @@ pub fn print_state(
|
|||
fn print_single_group(
|
||||
state: State,
|
||||
tasks: Vec<Task>,
|
||||
settings: &Settings,
|
||||
style: &OutputStyle,
|
||||
group_name: String,
|
||||
table_builder: TableBuilder,
|
||||
) {
|
||||
// Sort all tasks by their respective group;
|
||||
let mut sorted_tasks = sort_tasks_by_group(tasks);
|
||||
|
@ -74,13 +70,20 @@ fn print_single_group(
|
|||
println!("Task list is empty. Add tasks with `pueue add -g {group_name} -- [cmd]`");
|
||||
return;
|
||||
}
|
||||
print_table(tasks, style, settings);
|
||||
|
||||
let table = table_builder.build(tasks);
|
||||
println!("{table}");
|
||||
}
|
||||
|
||||
/// Print all groups. All tasks will be shown in the table of their assigned group.
|
||||
///
|
||||
/// This will create multiple tables, one table for each group.
|
||||
fn print_all_groups(state: State, tasks: Vec<Task>, settings: &Settings, style: &OutputStyle) {
|
||||
fn print_all_groups(
|
||||
state: State,
|
||||
tasks: Vec<Task>,
|
||||
style: &OutputStyle,
|
||||
table_builder: TableBuilder,
|
||||
) {
|
||||
// Early exit and hint if there are no tasks in the queue
|
||||
// Print the state of the default group anyway, since this is information one wants to
|
||||
// see most of the time anyway.
|
||||
|
@ -107,7 +110,8 @@ fn print_all_groups(state: State, tasks: Vec<Task>, settings: &Settings, style:
|
|||
style,
|
||||
);
|
||||
println!("{headline}");
|
||||
print_table(tasks, style, settings);
|
||||
let table = table_builder.clone().build(tasks);
|
||||
println!("{table}");
|
||||
|
||||
// Add a newline if there are further groups to be printed
|
||||
if sorted_tasks.len() > 1 {
|
||||
|
@ -126,7 +130,8 @@ fn print_all_groups(state: State, tasks: Vec<Task>, settings: &Settings, style:
|
|||
|
||||
let headline = get_group_headline(group, state.groups.get(group).unwrap(), style);
|
||||
println!("{headline}");
|
||||
print_table(tasks, style, settings);
|
||||
let table = table_builder.clone().build(tasks);
|
||||
println!("{table}");
|
||||
|
||||
// Add a newline between groups
|
||||
if sorted_iter.peek().is_some() {
|
||||
|
@ -134,165 +139,3 @@ fn print_all_groups(state: State, tasks: Vec<Task>, settings: &Settings, style:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Display tasks in a nicely formatted table.
|
||||
///
|
||||
/// For info on how this works, take a look at [comfy_table].
|
||||
fn print_table(tasks: &[Task], style: &OutputStyle, settings: &Settings) {
|
||||
let (has_delayed_tasks, has_dependencies, has_labels) = has_special_columns(tasks);
|
||||
|
||||
// Create table header row
|
||||
let mut headers = vec![Cell::new("Id"), Cell::new("Status")];
|
||||
|
||||
if has_delayed_tasks {
|
||||
headers.push(Cell::new("Enqueue At"));
|
||||
}
|
||||
if has_dependencies {
|
||||
headers.push(Cell::new("Deps"));
|
||||
}
|
||||
if has_labels {
|
||||
headers.push(Cell::new("Label"));
|
||||
}
|
||||
|
||||
headers.append(&mut vec![
|
||||
Cell::new("Command"),
|
||||
Cell::new("Path"),
|
||||
Cell::new("Start"),
|
||||
Cell::new("End"),
|
||||
]);
|
||||
|
||||
// Initialize comfy table.
|
||||
let mut table = Table::new();
|
||||
table
|
||||
.set_content_arrangement(ContentArrangement::Dynamic)
|
||||
.load_preset(UTF8_HORIZONTAL_ONLY)
|
||||
.set_header(headers);
|
||||
|
||||
// Explicitly force styling, in case we aren't on a tty, but `--color=always` is set.
|
||||
if style.enabled {
|
||||
table.enforce_styling();
|
||||
}
|
||||
|
||||
// Add rows one by one.
|
||||
for task in tasks.iter() {
|
||||
let mut row = Row::new();
|
||||
if let Some(height) = settings.client.max_status_lines {
|
||||
row.max_height(height);
|
||||
}
|
||||
row.add_cell(Cell::new(&task.id));
|
||||
|
||||
// Determine the human readable task status representation and the respective color.
|
||||
let status_string = task.status.to_string();
|
||||
let (status_text, color) = match &task.status {
|
||||
TaskStatus::Running => (status_string, Color::Green),
|
||||
TaskStatus::Paused | TaskStatus::Locked => (status_string, Color::White),
|
||||
TaskStatus::Done(result) => match result {
|
||||
TaskResult::Success => (TaskResult::Success.to_string(), Color::Green),
|
||||
TaskResult::DependencyFailed => ("Dependency failed".to_string(), Color::Red),
|
||||
TaskResult::FailedToSpawn(_) => ("Failed to spawn".to_string(), Color::Red),
|
||||
TaskResult::Failed(code) => (format!("Failed ({code})"), Color::Red),
|
||||
_ => (result.to_string(), Color::Red),
|
||||
},
|
||||
_ => (status_string, Color::Yellow),
|
||||
};
|
||||
row.add_cell(style.styled_cell(status_text, Some(color), None));
|
||||
|
||||
if has_delayed_tasks {
|
||||
if let TaskStatus::Stashed {
|
||||
enqueue_at: Some(enqueue_at),
|
||||
} = task.status
|
||||
{
|
||||
// Only show the date if the task is not supposed to be enqueued today.
|
||||
let enqueue_today =
|
||||
enqueue_at <= Local::today().and_hms(0, 0, 0) + Duration::days(1);
|
||||
let formatted_enqueue_at = if enqueue_today {
|
||||
enqueue_at.format(&settings.client.status_time_format)
|
||||
} else {
|
||||
enqueue_at.format(&settings.client.status_datetime_format)
|
||||
};
|
||||
row.add_cell(Cell::new(formatted_enqueue_at));
|
||||
} else {
|
||||
row.add_cell(Cell::new(""));
|
||||
}
|
||||
}
|
||||
|
||||
if has_dependencies {
|
||||
let text = task
|
||||
.dependencies
|
||||
.iter()
|
||||
.map(|id| id.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ");
|
||||
row.add_cell(Cell::new(text));
|
||||
}
|
||||
|
||||
if has_labels {
|
||||
row.add_cell(Cell::new(&task.label.as_deref().unwrap_or_default()));
|
||||
}
|
||||
|
||||
// Add command and path.
|
||||
if settings.client.show_expanded_aliases {
|
||||
row.add_cell(Cell::new(&task.command));
|
||||
} else {
|
||||
row.add_cell(Cell::new(&task.original_command));
|
||||
}
|
||||
row.add_cell(Cell::new(&task.path.to_string_lossy()));
|
||||
|
||||
// Add start and end info
|
||||
let (start, end) = formatted_start_end(task, settings);
|
||||
row.add_cell(Cell::new(start));
|
||||
row.add_cell(Cell::new(end));
|
||||
|
||||
table.add_row(row);
|
||||
}
|
||||
|
||||
// Print the table.
|
||||
println!("{table}");
|
||||
}
|
||||
|
||||
/// Returns the formatted `start` and `end` text for a given task.
|
||||
///
|
||||
/// 1. If the start || end is today, skip the date.
|
||||
/// 2. Otherwise show the date in both.
|
||||
///
|
||||
/// If the task doesn't have a start and/or end yet, an empty string will be returned
|
||||
/// for the respective field.
|
||||
fn formatted_start_end(task: &Task, settings: &Settings) -> (String, String) {
|
||||
// Get the start time.
|
||||
// If the task didn't start yet, just return two empty strings.
|
||||
let start = match task.start {
|
||||
Some(start) => start,
|
||||
None => return ("".into(), "".into()),
|
||||
};
|
||||
|
||||
// If the task started today, just show the time.
|
||||
// Otherwise show the full date and time.
|
||||
let started_today = start >= Local::today().and_hms(0, 0, 0);
|
||||
let formatted_start = if started_today {
|
||||
start
|
||||
.format(&settings.client.status_time_format)
|
||||
.to_string()
|
||||
} else {
|
||||
start
|
||||
.format(&settings.client.status_datetime_format)
|
||||
.to_string()
|
||||
};
|
||||
|
||||
// Get finish time, if already set. Otherwise only return the formatted start.
|
||||
let end = match task.end {
|
||||
Some(end) => end,
|
||||
None => return (formatted_start, "".into()),
|
||||
};
|
||||
|
||||
// If the task ended today we only show the time.
|
||||
// In all other circumstances, we show the full date.
|
||||
let finished_today = end >= Local::today().and_hms(0, 0, 0);
|
||||
let formatted_end = if finished_today {
|
||||
end.format(&settings.client.status_time_format).to_string()
|
||||
} else {
|
||||
end.format(&settings.client.status_datetime_format)
|
||||
.to_string()
|
||||
};
|
||||
|
||||
(formatted_start, formatted_end)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use crossterm::style::{style, Attribute, Color, Stylize};
|
|||
/// OutputStyle wrapper for actual colors depending on settings
|
||||
/// - Enables styles if color mode is 'always', or if color mode is 'auto' and output is a tty.
|
||||
/// - Using dark colors if dark_mode is enabled
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OutputStyle {
|
||||
/// whether or not ANSI styling is enabled
|
||||
pub enabled: bool,
|
||||
|
|
225
client/display/table_builder.rs
Normal file
225
client/display/table_builder.rs
Normal file
|
@ -0,0 +1,225 @@
|
|||
use chrono::{Duration, Local};
|
||||
use comfy_table::presets::UTF8_HORIZONTAL_ONLY;
|
||||
use comfy_table::*;
|
||||
|
||||
use pueue_lib::settings::Settings;
|
||||
use pueue_lib::task::{Task, TaskResult, TaskStatus};
|
||||
|
||||
use super::helper::formatted_start_end;
|
||||
use super::OutputStyle;
|
||||
|
||||
/// This builder is responsible for determining which table columns should be displayed and
|
||||
/// building a full [comfy_table] from a list of given [Task]s.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TableBuilder<'a> {
|
||||
settings: &'a Settings,
|
||||
style: &'a OutputStyle,
|
||||
|
||||
/// This following fields represent which columns should be displayed when executing
|
||||
/// `pueue status`. `true` for any column means that it'll be shown in the table.
|
||||
id: bool,
|
||||
status: bool,
|
||||
enqueue_at: bool,
|
||||
dependencies: bool,
|
||||
label: bool,
|
||||
command: bool,
|
||||
path: bool,
|
||||
start: bool,
|
||||
end: bool,
|
||||
}
|
||||
|
||||
impl<'a> TableBuilder<'a> {
|
||||
pub fn new(settings: &'a Settings, style: &'a OutputStyle) -> Self {
|
||||
Self {
|
||||
settings,
|
||||
style,
|
||||
|
||||
id: true,
|
||||
status: true,
|
||||
enqueue_at: false,
|
||||
dependencies: false,
|
||||
label: false,
|
||||
command: true,
|
||||
path: true,
|
||||
start: true,
|
||||
end: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build(mut self, tasks: &[Task]) -> Table {
|
||||
self.determine_special_columns(tasks);
|
||||
|
||||
let mut table = Table::new();
|
||||
table
|
||||
.set_content_arrangement(ContentArrangement::Dynamic)
|
||||
.load_preset(UTF8_HORIZONTAL_ONLY)
|
||||
.set_header(self.build_header())
|
||||
.add_rows(self.build_task_rows(tasks));
|
||||
|
||||
// Explicitly force styling, in case we aren't on a tty, but `--color=always` is set.
|
||||
if self.style.enabled {
|
||||
table.enforce_styling();
|
||||
}
|
||||
|
||||
table
|
||||
}
|
||||
|
||||
/// By default, several columns aren't shown until there's at least one task with relevant data.
|
||||
/// This function determines whether any of those columns should be shown.
|
||||
fn determine_special_columns(&mut self, tasks: &[Task]) {
|
||||
// Check whether there are any delayed tasks.
|
||||
let has_delayed_tasks = tasks.iter().any(|task| {
|
||||
matches!(
|
||||
task.status,
|
||||
TaskStatus::Stashed {
|
||||
enqueue_at: Some(_)
|
||||
}
|
||||
)
|
||||
});
|
||||
if has_delayed_tasks {
|
||||
self.enqueue_at = true;
|
||||
}
|
||||
|
||||
// Check whether there are any tasks with dependencies.
|
||||
if tasks.iter().any(|task| !task.dependencies.is_empty()) {
|
||||
self.dependencies = true;
|
||||
}
|
||||
|
||||
// Check whether there are any tasks a label.
|
||||
if tasks.iter().any(|task| task.label.is_some()) {
|
||||
self.label = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a header row based on the current selection of columns.
|
||||
fn build_header(&self) -> Row {
|
||||
let mut header = Vec::new();
|
||||
|
||||
// Create table header row
|
||||
if self.id {
|
||||
header.push(Cell::new("Id"));
|
||||
}
|
||||
if self.status {
|
||||
header.push(Cell::new("Status"));
|
||||
}
|
||||
|
||||
if self.enqueue_at {
|
||||
header.push(Cell::new("Enqueue At"));
|
||||
}
|
||||
if self.dependencies {
|
||||
header.push(Cell::new("Deps"));
|
||||
}
|
||||
if self.label {
|
||||
header.push(Cell::new("Label"));
|
||||
}
|
||||
if self.command {
|
||||
header.push(Cell::new("Command"));
|
||||
}
|
||||
if self.path {
|
||||
header.push(Cell::new("Path"));
|
||||
}
|
||||
if self.start {
|
||||
header.push(Cell::new("Start"));
|
||||
}
|
||||
if self.end {
|
||||
header.push(Cell::new("End"));
|
||||
}
|
||||
|
||||
Row::from(header)
|
||||
}
|
||||
|
||||
fn build_task_rows(&self, tasks: &[Task]) -> Vec<Row> {
|
||||
let mut rows = Vec::new();
|
||||
// Add rows one by one.
|
||||
for task in tasks.iter() {
|
||||
let mut row = Row::new();
|
||||
// Users can set a max height per row.
|
||||
if let Some(height) = self.settings.client.max_status_lines {
|
||||
row.max_height(height);
|
||||
}
|
||||
|
||||
if self.id {
|
||||
row.add_cell(Cell::new(&task.id));
|
||||
}
|
||||
|
||||
if self.status {
|
||||
// Determine the human readable task status representation and the respective color.
|
||||
let status_string = task.status.to_string();
|
||||
let (status_text, color) = match &task.status {
|
||||
TaskStatus::Running => (status_string, Color::Green),
|
||||
TaskStatus::Paused | TaskStatus::Locked => (status_string, Color::White),
|
||||
TaskStatus::Done(result) => match result {
|
||||
TaskResult::Success => (TaskResult::Success.to_string(), Color::Green),
|
||||
TaskResult::DependencyFailed => {
|
||||
("Dependency failed".to_string(), Color::Red)
|
||||
}
|
||||
TaskResult::FailedToSpawn(_) => ("Failed to spawn".to_string(), Color::Red),
|
||||
TaskResult::Failed(code) => (format!("Failed ({code})"), Color::Red),
|
||||
_ => (result.to_string(), Color::Red),
|
||||
},
|
||||
_ => (status_string, Color::Yellow),
|
||||
};
|
||||
row.add_cell(self.style.styled_cell(status_text, Some(color), None));
|
||||
}
|
||||
|
||||
if self.enqueue_at {
|
||||
if let TaskStatus::Stashed {
|
||||
enqueue_at: Some(enqueue_at),
|
||||
} = task.status
|
||||
{
|
||||
// Only show the date if the task is not supposed to be enqueued today.
|
||||
let enqueue_today =
|
||||
enqueue_at <= Local::today().and_hms(0, 0, 0) + Duration::days(1);
|
||||
let formatted_enqueue_at = if enqueue_today {
|
||||
enqueue_at.format(&self.settings.client.status_time_format)
|
||||
} else {
|
||||
enqueue_at.format(&self.settings.client.status_datetime_format)
|
||||
};
|
||||
row.add_cell(Cell::new(formatted_enqueue_at));
|
||||
} else {
|
||||
row.add_cell(Cell::new(""));
|
||||
}
|
||||
}
|
||||
|
||||
if self.dependencies {
|
||||
let text = task
|
||||
.dependencies
|
||||
.iter()
|
||||
.map(|id| id.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ");
|
||||
row.add_cell(Cell::new(text));
|
||||
}
|
||||
|
||||
if self.label {
|
||||
row.add_cell(Cell::new(&task.label.as_deref().unwrap_or_default()));
|
||||
}
|
||||
|
||||
// Add command and path.
|
||||
if self.command {
|
||||
if self.settings.client.show_expanded_aliases {
|
||||
row.add_cell(Cell::new(&task.command));
|
||||
} else {
|
||||
row.add_cell(Cell::new(&task.original_command));
|
||||
}
|
||||
}
|
||||
|
||||
if self.path {
|
||||
row.add_cell(Cell::new(&task.path.to_string_lossy()));
|
||||
}
|
||||
|
||||
// Add start and end info
|
||||
let (start, end) = formatted_start_end(task, self.settings);
|
||||
if self.start {
|
||||
row.add_cell(Cell::new(start));
|
||||
}
|
||||
if self.end {
|
||||
row.add_cell(Cell::new(end));
|
||||
}
|
||||
|
||||
rows.push(row);
|
||||
}
|
||||
|
||||
rows
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue