diff --git a/README.md b/README.md index 145c2af..7fc78ae 100755 --- a/README.md +++ b/README.md @@ -86,4 +86,3 @@ Toru stores tasks and other metadata locally in the folder of the vault in the i - Validate invariants at the point of saving, to create consistency across creating and editing notes. - Convenient options with the edit command so that editing the raw file isn't the only option -- Check for if dependencies are complete when listing notes with no dependencies. diff --git a/src/args.rs b/src/args.rs index 379de43..6d6556c 100644 --- a/src/args.rs +++ b/src/args.rs @@ -31,7 +31,7 @@ pub enum Command { dependency : Vec, #[clap(short, long, value_enum)] priority : Option, - /// Due date, expecting format yyyy-mm-ddThh:mm:ss + /// Due date, [format: yyyy-mm-ddThh:mm:ss]. #[clap(long)] due : Option, }, @@ -139,7 +139,7 @@ pub struct ListOptions { /// Include completed tasks in the list. #[clap(long)] pub include_completed : bool, - /// Only include tasks with no dependencies [alias: bottom-level]. + /// Only include tasks with no (incomplete) dependencies [alias: bottom-level]. #[clap(long, alias="bottom-level")] pub no_dependencies : bool, /// Only include tasks with no dependents [alias: top-level]. diff --git a/src/list.rs b/src/list.rs index e710f5e..8204807 100644 --- a/src/list.rs +++ b/src/list.rs @@ -3,10 +3,11 @@ use crate::error; use crate::state; use crate::tasks; use crate::format; +use crate::tasks::Id; use std::cmp; use std::path; -use std::collections::HashSet; +use std::collections::{HashSet, HashMap}; use chrono::SubsecRound; impl args::ListOptions { @@ -60,7 +61,12 @@ pub fn list(mut options : args::ListOptions, vault_folder : &path::Path, state : .set_content_arrangement(comfy_table::ContentArrangement::Dynamic); - let mut tasks : Box> = Box::new(tasks::Task::load_all(vault_folder, true)?.into_iter()); + let tasks = tasks::Task::load_all(vault_folder, true)?; + + // Collect the Ids of completed tasks for the sake of checking if a task has no incomplete dependencies. + let completed_ids : HashSet = tasks.iter().filter_map(|t| if t.data.completed.is_some() { Some(t.data.id) } else { None }).collect(); + + let mut tasks : Box> = Box::new(tasks.into_iter()); // Filter the tasks. if let Some(date) = options.created_before { @@ -122,9 +128,10 @@ pub fn list(mut options : args::ListOptions, vault_folder : &path::Path, state : })); } + // Checks that a task has no incomplete dependencies (these dependencies are direct only). if options.no_dependencies { tasks = Box::new(tasks.filter(move |t| { - t.data.dependencies.is_empty() + t.data.dependencies.iter().all(|d| completed_ids.contains(&d)) })); } @@ -136,8 +143,7 @@ pub fn list(mut options : args::ListOptions, vault_folder : &path::Path, state : })); } - let mut tasks : Vec = tasks.collect(); - + let mut tasks : Vec<_> = tasks.collect(); // Sort the tasks. use super::{OrderBy, Order};