diff --git a/src/cli_app.rs b/src/cli_app.rs index 3d9cf33..e6da6e5 100644 --- a/src/cli_app.rs +++ b/src/cli_app.rs @@ -1,4 +1,6 @@ use std::io; +use crate::DisplayArgs; + use super::todo_app::{App ,TodoList, Todo}; #[inline] @@ -32,7 +34,7 @@ impl <'a>CliApp <'a>{ #[inline] fn print_list(&self) { - for display in self.todo_app.display() { + for display in self.todo_app.display_current() { println!("{}", display); } } @@ -48,8 +50,8 @@ impl <'a>CliApp <'a>{ return Ok(()) } if self.todo_app.is_tree() { - let mut print_todo = PrintTodoTree::new(self.todo_app.args.show_done, self.todo_app.args.minimal_tree); - print_todo.print_list(&self.todo_app.todo_list, self.todo_app.args.done_string.as_str(), self.todo_app.args.undone_string.as_str()); + let mut print_todo = PrintTodoTree::new(self.todo_app.args.minimal_tree); + print_todo.print_list(&self.todo_app.todo_list, &self.todo_app.args.display_args); } else { self.print_list() } @@ -63,17 +65,15 @@ struct PrintTodoTree { should_print_indention: bool, is_last: bool, depth: usize, - show_done: bool, } impl PrintTodoTree { #[inline] - pub fn new(show_done: bool, should_print_indention:bool) -> Self { + pub fn new(should_print_indention:bool) -> Self { PrintTodoTree { was_last: vec![], is_last: false, depth: 0, - show_done, should_print_indention, } } @@ -88,9 +88,9 @@ impl PrintTodoTree { } #[inline] - pub fn print_list(&mut self, todo_list: &TodoList, done_str: &str, undone_str: &str) { + pub fn print_list(&mut self, todo_list: &TodoList, display_args: &DisplayArgs) { let mut todos = todo_list.undone.todos.clone(); - if self.show_done { + if display_args.show_done { todos.extend(todo_list.done.todos.clone()) } @@ -99,11 +99,11 @@ impl PrintTodoTree { if self.depth > 0 { self.print_indention(); } - self.print_todo(todo, done_str, undone_str); + self.print_todo(todo, display_args); if let Some(todo_list) = todo.dependency.todo_list() { let mut tree_child = self.tree_child(); - tree_child.print_list(todo_list, done_str, undone_str); + tree_child.print_list(todo_list, display_args); } if let Some(note) = todo.dependency.note() { @@ -113,8 +113,8 @@ impl PrintTodoTree { } #[inline] - fn print_todo(&self, todo: &Todo,done_str: &str, undone_str: &str) { - println!("{}", todo.display(Some(self.show_done), done_str, undone_str)); + fn print_todo(&self, todo: &Todo, display_args: &DisplayArgs) { + println!("{}", todo.display(&display_args)); } #[inline] diff --git a/src/main.rs b/src/main.rs index 03696a2..ec693af 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,21 @@ use todo_app::App; use fileio::get_todo_path; //}}} +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +pub struct DisplayArgs{ + /// Show done todos too + #[arg(short='d', long, default_value_t=false)] + show_done: bool, + + /// String before done todos + #[arg(long, default_value_t=String::from("[x] "))] + done_string: String, + + /// String before undone todos + #[arg(long, default_value_t=String::from("[ ] "))] + undone_string: String, +} /// A tree-like todo application that makes you smile #[derive(Parser, Debug)] @@ -44,13 +59,8 @@ pub struct Args { #[arg(long)] done_selected: bool, - /// String before done todos - #[arg(long, default_value_t=String::from("[x] "))] - done_string: String, - - /// String before undone todos - #[arg(long, default_value_t=String::from("[ ] "))] - undone_string: String, + #[command(flatten)] + display_args: DisplayArgs, /// Append todo #[arg(short='a', long)] @@ -68,10 +78,6 @@ pub struct Args { #[arg(short='l', long)] list: bool, - /// Show done todos too - #[arg(short='d', long)] - show_done: bool, - /// Enable TUI module at startup #[arg(short='m', long)] enable_module: bool, diff --git a/src/todo_app.rs b/src/todo_app.rs index ab03e4c..bfe9f30 100644 --- a/src/todo_app.rs +++ b/src/todo_app.rs @@ -73,7 +73,7 @@ impl App { } if self.args.done_selected { self.todo_list[sel_index].toggle_done(); - if !self.args.show_done { + if !self.args.display_args.show_done { self.selected.remove(iter_index); } should_write = true; @@ -108,7 +108,7 @@ impl App { #[inline] pub fn show_done(&self) -> bool { - self.args.show_done + self.args.display_args.show_done } #[inline] @@ -128,9 +128,10 @@ impl App { } #[inline] + /// fix done and undone lists of current list pub fn fix_done_undone(&mut self) { self.fix_dependency_done_undone(); - let show_done = self.args.show_done; + let show_done = self.args.display_args.show_done; let current_list = self.mut_current_list(); current_list.fix_undone(); if show_done { @@ -141,8 +142,9 @@ impl App { } #[inline] + /// fix done and undone lists of current todo's dependency fn fix_dependency_done_undone(&mut self) { - let show_done = self.args.show_done; + let show_done = self.args.display_args.show_done; if let Some(todo) = self.mut_todo() { let dep_list = &mut todo.dependency.todo_list; @@ -156,8 +158,8 @@ impl App { } - #[inline] + /// traverses up and fixes the undone todo, if the dependencies are done, recursively fn traverse_up_and_fix(&mut self) { while self.only_undone_empty() && !self.is_root() { self.traverse_up(); @@ -168,7 +170,7 @@ impl App { _ => {} } self.mut_current_list().fix_undone(); - if self.args.show_done { + if self.args.display_args.show_done { self.mut_current_list().fix_done(); } } @@ -183,7 +185,7 @@ impl App { return; } let mut todo_messages = self.current_list().undone.messages(); - if self.args.show_done { + if self.args.display_args.show_done { todo_messages.extend(self.current_list().done.messages()); } self.search_indexes = Vec::new(); @@ -213,10 +215,7 @@ impl App { #[inline] pub fn toggle_show_done(&mut self) { - self.args.show_done = !self.args.show_done; - // while self.only_undone_empty() && !self.prior_indexes.is_empty() { - // self.traverse_up() - // } + self.args.display_args.show_done = !self.args.display_args.show_done; self.search(None); } @@ -251,7 +250,7 @@ impl App { let was_done = self.todo().unwrap().done(); self.mut_todo().unwrap().toggle_done(); self.fix_done_undone(); - if self.args.show_done { + if self.args.display_args.show_done { let index = if was_done { self.current_list().undone.len()-1 } else { @@ -354,7 +353,7 @@ impl App { #[inline] pub fn is_todos_empty(&self) -> bool{ - if self.args.show_done { + if self.args.display_args.show_done { self.current_list().is_empty() } else { self.is_undone_empty() @@ -388,7 +387,7 @@ impl App { #[inline] pub fn len(&self) -> usize { - if self.args.show_done { + if self.args.display_args.show_done { self.current_list().len() } else { self.current_list().undone.len() @@ -529,8 +528,13 @@ impl App { } #[inline] - pub fn display(&self) -> Vec { - self.current_list().display(self.args.show_done, self.args.done_string.as_str(), self.args.undone_string.as_str()) + pub fn display_current(&self) -> Vec { + self.display_list(self.current_list()) + } + + #[inline] + pub fn display_list(&self, todo_list: &TodoList) -> Vec { + todo_list.display(&self.args.display_args) } #[inline] @@ -580,6 +584,7 @@ impl App { #[inline] pub fn paste_todo(&mut self) { + let todos_count = self.len(); match Todo::try_from(self.clipboard.get_text()) { Ok(mut todo) => { let todo_parent = TodoList::dependency_parent(&self.args.todo_path, true); @@ -587,7 +592,9 @@ impl App { let bottom = self.bottom()+1; let list = &mut self.mut_current_list(); list.push(todo); - self.index = list.reorder(bottom); + if todos_count != 0 { + self.index = list.reorder(bottom); + } }, _ => {}, }; @@ -613,7 +620,7 @@ impl App { #[inline] pub fn print_selected(&self) { for index in self.selected.clone() { - println!("{}", self.todo_list[index].display(Some(self.args.show_done), self.args.done_string.as_str(), self.args.undone_string.as_str())); + println!("{}", self.todo_list[index].display(&self.args.display_args)); } } } diff --git a/src/todo_app/todo.rs b/src/todo_app/todo.rs index 631898f..e07dcec 100644 --- a/src/todo_app/todo.rs +++ b/src/todo_app/todo.rs @@ -14,6 +14,7 @@ use schedule::Schedule; use note::{sha1, open_temp_editor}; use super::TodoList; +use crate::DisplayArgs; //}}} #[derive(Debug, PartialEq, Clone, Default)] @@ -170,16 +171,12 @@ impl Todo { } #[inline] - pub fn display(&self, show_done: Option, done_str: &str, undone_str: &str) -> String { - let show_done = match show_done { - None => true, - Some(value) => value, - }; - let done_string = if show_done { + pub fn display(&self, args: &DisplayArgs) -> String { + let done_string = if args.show_done { if self.done() { - done_str + args.done_string.as_str() } else { - undone_str + args.undone_string.as_str() } } else { "" @@ -315,6 +312,8 @@ impl Todo { #[cfg(test)] mod tests { + use clap::Parser; + use super::*; #[test] @@ -486,7 +485,7 @@ mod tests { }; let expected = "2. this one should be daily (Daily)"; - assert_eq!(test.display(Some(false), "[x]", "[ ]"), expected) + assert_eq!(test.display(&DisplayArgs::parse()), expected) } #[test] diff --git a/src/todo_app/todo_list.rs b/src/todo_app/todo_list.rs index d86d7c8..3ff3a45 100644 --- a/src/todo_app/todo_list.rs +++ b/src/todo_app/todo_list.rs @@ -4,7 +4,9 @@ use std::ops::{Index, IndexMut}; use std::io::{stdout, BufWriter, Write}; use std::io; use std::fs::read_to_string; + use super::Todo; +use crate::DisplayArgs; #[derive(Debug,PartialEq, Clone, Default)] pub struct TodoArray { @@ -66,8 +68,8 @@ impl TodoArray { self.todos.iter().map(|todo| todo.message.clone()).collect() } - pub fn display(&self, show_done: Option, done_str: &str, undone_str: &str) -> Vec { - self.todos.iter().map(|todo| todo.display(show_done, done_str, undone_str)).collect() + pub fn display(&self, args: &DisplayArgs) -> Vec { + self.todos.iter().map(|todo| todo.display(&args)).collect() } pub fn len(&self) -> usize { @@ -200,12 +202,11 @@ impl TodoList { self.undone.len() + self.done.len() } - pub fn display(&self, show_done: bool, done_str: &str, undone_str: &str) -> Vec { - let arg = Some(show_done); - let mut display_list = self.undone.display(arg, done_str, undone_str); + pub fn display(&self, display_args:&DisplayArgs) -> Vec { + let mut display_list = self.undone.display(display_args); - if show_done { - display_list.extend(self.done.display(arg, done_str, undone_str)); + if display_args.show_done { + display_list.extend(self.done.display(display_args)); } display_list } @@ -268,7 +269,7 @@ impl TodoList { } } - return output.clone(); + output.clone() } #[inline] diff --git a/src/tui_app.rs b/src/tui_app.rs index 777690f..b0b3fb4 100644 --- a/src/tui_app.rs +++ b/src/tui_app.rs @@ -417,7 +417,7 @@ impl<'a>TuiApp<'a>{ frame.render_widget(note_widget, dependency_layout); } if let Some(todo_list) = todo.dependency.todo_list() { - match create_todo_widget(&todo_list.display(self.todo_app.show_done(),self.todo_app.args.done_string.as_str(), self.todo_app.args.undone_string.as_str()), String::from("Todo dependencies")) { + match create_todo_widget(&self.todo_app.display_list(todo_list), String::from("Todo dependencies")) { TodoWidget::List(widget) => frame.render_widget(widget, dependency_layout), TodoWidget::Paragraph(widget) => frame.render_widget(widget, dependency_layout), } @@ -427,7 +427,7 @@ impl<'a>TuiApp<'a>{ #[inline] fn render_todos_widget(&self, frame: &mut Frame, list_state: &mut ListState, todo_layout: &Rc<[Rect]>) { - match create_todo_widget(&self.todo_app.display(), self.title()) { + match create_todo_widget(&self.todo_app.display_current(), self.title()) { TodoWidget::Paragraph(widget) => frame.render_widget(widget, todo_layout[1]), TodoWidget::List(widget) => frame.render_stateful_widget(widget, todo_layout[1], list_state), }