From 5c543f74f9723f1c1ea07f493c93072b3f5c97dd Mon Sep 17 00:00:00 2001 From: Dheepak Krishnamurthy Date: Sun, 12 May 2024 04:21:17 -0400 Subject: [PATCH] feat: Add task duplicate --- docs/keybindings.md | 2 ++ src/app.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++ src/keyconfig.rs | 5 +++++ 3 files changed, 56 insertions(+) diff --git a/docs/keybindings.md b/docs/keybindings.md index 3f46856f..ba4d363f 100644 --- a/docs/keybindings.md +++ b/docs/keybindings.md @@ -18,6 +18,8 @@ Keybindings for task report: e: task {selected} edit - Open selected task in editor + y: task {selected} duplicate - Duplicate tasks + j: {selected+=1} - Move down in task report k: {selected-=1} - Move up in task report diff --git a/src/app.rs b/src/app.rs index 7c860a71..0d5faf96 100644 --- a/src/app.rs +++ b/src/app.rs @@ -2265,6 +2265,47 @@ impl TaskwarriorTui { } } + pub fn task_duplicate(&mut self) -> Result<(), String> { + if self.tasks.is_empty() { + return Ok(()); + } + + let task_uuids = self.selected_task_uuids(); + + let mut command = std::process::Command::new("task"); + command.arg("rc.bulk=0"); + command.arg("rc.confirmation=off"); + command.arg("rc.dependency.confirmation=off"); + command.arg("rc.recurrence.confirmation=off"); + for task_uuid in &task_uuids { + command.arg(task_uuid.to_string()); + } + command.arg("duplicate"); + + let output = command.output(); + let r = match output { + Ok(o) => { + if o.status.success() { + Ok(()) + } else { + Err(format!("Modify failed. {}", String::from_utf8_lossy(&o.stdout))) + } + } + Err(_) => Err(format!( + "Cannot run `task {:?} duplicate`. Check documentation for more information", + task_uuids, + )), + }; + + if task_uuids.len() == 1 { + if let Some(uuid) = task_uuids.first() { + self.current_selection_uuid = Some(*uuid); + } + } + + r + } + pub async fn task_edit(&mut self) -> Result<(), String> { if self.tasks.is_empty() { return Ok(()); @@ -2617,6 +2658,14 @@ impl TaskwarriorTui { self.mode = Mode::Tasks(Action::Error); } } + } else if input == self.keyconfig.duplicate { + match self.task_duplicate() { + Ok(_) => self.update(true).await?, + Err(e) => { + self.error = Some(e); + self.mode = Mode::Tasks(Action::Error); + } + } } else if input == self.keyconfig.undo { if self.config.uda_task_report_prompt_on_undo { self.mode = Mode::Tasks(Action::UndoPrompt); diff --git a/src/keyconfig.rs b/src/keyconfig.rs index 87680d34..380b5b38 100644 --- a/src/keyconfig.rs +++ b/src/keyconfig.rs @@ -24,6 +24,7 @@ pub struct KeyConfig { pub select_all: KeyCode, pub undo: KeyCode, pub edit: KeyCode, + pub duplicate: KeyCode, pub modify: KeyCode, pub shell: KeyCode, pub log: KeyCode, @@ -70,6 +71,7 @@ impl Default for KeyConfig { select_all: KeyCode::Char('V'), undo: KeyCode::Char('u'), edit: KeyCode::Char('e'), + duplicate: KeyCode::Char('y'), modify: KeyCode::Char('m'), shell: KeyCode::Char('!'), log: KeyCode::Char('l'), @@ -123,6 +125,7 @@ impl KeyConfig { let select_all = Self::get_config("uda.taskwarrior-tui.keyconfig.select-all", data); let undo = Self::get_config("uda.taskwarrior-tui.keyconfig.undo", data); let edit = Self::get_config("uda.taskwarrior-tui.keyconfig.edit", data); + let duplicate = Self::get_config("uda.taskwarrior-tui.keyconfig.duplicate", data); let modify = Self::get_config("uda.taskwarrior-tui.keyconfig.modify", data); let shell = Self::get_config("uda.taskwarrior-tui.keyconfig.shell", data); let log = Self::get_config("uda.taskwarrior-tui.keyconfig.log", data); @@ -160,6 +163,7 @@ impl KeyConfig { self.select_all = select_all.unwrap_or(self.select_all); self.undo = undo.unwrap_or(self.undo); self.edit = edit.unwrap_or(self.edit); + self.duplicate = edit.unwrap_or(self.duplicate); self.modify = modify.unwrap_or(self.modify); self.shell = shell.unwrap_or(self.shell); self.log = log.unwrap_or(self.log); @@ -202,6 +206,7 @@ impl KeyConfig { &self.quick_tag, &self.undo, &self.edit, + &self.duplicate, &self.modify, &self.shell, &self.log,