mirror of
https://github.com/nikolassv/bartib
synced 2024-12-11 04:32:27 +00:00
Merge branch 'dev/list-last-tasks-with-index'
This commit is contained in:
commit
e1f06a0270
6 changed files with 227 additions and 114 deletions
78
README.md
78
README.md
|
@ -24,7 +24,9 @@ Print help information:
|
||||||
bartib -h
|
bartib -h
|
||||||
```
|
```
|
||||||
|
|
||||||
### Start a new activity
|
### Tracking activities
|
||||||
|
|
||||||
|
#### Start a new activity
|
||||||
|
|
||||||
Start a new activity with a short description and an associated project:
|
Start a new activity with a short description and an associated project:
|
||||||
|
|
||||||
|
@ -40,7 +42,7 @@ The `-t/--time` option specifies at which time of the current day the new activi
|
||||||
bartib start -p "The name of the associated project" -d "A description of the activity" -t 13:45
|
bartib start -p "The name of the associated project" -d "A description of the activity" -t 13:45
|
||||||
```
|
```
|
||||||
|
|
||||||
### Stop a running activity
|
#### Stop a running activity
|
||||||
|
|
||||||
Stops the currently running activity:
|
Stops the currently running activity:
|
||||||
|
|
||||||
|
@ -50,17 +52,47 @@ bartib stop
|
||||||
|
|
||||||
The `-t/--time` option specifies at which time of the current day the activities stop.
|
The `-t/--time` option specifies at which time of the current day the activities stop.
|
||||||
|
|
||||||
### Continue the last activity
|
#### Continue a recent activity
|
||||||
|
|
||||||
|
Instead of typing a project and a description for each new activity, it is possible to continue a recent activity. The `last` subcommand prints a list of recently
|
||||||
|
used projects and descriptions. Per default it prints 10 lines. The `-n/--number` option may be used to print a longer list.
|
||||||
|
|
||||||
```
|
```
|
||||||
bartib continue [-p "Another project"] [-d "Another description"]
|
bartib last [-n 25]
|
||||||
```
|
```
|
||||||
|
|
||||||
This continues the last activity. If an activity is currently tracked, bartib stops and restarts this activity. The associated project and description may be overwritten by setting a `-p / --project` or `-d / --description` option.
|
In the list each activity will be asigned an index. This index can be used with the `continue` subcommand to restart the selected activitiy. The description
|
||||||
|
and or the project of this activity can be overwritten for the new activity with the help of the `-d/--description` respectively the `-p/--project` argument.
|
||||||
|
The `-t/--time` option may be used to specify at which time of the current day the activity should be restarted. If an activity is currently tracked, bartib
|
||||||
|
stops it at the time the new activity starts.
|
||||||
|
|
||||||
The `-t/--time` option specifies at which time of the current day the activity (re-)starts.
|
```
|
||||||
|
bartib continue [3] [-p "Another project"] [-d "Another description"] [-t 8:45]
|
||||||
|
```
|
||||||
|
|
||||||
### List activities
|
The default value for the index parameter is `0` which always points to the most recently tracked activity. Therefore `bartib continue` without any parameters
|
||||||
|
or options may be used to continue the most recently tracked activity.
|
||||||
|
|
||||||
|
### Reporting and listing activities
|
||||||
|
|
||||||
|
#### Create a report
|
||||||
|
|
||||||
|
This will create a report of how much time has been spent on which projects and activities:
|
||||||
|
|
||||||
|
```
|
||||||
|
bartib report
|
||||||
|
```
|
||||||
|
|
||||||
|
The `report` subcommand accepts most of the arguments that the `list` subcommand accepts:
|
||||||
|
|
||||||
|
```
|
||||||
|
bartib report --today
|
||||||
|
bartib report --yesterday
|
||||||
|
bartib report --from 2021-09-01 --to 2021-09-05
|
||||||
|
bartib report --date 2021-09-03
|
||||||
|
```
|
||||||
|
|
||||||
|
#### List activities
|
||||||
|
|
||||||
All activities:
|
All activities:
|
||||||
|
|
||||||
|
@ -93,30 +125,10 @@ bartib list --today
|
||||||
bartib list --yesterday
|
bartib list --yesterday
|
||||||
```
|
```
|
||||||
|
|
||||||
### List all currently running activities
|
### Miscellaneous commands
|
||||||
|
|
||||||
```
|
|
||||||
bartib current
|
|
||||||
```
|
|
||||||
|
|
||||||
### Create a report
|
#### Edit activities
|
||||||
|
|
||||||
This will create a report of how much time has been spent on which projects and activities:
|
|
||||||
|
|
||||||
```
|
|
||||||
bartib report
|
|
||||||
```
|
|
||||||
|
|
||||||
The `report` subcommand accepts most of the arguments that the `list` subcommand accepts:
|
|
||||||
|
|
||||||
```
|
|
||||||
bartib report --today
|
|
||||||
bartib report --yesterday
|
|
||||||
bartib report --from 2021-09-01 --to 2021-09-05
|
|
||||||
bartib report --date 2021-09-03
|
|
||||||
```
|
|
||||||
|
|
||||||
### Edit activities
|
|
||||||
|
|
||||||
To change tracked activities, just open the file with your activities log in any text editor. To facilitate this, bartib offers the `edit` subcommand:
|
To change tracked activities, just open the file with your activities log in any text editor. To facilitate this, bartib offers the `edit` subcommand:
|
||||||
|
|
||||||
|
@ -130,13 +142,15 @@ This will open your log in the editor you have defined in your `EDITOR` environm
|
||||||
bartib edit -e vim
|
bartib edit -e vim
|
||||||
```
|
```
|
||||||
|
|
||||||
### Show last activity
|
|
||||||
|
#### List all currently running activities
|
||||||
|
|
||||||
```
|
```
|
||||||
bartib last
|
bartib current
|
||||||
```
|
```
|
||||||
|
|
||||||
### List all projects
|
|
||||||
|
#### List all projects
|
||||||
|
|
||||||
This command lists all projects for which an activity has ever been logged:
|
This command lists all projects for which an activity has ever been logged:
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,12 @@ pub fn list(file_name: &str, filter: getter::ActivityFilter, do_group_activities
|
||||||
|
|
||||||
if do_group_activities {
|
if do_group_activities {
|
||||||
list::list_activities_grouped_by_date(
|
list::list_activities_grouped_by_date(
|
||||||
&filtered_activities[first_element..filtered_activities.len()],
|
&filtered_activities[first_element..],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let with_start_dates = !filter.date.is_some();
|
let with_start_dates = !filter.date.is_some();
|
||||||
list::list_activities(
|
list::list_activities(
|
||||||
&filtered_activities[first_element..filtered_activities.len()],
|
&filtered_activities[first_element..],
|
||||||
with_start_dates,
|
with_start_dates,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -61,16 +61,13 @@ pub fn list_projects(file_name: &str) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// return last finished activity
|
// return last finished activity
|
||||||
pub fn display_last_activity(file_name: &str) -> Result<()> {
|
pub fn list_last_activities(file_name: &str, number: usize) -> Result<()> {
|
||||||
let file_content = bartib_file::get_file_content(file_name)?;
|
let file_content = bartib_file::get_file_content(file_name)?;
|
||||||
|
|
||||||
let last_activity = getter::get_last_activity_by_end(&file_content);
|
let descriptions_and_projects : Vec<(&String, &String)> = getter::get_descriptions_and_projects(&file_content);
|
||||||
|
let first_element = descriptions_and_projects.len().saturating_sub(number);
|
||||||
|
|
||||||
if let Some(activity) = last_activity {
|
list::list_descriptions_and_projects(&descriptions_and_projects[first_element..]);
|
||||||
list::display_single_activity(&activity);
|
|
||||||
} else {
|
|
||||||
println!("No activity has been finished yet.")
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
|
@ -67,24 +67,33 @@ pub fn continue_last_activity(
|
||||||
project_name: Option<&str>,
|
project_name: Option<&str>,
|
||||||
activity_description: Option<&str>,
|
activity_description: Option<&str>,
|
||||||
time: Option<NaiveDateTime>,
|
time: Option<NaiveDateTime>,
|
||||||
|
number: usize
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut file_content = bartib_file::get_file_content(file_name)?;
|
let mut file_content = bartib_file::get_file_content(file_name)?;
|
||||||
|
|
||||||
let optional_last_activity =
|
let descriptions_and_projects : Vec<(&String, &String)> = getter::get_descriptions_and_projects(&file_content);
|
||||||
getter::get_last_activity_by_start(&file_content).or(getter::get_last_activity_by_end(&file_content));
|
|
||||||
|
|
||||||
if let Some(last_activity) = optional_last_activity {
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
let new_activity = activity::Activity::start(
|
let new_activity = activity::Activity::start(
|
||||||
project_name.unwrap_or(&last_activity.project).to_string(),
|
project_name.unwrap_or(project).to_string(),
|
||||||
activity_description
|
activity_description.unwrap_or(description).to_string(),
|
||||||
.unwrap_or(&last_activity.description)
|
|
||||||
.to_string(),
|
|
||||||
time,
|
time,
|
||||||
);
|
);
|
||||||
stop_all_running_activities(&mut file_content, time);
|
stop_all_running_activities(&mut file_content, time);
|
||||||
save_new_activity(file_name, &mut file_content, new_activity)
|
save_new_activity(file_name, &mut file_content, new_activity)
|
||||||
} else {
|
} else {
|
||||||
bail!("No activity has been started before.")
|
bail!(format!("Less than {} distinct activities have been logged yet", number));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
use std::collections::HashSet;
|
||||||
use chrono::{naive, NaiveDate};
|
use chrono::{naive, NaiveDate};
|
||||||
|
|
||||||
use crate::data::activity;
|
use crate::data::activity;
|
||||||
use crate::data::bartib_file;
|
use crate::data::bartib_file;
|
||||||
|
use crate::data::activity::Activity;
|
||||||
|
|
||||||
pub struct ActivityFilter {
|
pub struct ActivityFilter {
|
||||||
pub number_of_activities: Option<usize>,
|
pub number_of_activities: Option<usize>,
|
||||||
|
@ -10,6 +12,38 @@ pub struct ActivityFilter {
|
||||||
pub date: Option<NaiveDate>,
|
pub date: Option<NaiveDate>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_descriptions_and_projects(file_content: &[bartib_file::Line]) -> Vec<(&String, &String)> {
|
||||||
|
let mut activities : Vec<&activity::Activity> = get_activities(file_content).collect();
|
||||||
|
get_descriptions_and_projects_from_activities(&mut activities)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_descriptions_and_projects_from_activities<'a>(activities: &mut [&'a Activity]) -> Vec<(&'a String, &'a String)> {
|
||||||
|
activities.sort_by_key(|activity| activity.start);
|
||||||
|
|
||||||
|
/* each activity should be placed in the list in the descending order of when it had been
|
||||||
|
started last. To achieve this we reverse the order of the activities before we extract the
|
||||||
|
set of descriptions and activities. Afterwards we also reverse the list of descriptions and
|
||||||
|
activities.
|
||||||
|
|
||||||
|
e.g. if tasks have been started in this order: a, b, c, a, c the list of descriptions and
|
||||||
|
activities should have this order: b, a, c
|
||||||
|
*/
|
||||||
|
activities.reverse();
|
||||||
|
|
||||||
|
let mut known_descriptions_and_projects: HashSet<(&String, &String)> = HashSet::new();
|
||||||
|
let mut descriptions_and_projects: Vec<(&String, &String)> = Vec::new();
|
||||||
|
|
||||||
|
for description_and_project in activities.iter().map(|a| (&a.description, &a.project)) {
|
||||||
|
if !known_descriptions_and_projects.contains(&description_and_project) {
|
||||||
|
known_descriptions_and_projects.insert(description_and_project);
|
||||||
|
descriptions_and_projects.push(description_and_project);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptions_and_projects.reverse();
|
||||||
|
descriptions_and_projects
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_running_activities(file_content: &[bartib_file::Line]) -> Vec<&activity::Activity> {
|
pub fn get_running_activities(file_content: &[bartib_file::Line]) -> Vec<&activity::Activity> {
|
||||||
get_activities(file_content)
|
get_activities(file_content)
|
||||||
.filter(|activity| !activity.is_stopped())
|
.filter(|activity| !activity.is_stopped())
|
||||||
|
@ -43,7 +77,7 @@ pub fn filter_activities<'a>(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_last_activity_by_end(file_content: &Vec<bartib_file::Line>) -> Option<&activity::Activity> {
|
pub fn get_last_activity_by_end(file_content: &[bartib_file::Line]) -> Option<&activity::Activity> {
|
||||||
get_activities(&file_content)
|
get_activities(&file_content)
|
||||||
.filter(|activity| activity.is_stopped())
|
.filter(|activity| activity.is_stopped())
|
||||||
.max_by_key(|activity| activity.end.unwrap_or(naive::MIN_DATE.and_hms(0, 0, 0)))
|
.max_by_key(|activity| activity.end.unwrap_or(naive::MIN_DATE.and_hms(0, 0, 0)))
|
||||||
|
@ -52,3 +86,36 @@ pub fn get_last_activity_by_end(file_content: &Vec<bartib_file::Line>) -> Option
|
||||||
pub fn get_last_activity_by_start(file_content: &Vec<bartib_file::Line>) -> Option<&activity::Activity> {
|
pub fn get_last_activity_by_start(file_content: &Vec<bartib_file::Line>) -> Option<&activity::Activity> {
|
||||||
get_activities(&file_content).max_by_key(|activity| activity.start)
|
get_activities(&file_content).max_by_key(|activity| activity.start)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_descriptions_and_projects_test_simple() {
|
||||||
|
let a1 = activity::Activity::start("p1".to_string(), "d1".to_string(), None);
|
||||||
|
let a2 = activity::Activity::start("p1".to_string(), "d1".to_string(), None);
|
||||||
|
let a3 = activity::Activity::start("p2".to_string(), "d1".to_string(), None);
|
||||||
|
let mut activities = vec![&a1, &a2, &a3];
|
||||||
|
|
||||||
|
let descriptions_and_projects = get_descriptions_and_projects_from_activities(&mut activities);
|
||||||
|
|
||||||
|
assert_eq!(descriptions_and_projects.len(), 2);
|
||||||
|
assert_eq!(*descriptions_and_projects.get(0).unwrap(), (&"d1".to_string(), &"p1".to_string()));
|
||||||
|
assert_eq!(*descriptions_and_projects.get(1).unwrap(), (&"d1".to_string(), &"p2".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_descriptions_and_projects_test_restarted_activitiy() {
|
||||||
|
let a1 = activity::Activity::start("p1".to_string(), "d1".to_string(), None);
|
||||||
|
let a2 = activity::Activity::start("p2".to_string(), "d1".to_string(), None);
|
||||||
|
let a3 = activity::Activity::start("p1".to_string(), "d1".to_string(), None);
|
||||||
|
let mut activities = vec![&a1, &a2, &a3];
|
||||||
|
|
||||||
|
let descriptions_and_projects = get_descriptions_and_projects_from_activities(&mut activities);
|
||||||
|
|
||||||
|
assert_eq!(descriptions_and_projects.len(), 2);
|
||||||
|
assert_eq!(*descriptions_and_projects.get(0).unwrap(), (&"d1".to_string(), &"p2".to_string()));
|
||||||
|
assert_eq!(*descriptions_and_projects.get(1).unwrap(), (&"d1".to_string(), &"p1".to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
121
src/main.rs
121
src/main.rs
|
@ -53,6 +53,18 @@ fn main() -> Result<()> {
|
||||||
.conflicts_with_all(&["from_date", "to_date", "date", "today"])
|
.conflicts_with_all(&["from_date", "to_date", "date", "today"])
|
||||||
.takes_value(false);
|
.takes_value(false);
|
||||||
|
|
||||||
|
let arg_description = Arg::with_name("description")
|
||||||
|
.short("d")
|
||||||
|
.value_name("DESCRIPTION")
|
||||||
|
.help("the description of the new activity")
|
||||||
|
.takes_value(true);
|
||||||
|
|
||||||
|
let arg_project = Arg::with_name("project")
|
||||||
|
.short("p")
|
||||||
|
.value_name("PROJECT")
|
||||||
|
.help("the project to which the new activity belongs")
|
||||||
|
.takes_value(true);
|
||||||
|
|
||||||
let matches = App::new("bartib")
|
let matches = App::new("bartib")
|
||||||
.version("0.1")
|
.version("0.1")
|
||||||
.author("Nikolas Schmidt-Voigt <nikolas.schmidt-voigt@posteo.de>")
|
.author("Nikolas Schmidt-Voigt <nikolas.schmidt-voigt@posteo.de>")
|
||||||
|
@ -70,40 +82,22 @@ fn main() -> Result<()> {
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("start")
|
SubCommand::with_name("start")
|
||||||
.about("starts a new activity")
|
.about("starts a new activity")
|
||||||
.arg(
|
.arg(&arg_description)
|
||||||
Arg::with_name("project")
|
.arg(&arg_project)
|
||||||
.short("p")
|
|
||||||
.value_name("PROJECT")
|
|
||||||
.help("the project to which the new activity belong")
|
|
||||||
.required(true)
|
|
||||||
.takes_value(true),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("description")
|
|
||||||
.short("d")
|
|
||||||
.value_name("DESCRIPTION")
|
|
||||||
.help("a description of the new activity")
|
|
||||||
.required(true)
|
|
||||||
.takes_value(true),
|
|
||||||
)
|
|
||||||
.arg(&arg_time),
|
.arg(&arg_time),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("continue")
|
SubCommand::with_name("continue")
|
||||||
.about("continues the last activity")
|
.about("continues a previous activity")
|
||||||
|
.arg(&arg_description)
|
||||||
|
.arg(&arg_project)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("project")
|
Arg::with_name("number")
|
||||||
.short("p")
|
.value_name("NUMBER")
|
||||||
.value_name("PROJECT")
|
.help("the number of the activity to continue (see subcommand `last`)")
|
||||||
.help("the project to which the new activity belong")
|
.required(false)
|
||||||
.takes_value(true),
|
.takes_value(true)
|
||||||
)
|
.default_value("0")
|
||||||
.arg(
|
|
||||||
Arg::with_name("description")
|
|
||||||
.short("d")
|
|
||||||
.value_name("DESCRIPTION")
|
|
||||||
.help("a description of the new activity")
|
|
||||||
.takes_value(true),
|
|
||||||
)
|
)
|
||||||
.arg(&arg_time),
|
.arg(&arg_time),
|
||||||
)
|
)
|
||||||
|
@ -147,7 +141,20 @@ fn main() -> Result<()> {
|
||||||
.arg(&arg_today)
|
.arg(&arg_today)
|
||||||
.arg(&arg_yesterday),
|
.arg(&arg_yesterday),
|
||||||
)
|
)
|
||||||
.subcommand(SubCommand::with_name("last").about("displays last finished acitivity"))
|
.subcommand(
|
||||||
|
SubCommand::with_name("last")
|
||||||
|
.about("displays the descriptions and projects of recent activities")
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("number")
|
||||||
|
.short("n")
|
||||||
|
.long("number")
|
||||||
|
.value_name("NUMBER")
|
||||||
|
.help("maximum number of lines to display")
|
||||||
|
.required(false)
|
||||||
|
.takes_value(true)
|
||||||
|
.default_value("10")
|
||||||
|
)
|
||||||
|
)
|
||||||
.subcommand(SubCommand::with_name("projects").about("list all projects"))
|
.subcommand(SubCommand::with_name("projects").about("list all projects"))
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("edit")
|
SubCommand::with_name("edit")
|
||||||
|
@ -184,8 +191,12 @@ fn run_subcommand(matches: &ArgMatches, file_name: &str) -> Result<()> {
|
||||||
let activity_description = sub_m.value_of("description");
|
let activity_description = sub_m.value_of("description");
|
||||||
let time = get_time_argument_or_ignore(sub_m.value_of("time"), "-t/--time")
|
let time = get_time_argument_or_ignore(sub_m.value_of("time"), "-t/--time")
|
||||||
.map(|t| Local::today().naive_local().and_time(t));
|
.map(|t| Local::today().naive_local().and_time(t));
|
||||||
|
let number = get_number_argument_or_ignore(
|
||||||
|
sub_m.value_of("number"),
|
||||||
|
"-n/--number",
|
||||||
|
).unwrap_or(0);
|
||||||
|
|
||||||
bartib::controller::manipulation::continue_last_activity(file_name, project_name, activity_description, time)
|
bartib::controller::manipulation::continue_last_activity(file_name, project_name, activity_description, time, number)
|
||||||
}
|
}
|
||||||
("stop", Some(sub_m)) => {
|
("stop", Some(sub_m)) => {
|
||||||
let time = get_time_argument_or_ignore(sub_m.value_of("time"), "-t/--time")
|
let time = get_time_argument_or_ignore(sub_m.value_of("time"), "-t/--time")
|
||||||
|
@ -195,25 +206,6 @@ fn run_subcommand(matches: &ArgMatches, file_name: &str) -> Result<()> {
|
||||||
}
|
}
|
||||||
("current", Some(_)) => bartib::controller::list::list_running(file_name),
|
("current", Some(_)) => bartib::controller::list::list_running(file_name),
|
||||||
("list", Some(sub_m)) => {
|
("list", Some(sub_m)) => {
|
||||||
let mut filter = bartib::data::getter::ActivityFilter {
|
|
||||||
number_of_activities: None,
|
|
||||||
from_date: get_date_argument_or_ignore(sub_m.value_of("from_date"), "--from"),
|
|
||||||
to_date: get_date_argument_or_ignore(sub_m.value_of("to_date"), "--to"),
|
|
||||||
date: get_date_argument_or_ignore(sub_m.value_of("date"), "-d/--date"),
|
|
||||||
};
|
|
||||||
|
|
||||||
if sub_m.is_present("today") {
|
|
||||||
filter.date = Some(Local::now().naive_local().date());
|
|
||||||
}
|
|
||||||
|
|
||||||
if sub_m.is_present("yesterday") {
|
|
||||||
filter.date = Some(Local::now().naive_local().date() - Duration::days(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
let do_group_activities = !sub_m.is_present("no_grouping") && !filter.date.is_some();
|
|
||||||
bartib::controller::list::list(file_name, filter, do_group_activities)
|
|
||||||
}
|
|
||||||
("report", Some(sub_m)) => {
|
|
||||||
let mut filter = bartib::data::getter::ActivityFilter {
|
let mut filter = bartib::data::getter::ActivityFilter {
|
||||||
number_of_activities: get_number_argument_or_ignore(
|
number_of_activities: get_number_argument_or_ignore(
|
||||||
sub_m.value_of("number"),
|
sub_m.value_of("number"),
|
||||||
|
@ -232,10 +224,35 @@ fn run_subcommand(matches: &ArgMatches, file_name: &str) -> Result<()> {
|
||||||
filter.date = Some(Local::now().naive_local().date() - Duration::days(1));
|
filter.date = Some(Local::now().naive_local().date() - Duration::days(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let do_group_activities = !sub_m.is_present("no_grouping") && !filter.date.is_some();
|
||||||
|
bartib::controller::list::list(file_name, filter, do_group_activities)
|
||||||
|
}
|
||||||
|
("report", Some(sub_m)) => {
|
||||||
|
let mut filter = bartib::data::getter::ActivityFilter {
|
||||||
|
number_of_activities: None,
|
||||||
|
from_date: get_date_argument_or_ignore(sub_m.value_of("from_date"), "--from"),
|
||||||
|
to_date: get_date_argument_or_ignore(sub_m.value_of("to_date"), "--to"),
|
||||||
|
date: get_date_argument_or_ignore(sub_m.value_of("date"), "-d/--date"),
|
||||||
|
};
|
||||||
|
|
||||||
|
if sub_m.is_present("today") {
|
||||||
|
filter.date = Some(Local::now().naive_local().date());
|
||||||
|
}
|
||||||
|
|
||||||
|
if sub_m.is_present("yesterday") {
|
||||||
|
filter.date = Some(Local::now().naive_local().date() - Duration::days(1));
|
||||||
|
}
|
||||||
|
|
||||||
bartib::controller::report::show_report(file_name, filter)
|
bartib::controller::report::show_report(file_name, filter)
|
||||||
}
|
}
|
||||||
("projects", Some(_)) => bartib::controller::list::list_projects(file_name),
|
("projects", Some(_)) => bartib::controller::list::list_projects(file_name),
|
||||||
("last", Some(_)) => bartib::controller::list::display_last_activity(file_name),
|
("last", Some(sub_m)) => {
|
||||||
|
let number = get_number_argument_or_ignore(
|
||||||
|
sub_m.value_of("number"),
|
||||||
|
"-n/--number",
|
||||||
|
).unwrap_or(10);
|
||||||
|
bartib::controller::list::list_last_activities(file_name, number)
|
||||||
|
}
|
||||||
("edit", Some(sub_m)) => {
|
("edit", Some(sub_m)) => {
|
||||||
let optional_editor_command = sub_m.value_of("editor");
|
let optional_editor_command = sub_m.value_of("editor");
|
||||||
bartib::controller::manipulation::start_editor(file_name, optional_editor_command)
|
bartib::controller::manipulation::start_editor(file_name, optional_editor_command)
|
||||||
|
|
|
@ -91,20 +91,29 @@ pub fn list_running_activities(running_activities: &[&activity::Activity]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// displays a single activity
|
// display a list of projects and descriptions with index number
|
||||||
pub fn display_single_activity(activity: &activity::Activity) {
|
pub fn list_descriptions_and_projects(descriptions_and_projects : &[(&String, &String)]) {
|
||||||
println!("Begin: {}", activity.start.format(conf::FORMAT_DATETIME));
|
if descriptions_and_projects.is_empty() {
|
||||||
|
println!("No activities have been tracked yet");
|
||||||
|
} else {
|
||||||
|
let mut descriptions_and_projects_table = table::Table::new(vec![
|
||||||
|
" # ".to_string(),
|
||||||
|
"Description".to_string(),
|
||||||
|
"Project".to_string()
|
||||||
|
]);
|
||||||
|
|
||||||
if let Some(end) = activity.end {
|
let mut i = descriptions_and_projects.len();
|
||||||
println!("End: {}", end.format(conf::FORMAT_DATETIME));
|
|
||||||
println!(
|
for (description, project) in descriptions_and_projects {
|
||||||
"Duration: {}",
|
i = i.saturating_sub(1);
|
||||||
format_util::format_duration(&activity.get_duration())
|
|
||||||
);
|
descriptions_and_projects_table.add_row(
|
||||||
|
table::Row::new(vec![format!("[{}]", i), description.to_string(), project.to_string()])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("\n{}", descriptions_and_projects_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Project: {}", activity.project);
|
|
||||||
println!("Description: {}", activity.description);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a row for a activity
|
// create a row for a activity
|
||||||
|
|
Loading…
Reference in a new issue