ability to overwrite and add to profile arguments from command line
This commit is contained in:
parent
4056cd2a60
commit
130fab27d7
18
src/args.rs
18
src/args.rs
@ -112,12 +112,12 @@ pub struct ListOptions {
|
|||||||
/// Which columns to include.
|
/// Which columns to include.
|
||||||
#[clap(short, value_enum)]
|
#[clap(short, value_enum)]
|
||||||
pub column : Vec<Column>,
|
pub column : Vec<Column>,
|
||||||
/// Field to order by.
|
/// Field to order by [default: id].
|
||||||
#[clap(long, value_enum, default_value_t=OrderBy::Id)]
|
#[clap(long, value_enum)]
|
||||||
pub order_by : OrderBy,
|
pub order_by : Option<OrderBy>,
|
||||||
/// Sort ascending on descending.
|
/// Sort ascending on descending [default: asc].
|
||||||
#[clap(long, value_enum, default_value_t=Order::Asc)]
|
#[clap(long, value_enum)]
|
||||||
pub order : Order,
|
pub order : Option<Order>,
|
||||||
/// Tags to include.
|
/// Tags to include.
|
||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
pub tag : Vec<String>,
|
pub tag : Vec<String>,
|
||||||
@ -150,14 +150,14 @@ pub struct ListOptions {
|
|||||||
pub no_dependents : bool,
|
pub no_dependents : bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Debug, PartialEq, Eq, clap::ValueEnum, serde::Serialize, serde::Deserialize)]
|
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, clap::ValueEnum, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum Order {
|
pub enum Order {
|
||||||
#[default]
|
#[default]
|
||||||
Asc,
|
Asc,
|
||||||
Desc,
|
Desc,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Hash, Clone, Debug, PartialEq, Eq, clap::ValueEnum, serde::Serialize, serde::Deserialize)]
|
#[derive(Hash, Clone, Copy, Debug, PartialEq, Eq, clap::ValueEnum, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum Column {
|
pub enum Column {
|
||||||
Due,
|
Due,
|
||||||
Priority,
|
Priority,
|
||||||
@ -167,7 +167,7 @@ pub enum Column {
|
|||||||
Status,
|
Status,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Debug, PartialEq, Eq, clap::ValueEnum, serde::Serialize, serde::Deserialize)]
|
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, clap::ValueEnum, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum OrderBy {
|
pub enum OrderBy {
|
||||||
#[default]
|
#[default]
|
||||||
Id,
|
Id,
|
||||||
|
11
src/main.rs
11
src/main.rs
@ -171,13 +171,14 @@ fn program() -> Result<(), error::Error> {
|
|||||||
task.save()?;
|
task.save()?;
|
||||||
println!("Marked task {} as complete", format::id(id));
|
println!("Marked task {} as complete", format::id(id));
|
||||||
},
|
},
|
||||||
Command::List { profile, options } => {
|
Command::List { profile : profile_name, options : additional } => {
|
||||||
let options = match profile {
|
let options = match profile_name {
|
||||||
Some(profile) => {
|
Some(profile_name) => {
|
||||||
config.get_profile(&profile)?
|
let profile = config.get_profile(&profile_name)?;
|
||||||
|
ListOptions::combine(profile, &additional)
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
&options
|
additional
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
tasks::list(options, vault_folder, &state)?;
|
tasks::list(options, vault_folder, &state)?;
|
||||||
|
63
src/tasks.rs
63
src/tasks.rs
@ -1,3 +1,4 @@
|
|||||||
|
use crate::args;
|
||||||
use crate::error;
|
use crate::error;
|
||||||
use crate::state;
|
use crate::state;
|
||||||
use crate::format;
|
use crate::format;
|
||||||
@ -355,8 +356,50 @@ fn compare_due_dates<T : Ord>(first : &Option<T>, second : &Option<T>) -> cmp::O
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl args::ListOptions {
|
||||||
|
/// Combines list options coming from a profile and from the additional arguments given. Order
|
||||||
|
/// of the arguments provided matters, hence the argument names (because optional arguments
|
||||||
|
/// from the profile are overwritten by the additional arguments).
|
||||||
|
pub fn combine(profile : &Self, additional : &Self) -> Self {
|
||||||
|
/// Joins two vectors together one after the other, creating a new allocation.
|
||||||
|
fn concat<T : Clone>(a : &Vec<T>, b : &Vec<T>) -> Vec<T> {
|
||||||
|
let mut a = a.clone();
|
||||||
|
a.extend(b.iter().cloned());
|
||||||
|
a
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes two options, and prioritises the second if it is provided in the output, using
|
||||||
|
/// the first as a fallback, and returning None if both are None.
|
||||||
|
fn join_options<T : Clone>(a : &Option<T>, b : &Option<T>) -> Option<T> {
|
||||||
|
match (a, b) {
|
||||||
|
(Some(_), Some(b)) => Some(b.clone()),
|
||||||
|
(Some(a), None) => Some(a.clone()),
|
||||||
|
(None, Some(b)) => Some(b.clone()),
|
||||||
|
(None, None) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Self {
|
||||||
|
column : concat(&profile.column, &additional.column),
|
||||||
|
order_by : join_options(&profile.order_by, &additional.order_by),
|
||||||
|
order : join_options(&profile.order, &profile.order),
|
||||||
|
tag : concat(&profile.tag, &additional.tag),
|
||||||
|
exclude_tag : concat(&profile.exclude_tag, &additional.exclude_tag),
|
||||||
|
priority : concat(&profile.priority, &additional.priority),
|
||||||
|
due_before : join_options(&profile.due_before, &additional.due_before),
|
||||||
|
due_after : join_options(&profile.due_after, &additional.due_after),
|
||||||
|
created_before : join_options(&profile.created_before, &additional.created_before),
|
||||||
|
created_after : join_options(&profile.created_after, &additional.created_after),
|
||||||
|
include_completed : profile.include_completed || additional.include_completed,
|
||||||
|
no_dependencies : profile.no_dependencies || additional.no_dependencies,
|
||||||
|
no_dependents : profile.no_dependents || additional.no_dependents,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Lists all tasks in the specified vault.
|
/// Lists all tasks in the specified vault.
|
||||||
pub fn list(options : &super::ListOptions, vault_folder : &path::Path, state : &state::State) -> Result<(), error::Error> {
|
pub fn list(mut options : args::ListOptions, vault_folder : &path::Path, state : &state::State) -> Result<(), error::Error> {
|
||||||
|
|
||||||
let mut table = comfy_table::Table::new();
|
let mut table = comfy_table::Table::new();
|
||||||
table
|
table
|
||||||
@ -446,9 +489,9 @@ pub fn list(options : &super::ListOptions, vault_folder : &path::Path, state : &
|
|||||||
|
|
||||||
// Sort the tasks.
|
// Sort the tasks.
|
||||||
use super::{OrderBy, Order};
|
use super::{OrderBy, Order};
|
||||||
match options.order_by {
|
match options.order_by.unwrap_or_default() {
|
||||||
OrderBy::Id => {
|
OrderBy::Id => {
|
||||||
match options.order {
|
match options.order.unwrap_or_default() {
|
||||||
Order::Asc => {
|
Order::Asc => {
|
||||||
tasks.sort_by(|t1, t2| t1.data.id.cmp(&t2.data.id));
|
tasks.sort_by(|t1, t2| t1.data.id.cmp(&t2.data.id));
|
||||||
},
|
},
|
||||||
@ -458,7 +501,7 @@ pub fn list(options : &super::ListOptions, vault_folder : &path::Path, state : &
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
OrderBy::Name => {
|
OrderBy::Name => {
|
||||||
match options.order {
|
match options.order.unwrap_or_default() {
|
||||||
Order::Asc => {
|
Order::Asc => {
|
||||||
tasks.sort_by(|t1, t2| t1.data.name.cmp(&t2.data.name));
|
tasks.sort_by(|t1, t2| t1.data.name.cmp(&t2.data.name));
|
||||||
},
|
},
|
||||||
@ -468,7 +511,7 @@ pub fn list(options : &super::ListOptions, vault_folder : &path::Path, state : &
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
OrderBy::Due => {
|
OrderBy::Due => {
|
||||||
match options.order {
|
match options.order.unwrap_or_default() {
|
||||||
Order::Asc => {
|
Order::Asc => {
|
||||||
tasks.sort_by(|t1, t2| compare_due_dates(&t1.data.due, &t2.data.due));
|
tasks.sort_by(|t1, t2| compare_due_dates(&t1.data.due, &t2.data.due));
|
||||||
},
|
},
|
||||||
@ -478,7 +521,7 @@ pub fn list(options : &super::ListOptions, vault_folder : &path::Path, state : &
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
OrderBy::Priority => {
|
OrderBy::Priority => {
|
||||||
match options.order {
|
match options.order.unwrap_or_default() {
|
||||||
Order::Asc => {
|
Order::Asc => {
|
||||||
tasks.sort_by(|t1, t2| t1.data.priority.cmp(&t2.data.priority));
|
tasks.sort_by(|t1, t2| t1.data.priority.cmp(&t2.data.priority));
|
||||||
},
|
},
|
||||||
@ -488,7 +531,7 @@ pub fn list(options : &super::ListOptions, vault_folder : &path::Path, state : &
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
OrderBy::Created => {
|
OrderBy::Created => {
|
||||||
match options.order {
|
match options.order.unwrap_or_default() {
|
||||||
Order::Asc => {
|
Order::Asc => {
|
||||||
tasks.sort_by(|t1, t2| t1.data.created.cmp(&t2.data.created));
|
tasks.sort_by(|t1, t2| t1.data.created.cmp(&t2.data.created));
|
||||||
},
|
},
|
||||||
@ -498,7 +541,7 @@ pub fn list(options : &super::ListOptions, vault_folder : &path::Path, state : &
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
OrderBy::Tracked => {
|
OrderBy::Tracked => {
|
||||||
match options.order {
|
match options.order.unwrap_or_default() {
|
||||||
Order::Asc => {
|
Order::Asc => {
|
||||||
tasks.sort_by(|t1, t2| TimeEntry::total(&t1.data.time_entries).cmp(&TimeEntry::total(&t2.data.time_entries)));
|
tasks.sort_by(|t1, t2| TimeEntry::total(&t1.data.time_entries).cmp(&TimeEntry::total(&t2.data.time_entries)));
|
||||||
},
|
},
|
||||||
@ -513,7 +556,7 @@ pub fn list(options : &super::ListOptions, vault_folder : &path::Path, state : &
|
|||||||
let mut headers = vec!["Id", "Name"];
|
let mut headers = vec!["Id", "Name"];
|
||||||
|
|
||||||
// Remove duplicate columns.
|
// Remove duplicate columns.
|
||||||
let unique_columns : Vec<_> = {
|
options.column = {
|
||||||
let mut columns = HashSet::new();
|
let mut columns = HashSet::new();
|
||||||
|
|
||||||
options.column.clone()
|
options.column.clone()
|
||||||
@ -531,7 +574,7 @@ pub fn list(options : &super::ListOptions, vault_folder : &path::Path, state : &
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::Column;
|
use super::Column;
|
||||||
for column in &unique_columns {
|
for column in &options.column {
|
||||||
match column {
|
match column {
|
||||||
Column::Tracked => {
|
Column::Tracked => {
|
||||||
headers.push("Tracked");
|
headers.push("Tracked");
|
||||||
|
Loading…
Reference in New Issue
Block a user