only check for incomplete dependencies when listing with --no-dependencies

This commit is contained in:
aaron-jack-manning 2022-09-10 15:38:37 +10:00
parent e496faee48
commit 2c5acbe61d
3 changed files with 13 additions and 8 deletions

View File

@ -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. - 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 - 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.

View File

@ -31,7 +31,7 @@ pub enum Command {
dependency : Vec<Id>, dependency : Vec<Id>,
#[clap(short, long, value_enum)] #[clap(short, long, value_enum)]
priority : Option<tasks::Priority>, priority : Option<tasks::Priority>,
/// Due date, expecting format yyyy-mm-ddThh:mm:ss /// Due date, [format: yyyy-mm-ddThh:mm:ss].
#[clap(long)] #[clap(long)]
due : Option<chrono::NaiveDateTime>, due : Option<chrono::NaiveDateTime>,
}, },
@ -139,7 +139,7 @@ pub struct ListOptions {
/// Include completed tasks in the list. /// Include completed tasks in the list.
#[clap(long)] #[clap(long)]
pub include_completed : bool, 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")] #[clap(long, alias="bottom-level")]
pub no_dependencies : bool, pub no_dependencies : bool,
/// Only include tasks with no dependents [alias: top-level]. /// Only include tasks with no dependents [alias: top-level].

View File

@ -3,10 +3,11 @@ use crate::error;
use crate::state; use crate::state;
use crate::tasks; use crate::tasks;
use crate::format; use crate::format;
use crate::tasks::Id;
use std::cmp; use std::cmp;
use std::path; use std::path;
use std::collections::HashSet; use std::collections::{HashSet, HashMap};
use chrono::SubsecRound; use chrono::SubsecRound;
impl args::ListOptions { 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); .set_content_arrangement(comfy_table::ContentArrangement::Dynamic);
let mut tasks : Box<dyn Iterator<Item = tasks::Task>> = 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<Id> = tasks.iter().filter_map(|t| if t.data.completed.is_some() { Some(t.data.id) } else { None }).collect();
let mut tasks : Box<dyn Iterator<Item = tasks::Task>> = Box::new(tasks.into_iter());
// Filter the tasks. // Filter the tasks.
if let Some(date) = options.created_before { 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 { if options.no_dependencies {
tasks = Box::new(tasks.filter(move |t| { 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::Task> = tasks.collect(); let mut tasks : Vec<_> = tasks.collect();
// Sort the tasks. // Sort the tasks.
use super::{OrderBy, Order}; use super::{OrderBy, Order};