diff --git a/Cargo.lock b/Cargo.lock index 47dd664..1514117 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -825,7 +825,7 @@ dependencies = [ [[package]] name = "toru" -version = "0.1.2" +version = "0.1.3" dependencies = [ "chrono", "clap", diff --git a/README.md b/README.md index 746d8d6..adc7c0a 100644 --- a/README.md +++ b/README.md @@ -95,10 +95,6 @@ Then you can run `toru new` to create your first task. - Error if any circular dependencies are introduced - Make sure dependencies written to file are only those that could be successfully created - List dependencies as a tree on note view below info -- Completed Date - - Keep track of completed date, and correctly update upon marking as complete or manual edit - - Disallow removing it in a manual edit unless complete is also marked to false - - Add to statistics - Statistics - Completed tasks over last x days - Improve formatting to terminal to make easier to read for `tracked` command diff --git a/src/main.rs b/src/main.rs index 3363326..f0f4340 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,7 +41,7 @@ enum Command { View { id_or_name : String, }, - /// Edit a note directly. + /// Edit a task directly. Edit { id_or_name : String, /// Edit the info specifically in its own file. @@ -83,7 +83,7 @@ enum Command { // - which columns to include // - filters which exclude values }, - /// For tracking time against a note. + /// For tracking time against a task. Track { id_or_name : String, #[clap(short='H', default_value_t=0)] @@ -294,7 +294,7 @@ fn program() -> Result<(), error::Error> { Complete { id_or_name } => { let id = state.name_or_id_to_id(&id_or_name)?; let mut task = tasks::Task::load(id, vault_folder, false)?; - task.data.complete = true; + task.data.completed = Some(chrono::Local::now().naive_local()); task.save()?; println!("Marked task {} as complete", colour::id(&id.to_string())); }, diff --git a/src/stats.rs b/src/stats.rs index 41c7fb5..1f18583 100644 --- a/src/stats.rs +++ b/src/stats.rs @@ -2,13 +2,13 @@ use crate::tasks; use crate::error; use std::path; -use std::collections::HashMap; +use std::collections::BTreeMap; pub fn time_per_tag(days : u16, vault_folder : &path::Path) -> Result<(), error::Error> { let tasks = tasks::Task::load_all(vault_folder, true)?; - let mut times = HashMap::::new(); + let mut times = BTreeMap::::new(); for task in &tasks { if !task.data.discarded { @@ -29,7 +29,7 @@ pub fn time_per_tag(days : u16, vault_folder : &path::Path) -> Result<(), error: *time = *time + time_per_tag; }, None => { - times.insert(tag.clone(), time); + times.insert(tag.clone(), time_per_tag); } } } @@ -43,8 +43,8 @@ pub fn time_per_tag(days : u16, vault_folder : &path::Path) -> Result<(), error: .set_content_arrangement(comfy_table::ContentArrangement::Dynamic); table.set_header(vec!["Tag", "Time"]); - for (tag, duration) in × { + for (tag, duration) in times { table.add_row( vec![ tag.clone(), diff --git a/src/tasks.rs b/src/tasks.rs index ff89fc5..373ff91 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -76,7 +76,7 @@ pub struct InternalTask { pub priority : Priority, pub due : Option, pub created : chrono::NaiveDateTime, - pub complete : bool, + pub completed : Option, pub discarded : bool, pub info : Option, pub time_entries : Vec, @@ -109,7 +109,7 @@ impl Task { due, time_entries : Vec::new(), created : chrono::Local::now().naive_local(), - complete : false, + completed : None, discarded : false, }; @@ -235,7 +235,7 @@ impl Task { let discarded = if self.data.discarded { String::from(" (discarded)") } else { String::new() }; ( - format!("[{}] {} {}{}", if self.data.complete {"X"} else {" "}, colour::id(id), colour::task_name(&self.data.name), colour::greyed_out(&discarded)), + format!("[{}] {} {}{}", if self.data.completed.is_some() {"X"} else {" "}, colour::id(id), colour::task_name(&self.data.name), colour::greyed_out(&discarded)), 5 + self.data.name.chars().count() + id.chars().count() + discarded.chars().count() ) }; @@ -248,7 +248,7 @@ impl Task { println!("Created: {}", self.data.created.round_subsecs(0)); if let Some(due) = self.data.due { - let due = format_due_date(&due, !self.data.complete, true); + let due = format_due_date(&due, self.data.completed.is_none(), true); println!("Due: {}", due); } @@ -373,7 +373,7 @@ pub fn list(vault_folder : &path::Path) -> Result<(), error::Error> { tasks.sort_by(|t1, t2| t2.data.priority.cmp(&t1.data.priority)); for task in tasks { - if !task.data.discarded && !task.data.complete { + if !task.data.discarded && task.data.completed.is_none() { let duration = TimeEntry::total(&task.data.time_entries); @@ -384,7 +384,7 @@ pub fn list(vault_folder : &path::Path) -> Result<(), error::Error> { format_hash_set(&task.data.tags)?, task.data.priority.to_string(), if duration == Duration::zero() { String::new() } else { duration.to_string() }, - match task.data.due { Some(due) => format_due_date(&due, !task.data.complete, false), None => String::new() }, + match task.data.due { Some(due) => format_due_date(&due, task.data.completed.is_none(), false), None => String::new() }, ] ); } @@ -435,7 +435,7 @@ impl ops::Div for Duration { fn div(self, divisor : usize) -> Self::Output { let total_mins = f64::from(self.hours * 60 + self.minutes); - let divided_mins = total_mins / divisor as f64; + let divided_mins = total_mins / (divisor as f64); let divided_mins = divided_mins.round() as u16; Self {