From 15eccfc785175c34768d4fedffafb448cd4ffd03 Mon Sep 17 00:00:00 2001 From: Dheepak Krishnamurthy Date: Tue, 15 Feb 2022 18:32:57 -0700 Subject: [PATCH] =?UTF-8?q?feat:=20Use=20all=20tasks=20for=20completion=20?= =?UTF-8?q?=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++------- src/config.rs | 10 +++++++ 2 files changed, 74 insertions(+), 10 deletions(-) diff --git a/src/app.rs b/src/app.rs index 9b82762..d3bc834 100644 --- a/src/app.rs +++ b/src/app.rs @@ -167,6 +167,7 @@ pub struct TaskwarriorTui { pub filter: LineBuffer, pub modify: LineBuffer, pub tasks: Vec, + pub all_tasks: Vec, pub task_details: HashMap, pub marked: HashSet, // stores index of current task that is highlighted @@ -240,6 +241,7 @@ impl TaskwarriorTui { dirty: true, task_table_state: TableState::default(), tasks: vec![], + all_tasks: vec![], task_details: HashMap::new(), marked: HashSet::new(), current_selection: 0, @@ -1286,6 +1288,9 @@ impl TaskwarriorTui { self.last_export = Some(std::time::SystemTime::now()); self.task_report_table.export_headers(None, &self.report)?; self.export_tasks()?; + if self.config.uda_task_report_use_all_tasks_for_completion { + self.export_all_tasks()?; + } self.contexts.update_data()?; self.projects.update_data()?; self.update_tags(); @@ -1607,6 +1612,49 @@ impl TaskwarriorTui { } } + pub fn export_all_tasks(&mut self) -> Result<()> { + let mut task = Command::new("task"); + + task.arg("rc.json.array=on") + .arg("rc.confirmation=off") + .arg("rc.json.depends.array=on") + .arg("rc.color=off") + .arg("rc._forcecolor=off"); + // .arg("rc.verbose:override=false"); + + task.arg("export"); + + task.arg("all"); + + info!("Running `{:?}`", task); + let output = task.output()?; + let data = String::from_utf8_lossy(&output.stdout); + let error = String::from_utf8_lossy(&output.stderr); + + if output.status.success() { + if let Ok(imported) = import(data.as_bytes()) { + self.all_tasks = imported; + info!("Imported {} tasks", self.tasks.len()); + self.error = None; + if self.mode == Mode::Tasks(Action::Error) { + self.mode = self.previous_mode.clone().unwrap_or(Mode::Tasks(Action::Report)); + self.previous_mode = None; + } + } else { + self.error = Some(format!("Unable to parse output of `{:?}`:\n`{:?}`", task, data)); + self.mode = Mode::Tasks(Action::Error); + debug!("Unable to parse output: {:?}", data); + } + } else { + self.error = Some(format!( + "Cannot run `{:?}` - ({}) error:\n{}", + &task, output.status, error + )); + } + + Ok(()) + } + pub fn export_tasks(&mut self) -> Result<()> { let mut task = Command::new("task"); @@ -3392,6 +3440,12 @@ impl TaskwarriorTui { pub fn update_completion_list(&mut self) { self.completion_list.clear(); + let tasks = if self.config.uda_task_report_use_all_tasks_for_completion { + &self.all_tasks + } else { + &self.tasks + }; + if let Mode::Tasks(Action::Modify | Action::Filter | Action::Annotate | Action::Add | Action::Log) = self.mode { for s in vec![ "project:".to_string(), @@ -3440,7 +3494,7 @@ impl TaskwarriorTui { self.completion_list.insert(("priority".to_string(), p)); } let virtual_tags = self.task_report_table.virtual_tags.clone(); - for task in &self.tasks { + for task in tasks { if let Some(tags) = task.tags() { for tag in tags { if !virtual_tags.contains(tag) { @@ -3450,7 +3504,7 @@ impl TaskwarriorTui { } } } - for task in &self.tasks { + for task in tasks { if let Some(tags) = task.tags() { for tag in tags { if !virtual_tags.contains(tag) { @@ -3459,7 +3513,7 @@ impl TaskwarriorTui { } } } - for task in &self.tasks { + for task in tasks { if let Some(project) = task.project() { let p = if project.contains(' ') { format!(r#""{}""#, &project) @@ -3469,7 +3523,7 @@ impl TaskwarriorTui { self.completion_list.insert(("project".to_string(), p)); } } - for task in &self.tasks { + for task in tasks { if let Some(date) = task.due() { let now = Local::now(); let date = TimeZone::from_utc_datetime(now.offset(), date); @@ -3485,7 +3539,7 @@ impl TaskwarriorTui { self.completion_list.insert(("due".to_string(), s)); } } - for task in &self.tasks { + for task in tasks { if let Some(date) = task.wait() { let now = Local::now(); let date = TimeZone::from_utc_datetime(now.offset(), date); @@ -3501,7 +3555,7 @@ impl TaskwarriorTui { self.completion_list.insert(("wait".to_string(), s)); } } - for task in &self.tasks { + for task in tasks { if let Some(date) = task.scheduled() { let now = Local::now(); let date = TimeZone::from_utc_datetime(now.offset(), date); @@ -3517,7 +3571,7 @@ impl TaskwarriorTui { self.completion_list.insert(("scheduled".to_string(), s)); } } - for task in &self.tasks { + for task in tasks { if let Some(date) = task.end() { let now = Local::now(); let date = TimeZone::from_utc_datetime(now.offset(), date); @@ -3548,17 +3602,17 @@ impl TaskwarriorTui { Mode::Tasks(Action::Add | Action::Annotate | Action::Log) => { let i = get_start_word_under_cursor(self.command.as_str(), self.command.pos()); let input = self.command.as_str()[i..self.command.pos()].to_string(); - self.completion_list.input(input, self.command.as_str().to_string()); + self.completion_list.input(input, "".to_string()); } Mode::Tasks(Action::Modify) => { let i = get_start_word_under_cursor(self.modify.as_str(), self.modify.pos()); let input = self.modify.as_str()[i..self.modify.pos()].to_string(); - self.completion_list.input(input, self.modify.as_str().to_string()); + self.completion_list.input(input, "".to_string()); } Mode::Tasks(Action::Filter) => { let i = get_start_word_under_cursor(self.filter.as_str(), self.filter.pos()); let input = self.filter.as_str()[i..self.filter.pos()].to_string(); - self.completion_list.input(input, self.filter.as_str().to_string()); + self.completion_list.input(input, "".to_string()); } _ => {} } diff --git a/src/config.rs b/src/config.rs index a2a34f6..214ea38 100644 --- a/src/config.rs +++ b/src/config.rs @@ -54,6 +54,7 @@ pub struct Config { pub uda_prefill_task_metadata: bool, pub uda_reset_filter_on_esc: bool, pub uda_task_detail_prefetch: usize, + pub uda_task_report_use_all_tasks_for_completion: bool, pub uda_task_report_show_info: bool, pub uda_task_report_looping: bool, pub uda_task_report_jump_to_task_on_add: bool, @@ -109,6 +110,7 @@ impl Config { let uda_prefill_task_metadata = Self::get_uda_prefill_task_metadata(data); let uda_reset_filter_on_esc = Self::get_uda_reset_filter_on_esc(data); let uda_task_detail_prefetch = Self::get_uda_task_detail_prefetch(data); + let uda_task_report_use_all_tasks_for_completion = Self::get_uda_task_report_use_all_tasks_for_completion(data); let uda_task_report_show_info = Self::get_uda_task_report_show_info(data); let uda_task_report_looping = Self::get_uda_task_report_looping(data); let uda_task_report_jump_to_task_on_add = Self::get_uda_task_report_jump_to_task_on_add(data); @@ -165,6 +167,7 @@ impl Config { uda_prefill_task_metadata, uda_reset_filter_on_esc, uda_task_detail_prefetch, + uda_task_report_use_all_tasks_for_completion, uda_task_report_show_info, uda_task_report_looping, uda_task_report_jump_to_task_on_add, @@ -510,6 +513,13 @@ impl Config { .unwrap_or(10) } + fn get_uda_task_report_use_all_tasks_for_completion(data: &str) -> bool { + Self::get_config("uda.taskwarrior-tui.task-report.use-all-tasks-for-completion", data) + .unwrap_or_default() + .get_bool() + .unwrap_or(false) + } + fn get_uda_task_report_show_info(data: &str) -> bool { Self::get_config("uda.taskwarrior-tui.task-report.show-info", data) .unwrap_or_default()