feat: more adaptive tag filtering

Make tag exclusions more persistent
This commit is contained in:
xeruf 2024-08-25 15:37:05 +03:00
parent dedda147c0
commit f381608b4c
3 changed files with 20 additions and 15 deletions

View File

@ -95,7 +95,7 @@ To stop time-tracking completely, simply move to the root of all tasks.
- `TASK` - create task
+ prefix with space if you want a task to start with a command character
+ copy in text with newlines to create one task per line
- `.` - clear filters
- `.` - clear all filters
- `.TASK`
+ activate task by id
+ match by task name prefix: if one or more tasks match, filter / activate (tries case-sensitive then case-insensitive)
@ -125,9 +125,9 @@ Dot or slash can be repeated to move to parent tasks before acting.
Property Filters:
- `#TAG1 TAG2` - set tag filter (empty: list all used tags)
- `+TAG` - add tag filter
- `-TAG` - remove tag filters by prefix
- `#TAG1 TAG2` - set tag filter
- `+TAG` - add tag filter (empty: list all used tags)
- `-TAG` - remove tag filters (by prefix)
- `?STATUS` - filter by status (type or description) - plain `?` to reset, `??` to show all
- `@AUTHOR` - filter by time or author (pubkey, or `@` for self, TBI: id prefix, name prefix)
- TBI: `**INT` - filter by priority

View File

@ -536,24 +536,24 @@ async fn main() -> Result<()> {
}
Some('#') =>
match arg {
Some(arg) => tasks.set_tags(arg.split_whitespace().map(|s| Hashtag(s.to_string()).into())),
None => {
println!("Hashtags of all known tasks:\n{}", tasks.all_hashtags().join(" "));
continue;
}
}
tasks.set_tags(arg_default.split_whitespace().map(|s| Hashtag(s.to_string()).into())),
Some('+') =>
match arg {
Some(arg) => tasks.add_tag(arg.to_string()),
None => tasks.clear_filter()
None => {
println!("Hashtags of all known tasks:\n{}", tasks.all_hashtags().join(" ").italic());
if tasks.has_tag_filter() {
println!("Use # to remove tag filters and . to remove all filters.")
}
continue;
}
}
Some('-') =>
match arg {
Some(arg) => tasks.remove_tag(arg),
None => tasks.clear_filter()
None => tasks.clear_filters()
}
Some('(') => {
@ -597,6 +597,8 @@ async fn main() -> Result<()> {
tasks.move_to(pos.cloned());
if dots > 1 {
info!("Moving up {} tasks", dots - 1)
} else {
tasks.clear_filters();
}
} else if let Ok(depth) = slice.parse::<i8>() {
if pos != tasks.get_position_ref() {

View File

@ -505,15 +505,18 @@ impl Tasks {
self.view = view;
}
pub(crate) fn clear_filter(&mut self) {
pub(crate) fn clear_filters(&mut self) {
self.view.clear();
self.tags.clear();
self.tags_excluded.clear();
info!("Removed all filters");
}
pub(crate) fn has_tag_filter(&self) -> bool {
!self.tags.is_empty() || !self.tags_excluded.is_empty()
}
pub(crate) fn set_tags(&mut self, tags: impl IntoIterator<Item=Tag>) {
self.tags_excluded.clear();
self.tags.clear();
self.tags.extend(tags);
}