diff --git a/README.md b/README.md index d3699f9..7e47697 100644 --- a/README.md +++ b/README.md @@ -263,6 +263,17 @@ bartib list --from 2021-09-01 --to 2021-09-05 # list activities in a given ti bartib list --project "The most exciting project" # list activities for a given project ``` +### Edit activities + +```bash +bartib change -d "A new description" # change the description of the current activity +bartib change -p "Another project" # change the project for the current activity +bartib change -t 8:15 # change the start time of the current activity + +bartib edit # open the activity log in the editor you have defined in your `EDITOR` environment variable +bartib edit -e vim # open the activity log in a given editor +``` + ### Doing other stuff ```bash @@ -270,9 +281,6 @@ bartib current # show currently running activity bartib projects # list all projects ever used bartib projects -c # show current project only -bartib edit # open the activity log in the editor you have defined in your `EDITOR` environment variable -bartib edit -e vim # open the activity log in a given editor - bartib check # check your activity log for invalid lines bartib sanity # check for activities with logical errors (e.g activities with negative duration) ``` diff --git a/src/controller/manipulation.rs b/src/controller/manipulation.rs index 9bc01d1..66acb4b 100644 --- a/src/controller/manipulation.rs +++ b/src/controller/manipulation.rs @@ -2,10 +2,10 @@ use anyhow::{anyhow, bail, Context, Error, Result}; use chrono::NaiveDateTime; use std::process::Command; +use crate::conf; use crate::data::activity; use crate::data::bartib_file; use crate::data::getter; -use crate::conf; use crate::view::format_util; // starts a new activity @@ -52,6 +52,50 @@ fn save_new_activity( .context(format!("Could not write to file: {}", file_name)) } +pub fn change( + file_name: &str, + project_name: Option<&str>, + activity_description: Option<&str>, + time: Option, +) -> Result<()> { + let mut file_content = bartib_file::get_file_content(file_name)?; + + for line in file_content.iter_mut() { + if let Ok(activity) = &mut line.activity { + if !activity.is_stopped() { + let mut changed = false; + + if let Some(project_name) = project_name { + activity.project = project_name.to_string(); + changed = true; + } + + if let Some(activity_description) = activity_description { + activity.description = activity_description.to_string(); + changed = true; + } + + if let Some(time) = time { + activity.start = time; + changed = true; + } + + if changed { + println!( + "Changed activity: \"{}\" ({}) started at {}", + activity.description, + activity.project, + activity.start.format(conf::FORMAT_DATETIME) + ); + line.set_changed(); + } + } + } + } + bartib_file::write_to_file(file_name, &file_content) + .context(format!("Could not write to file: {}", file_name)) +} + // stops all currently running activities pub fn stop(file_name: &str, time: Option) -> Result<()> { let mut file_content = bartib_file::get_file_content(file_name)?; @@ -63,7 +107,7 @@ pub fn stop(file_name: &str, time: Option) -> Result<()> { // cancels all currently running activities pub fn cancel(file_name: &str) -> Result<()> { let file_content = bartib_file::get_file_content(file_name)?; - let mut new_file_content : Vec = Vec::new(); + let mut new_file_content: Vec = Vec::new(); for line in file_content { match &line.activity { @@ -71,14 +115,15 @@ pub fn cancel(file_name: &str) -> Result<()> { if activity.is_stopped() { new_file_content.push(line); } else { - println!("Canceled activity: \"{}\" ({}) started at {}", - activity.description, - activity.project, - activity.start.format(conf::FORMAT_DATETIME) + println!( + "Canceled activity: \"{}\" ({}) started at {}", + activity.description, + activity.project, + activity.start.format(conf::FORMAT_DATETIME) ); } - }, - Err(_) => new_file_content.push(line) + } + Err(_) => new_file_content.push(line), } } @@ -86,28 +131,34 @@ pub fn cancel(file_name: &str) -> Result<()> { .context(format!("Could not write to file: {}", file_name)) } - // continue last activity pub fn continue_last_activity( file_name: &str, project_name: Option<&str>, activity_description: Option<&str>, time: Option, - number: usize + number: usize, ) -> Result<()> { let mut file_content = bartib_file::get_file_content(file_name)?; - let descriptions_and_projects : Vec<(&String, &String)> = getter::get_descriptions_and_projects(&file_content); + let descriptions_and_projects: Vec<(&String, &String)> = + getter::get_descriptions_and_projects(&file_content); if descriptions_and_projects.is_empty() { bail!("No activity has been started before.") } if number > descriptions_and_projects.len() { - bail!(format!("Less than {} distinct activities have been logged yet", number)); + bail!(format!( + "Less than {} distinct activities have been logged yet", + number + )); } - let i = descriptions_and_projects.len().saturating_sub(number).saturating_sub(1); + let i = descriptions_and_projects + .len() + .saturating_sub(number) + .saturating_sub(1); let optional_description_and_project = descriptions_and_projects.get(i); if let Some((description, project)) = optional_description_and_project { @@ -119,7 +170,10 @@ pub fn continue_last_activity( stop_all_running_activities(&mut file_content, time); save_new_activity(file_name, &mut file_content, new_activity) } else { - bail!(format!("Less than {} distinct activities have been logged yet", number)); + bail!(format!( + "Less than {} distinct activities have been logged yet", + number + )); } } @@ -156,4 +210,4 @@ fn stop_all_running_activities( } } } -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index f5d5e4e..306c1dc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -126,6 +126,13 @@ fn main() -> Result<()> { ) .arg(&arg_time), ) + .subcommand( + SubCommand::with_name("change") + .about("changes the current activity") + .arg(&arg_description) + .arg(&arg_project) + .arg(&arg_time) + ) .subcommand( SubCommand::with_name("stop") .about("stops all currently running activities") @@ -251,6 +258,14 @@ fn run_subcommand(matches: &ArgMatches, file_name: &str) -> Result<()> { bartib::controller::manipulation::start(file_name, project_name, activity_description, time) } + ("change", Some(sub_m)) => { + let project_name = sub_m.value_of("project"); + let activity_description = sub_m.value_of("description"); + let time = get_time_argument_or_ignore(sub_m.value_of("time"), "-t/--time") + .map(|t| Local::today().naive_local().and_time(t)); + + bartib::controller::manipulation::change(file_name, project_name, activity_description, time) + } ("continue", Some(sub_m)) => { let project_name = sub_m.value_of("project"); let activity_description = sub_m.value_of("description");