mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
Support parsing depends:.. in CLI
This commit is contained in:
parent
bf73cc4cc7
commit
db1e1c9c96
4 changed files with 99 additions and 12 deletions
|
@ -1,4 +1,4 @@
|
|||
use super::{any, timestamp};
|
||||
use super::{any, id_list, timestamp, TaskId};
|
||||
use crate::argparse::NOW;
|
||||
use nom::bytes::complete::tag as nomtag;
|
||||
use nom::{branch::*, character::complete::*, combinator::*, sequence::*, IResult};
|
||||
|
@ -48,6 +48,17 @@ pub(crate) fn wait_colon(input: &str) -> IResult<&str, Option<DateTime<Utc>>> {
|
|||
)(input)
|
||||
}
|
||||
|
||||
/// Recognizes `depends:<task>` to `(true, <task>)` and `depends:-<task>` to `(false, <task>)`.
|
||||
pub(crate) fn depends_colon(input: &str) -> IResult<&str, (bool, Vec<TaskId>)> {
|
||||
fn to_bool(maybe_minus: Option<char>) -> Result<bool, ()> {
|
||||
Ok(maybe_minus.is_none()) // None -> true, Some -> false
|
||||
}
|
||||
preceded(
|
||||
nomtag("depends:"),
|
||||
pair(map_res(opt(char('-')), to_bool), id_list),
|
||||
)(input)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
|
|
@ -2,7 +2,7 @@ use nom::{branch::*, character::complete::*, combinator::*, multi::*, sequence::
|
|||
use taskchampion::Uuid;
|
||||
|
||||
/// A task identifier, as given in a filter command-line expression
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
||||
pub(crate) enum TaskId {
|
||||
/// A small integer identifying a working-set task
|
||||
WorkingSetId(usize),
|
||||
|
|
|
@ -8,7 +8,7 @@ mod tags;
|
|||
mod time;
|
||||
|
||||
pub(crate) use arg_matching::arg_matching;
|
||||
pub(crate) use colon::{status_colon, wait_colon};
|
||||
pub(crate) use colon::{depends_colon, status_colon, wait_colon};
|
||||
pub(crate) use idlist::{id_list, TaskId};
|
||||
pub(crate) use misc::{any, literal, report_name};
|
||||
pub(crate) use tags::{minus_tag, plus_tag};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::args::{any, arg_matching, minus_tag, plus_tag, wait_colon};
|
||||
use super::args::{any, arg_matching, depends_colon, minus_tag, plus_tag, wait_colon, TaskId};
|
||||
use super::ArgList;
|
||||
use crate::usage;
|
||||
use nom::{branch::alt, combinator::*, multi::fold_many0, IResult};
|
||||
|
@ -30,27 +30,33 @@ impl Default for DescriptionMod {
|
|||
/// A modification represents a change to a task: adding or removing tags, setting the
|
||||
/// description, and so on.
|
||||
#[derive(Debug, PartialEq, Clone, Default)]
|
||||
pub struct Modification {
|
||||
pub(crate) struct Modification {
|
||||
/// Change the description
|
||||
pub description: DescriptionMod,
|
||||
pub(crate) description: DescriptionMod,
|
||||
|
||||
/// Set the status
|
||||
pub status: Option<Status>,
|
||||
pub(crate) status: Option<Status>,
|
||||
|
||||
/// Set (or, with `Some(None)`, clear) the wait timestamp
|
||||
pub wait: Option<Option<DateTime<Utc>>>,
|
||||
pub(crate) wait: Option<Option<DateTime<Utc>>>,
|
||||
|
||||
/// Set the "active" state, that is, start (true) or stop (false) the task.
|
||||
pub active: Option<bool>,
|
||||
pub(crate) active: Option<bool>,
|
||||
|
||||
/// Add tags
|
||||
pub add_tags: HashSet<Tag>,
|
||||
pub(crate) add_tags: HashSet<Tag>,
|
||||
|
||||
/// Remove tags
|
||||
pub remove_tags: HashSet<Tag>,
|
||||
pub(crate) remove_tags: HashSet<Tag>,
|
||||
|
||||
/// Add dependencies
|
||||
pub(crate) add_dependencies: HashSet<TaskId>,
|
||||
|
||||
/// Remove dependencies
|
||||
pub(crate) remove_dependencies: HashSet<TaskId>,
|
||||
|
||||
/// Add annotation
|
||||
pub annotate: Option<String>,
|
||||
pub(crate) annotate: Option<String>,
|
||||
}
|
||||
|
||||
/// A single argument that is part of a modification, used internally to this module
|
||||
|
@ -59,6 +65,8 @@ enum ModArg<'a> {
|
|||
PlusTag(Tag),
|
||||
MinusTag(Tag),
|
||||
Wait(Option<DateTime<Utc>>),
|
||||
AddDependencies(Vec<TaskId>),
|
||||
RemoveDependencies(Vec<TaskId>),
|
||||
}
|
||||
|
||||
impl Modification {
|
||||
|
@ -82,6 +90,16 @@ impl Modification {
|
|||
ModArg::Wait(wait) => {
|
||||
acc.wait = Some(wait);
|
||||
}
|
||||
ModArg::AddDependencies(task_ids) => {
|
||||
for tid in task_ids {
|
||||
acc.add_dependencies.insert(tid);
|
||||
}
|
||||
}
|
||||
ModArg::RemoveDependencies(task_ids) => {
|
||||
for tid in task_ids {
|
||||
acc.remove_dependencies.insert(tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
acc
|
||||
}
|
||||
|
@ -90,6 +108,7 @@ impl Modification {
|
|||
Self::plus_tag,
|
||||
Self::minus_tag,
|
||||
Self::wait,
|
||||
Self::dependencies,
|
||||
// this must come last
|
||||
Self::description,
|
||||
)),
|
||||
|
@ -128,6 +147,17 @@ impl Modification {
|
|||
map_res(arg_matching(wait_colon), to_modarg)(input)
|
||||
}
|
||||
|
||||
fn dependencies(input: ArgList) -> IResult<ArgList, ModArg> {
|
||||
fn to_modarg(input: (bool, Vec<TaskId>)) -> Result<ModArg<'static>, ()> {
|
||||
Ok(if input.0 {
|
||||
ModArg::AddDependencies(input.1)
|
||||
} else {
|
||||
ModArg::RemoveDependencies(input.1)
|
||||
})
|
||||
}
|
||||
map_res(arg_matching(depends_colon), to_modarg)(input)
|
||||
}
|
||||
|
||||
pub(super) fn get_usage(u: &mut usage::Usage) {
|
||||
u.modifications.push(usage::Modification {
|
||||
syntax: "DESCRIPTION",
|
||||
|
@ -161,6 +191,19 @@ impl Modification {
|
|||
reports, e.g., `wait:3day` to wait for three days. With `wait:`, the time is
|
||||
un-set. See the documentation for the timestamp syntax.",
|
||||
});
|
||||
u.modifications.push(usage::Modification {
|
||||
syntax: "depends:<task-list>",
|
||||
summary: "Add task dependencies",
|
||||
description: "
|
||||
Add a dependency of this task on the given tasks. The tasks can be specified
|
||||
in the same syntax as for filters, e.g., `depends:13,94500c95`.",
|
||||
});
|
||||
u.modifications.push(usage::Modification {
|
||||
syntax: "depends:-<task-list>",
|
||||
summary: "Remove task dependencies",
|
||||
description: "
|
||||
Remove the dependency of this task on the given tasks.",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,6 +265,39 @@ mod test {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_deps() {
|
||||
let (input, modification) = Modification::parse(argv!["depends:13,e72b73d1-9e88"]).unwrap();
|
||||
assert_eq!(input.len(), 0);
|
||||
let mut deps = HashSet::new();
|
||||
deps.insert(TaskId::WorkingSetId(13));
|
||||
deps.insert(TaskId::PartialUuid("e72b73d1-9e88".into()));
|
||||
assert_eq!(
|
||||
modification,
|
||||
Modification {
|
||||
add_dependencies: deps,
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remove_deps() {
|
||||
let (input, modification) =
|
||||
Modification::parse(argv!["depends:-13,e72b73d1-9e88"]).unwrap();
|
||||
assert_eq!(input.len(), 0);
|
||||
let mut deps = HashSet::new();
|
||||
deps.insert(TaskId::WorkingSetId(13));
|
||||
deps.insert(TaskId::PartialUuid("e72b73d1-9e88".into()));
|
||||
assert_eq!(
|
||||
modification,
|
||||
Modification {
|
||||
remove_dependencies: deps,
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unset_wait() {
|
||||
let (input, modification) = Modification::parse(argv!["wait:"]).unwrap();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue