diff --git a/src/cli/add.rs b/src/cli/add.rs index 475b277..b304b3d 100644 --- a/src/cli/add.rs +++ b/src/cli/add.rs @@ -16,14 +16,14 @@ pub fn execute(repo: impl Repository, args: Args) { match res { Ok(task) => { - println!("Task was added successfully"); + println!("The task was added successfully"); println!(" {}", task.name); if let Some(link) = task.link { println!(" link: {}", link); } } Err(err) => { - eprintln!("Cannot insert data: {}", err); + eprintln!("Cannot insert a new task: {}", err); } } diff --git a/src/cli/edit.rs b/src/cli/edit.rs index 43566b2..02bee6f 100644 --- a/src/cli/edit.rs +++ b/src/cli/edit.rs @@ -1,7 +1,7 @@ use std::io::Write; -use std::path::PathBuf; -use crate::{CurrentTaskInfo, Task}; +use crate::repo::{self, Repository}; +use crate::CurrentTaskInfo; #[derive(clap::Args)] pub struct Args { @@ -19,33 +19,32 @@ pub struct Args { pub struct Request { pub args: Args, pub current_task_info: Option, - pub tasks: Vec, - pub tasks_file_path: PathBuf, } -pub fn execute(mut req: Request) { +pub fn execute(repo: impl Repository, mut req: Request) { if req.current_task_info.is_some() { panic!("You can edit task only when you don't have an active task, yet"); } - let idx = req.args.idx; - if idx == 0 || idx > req.tasks.len() { - panic!("invalid index"); - } + let args = req.args; - let mut task = &mut req.tasks[idx - 1]; - if let Some(name) = req.args.name { - task.name = name; + let res = repo.update_task( + args.idx, + repo::UpdateTaskData { + name: args.name, + link: args.no_link.then(|| None).or(args.link.map(Some)), + }, + ); + match res { + Ok(task) => { + println!("The task was changed successfully"); + println!(" {}", task.name); + if let Some(link) = task.link { + println!(" link: {}", link); + } + } + Err(err) => { + eprintln!("Cannot update the task: {}", err); + } } - if let Some(link) = req.args.link { - task.link = Some(link); - } else if req.args.no_link { - task.link = None; - } - - let mut file = std::fs::File::create(&req.tasks_file_path).unwrap(); - file.write_all(&serde_json::to_vec(&req.tasks).unwrap()) - .unwrap(); - - println!("changed"); } diff --git a/src/domain.rs b/src/domain.rs index 05f8920..f9dbeb2 100644 --- a/src/domain.rs +++ b/src/domain.rs @@ -1,3 +1,5 @@ +pub type TaskId = usize; + pub struct Task { pub name: String, pub link: Option, diff --git a/src/main.rs b/src/main.rs index 6c8734f..0c6f98d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,12 +55,13 @@ fn main() { cli::add::execute(repo, args); } cli::SubCommand::Edit(args) => { - cli::edit::execute(cli::edit::Request { - args, - current_task_info, - tasks, - tasks_file_path, - }); + cli::edit::execute( + repo, + cli::edit::Request { + args, + current_task_info, + }, + ); } cli::SubCommand::Remove(args) => { cli::remove::execute(cli::remove::Request { diff --git a/src/repo.rs b/src/repo.rs index f2e54c5..2eb691f 100755 --- a/src/repo.rs +++ b/src/repo.rs @@ -26,8 +26,19 @@ pub struct InsertTaskData { link: Option, } +pub struct UpdateTaskData { + name: Option, + link: Option>, +} + pub trait Repository { fn get_tasks(&self) -> Result, Error>; + fn update_task( + &self, + id: domain::TaskId, + update_data: UpdateTaskData, + ) -> Result; + fn insert_task(&self, insert_data: InsertTaskData) -> Result; } diff --git a/src/repo/fs.rs b/src/repo/fs.rs index 750f85f..2cb5eaa 100644 --- a/src/repo/fs.rs +++ b/src/repo/fs.rs @@ -2,7 +2,7 @@ use std::fs::File; use std::io::Write; use crate::domain; -use crate::repo::{Error, InsertTaskData, Repository}; +use crate::repo::{Error, InsertTaskData, Repository, UpdateTaskData}; use serde::{Deserialize, Serialize}; use xdg::BaseDirectories; @@ -41,6 +41,32 @@ impl Repository for FsRepo { .map(|tasks| tasks.into_iter().map(Task::into).collect()) } + fn update_task( + &self, + id: domain::TaskId, + update_data: UpdateTaskData, + ) -> Result { + let mut tasks = self.get_tasks_impl()?; + if id == 0 || id > tasks.len() { + return Err(Error::NotFound); + } + + let mut task = &mut tasks[id]; + if let Some(name) = update_data.name { + task.name = name; + } + + if let Some(link) = update_data.link { + task.link = link; + } + + let new_task = task.clone(); + + self.save_tasks_impl(tasks)?; + + Ok(new_task.into()) + } + fn insert_task(&self, insert_data: InsertTaskData) -> Result { let new_task = Task { name: insert_data.name, @@ -50,13 +76,7 @@ impl Repository for FsRepo { let mut tasks = self.get_tasks_impl()?; tasks.push(new_task.clone()); - let file_path = self - .xdg_dirs - .place_data_file(DATA_FILE) - .map_err(|_| Error::InsertData)?; - let mut file = File::create(&file_path).map_err(|_| Error::InsertData)?; - let new_data = serde_json::to_vec(&tasks).map_err(|_| Error::InvalidData)?; - file.write_all(&new_data).map_err(|_| Error::InsertData); + self.save_tasks_impl(tasks)?; Ok(new_task.into()) } @@ -69,4 +89,14 @@ impl FsRepo { .map_err(|_| Error::NotFound) .and_then(|file| serde_json::from_reader(file).map_err(|_| Error::InvalidData)) } + + fn save_tasks_impl(&self, tasks: Vec) -> Result<(), Error> { + let file_path = self + .xdg_dirs + .place_data_file(DATA_FILE) + .map_err(|_| Error::InsertData)?; + let mut file = File::create(&file_path).map_err(|_| Error::InsertData)?; + let new_data = serde_json::to_vec(&tasks).map_err(|_| Error::InvalidData)?; + file.write_all(&new_data).map_err(|_| Error::InsertData) + } }