mirror of
https://github.com/nikolassv/bartib
synced 2024-11-10 22:24:12 +00:00
list tasks of a certain date or date range
This commit is contained in:
parent
e1804a7d06
commit
5f03c20706
4 changed files with 105 additions and 15 deletions
|
@ -1,2 +1,3 @@
|
|||
pub static FORMAT_DATETIME : &str = "%F %R";
|
||||
pub static FORMAT_TIME : &str = "%R";
|
||||
pub static FORMAT_TIME : &str = "%R";
|
||||
pub static FORMAT_DATE : &str = "%F";
|
43
src/lib.rs
43
src/lib.rs
|
@ -1,4 +1,7 @@
|
|||
mod conf;
|
||||
use chrono::NaiveDate;
|
||||
use chrono::naive;
|
||||
|
||||
pub mod conf;
|
||||
mod project;
|
||||
mod task;
|
||||
mod table;
|
||||
|
@ -6,6 +9,13 @@ mod format_util;
|
|||
mod output;
|
||||
pub mod bartib_file;
|
||||
|
||||
pub struct TaskFilter {
|
||||
pub number_of_tasks: Option<usize>,
|
||||
pub from_date: Option<NaiveDate>,
|
||||
pub to_date: Option<NaiveDate>,
|
||||
pub date: Option<NaiveDate>
|
||||
}
|
||||
|
||||
// starts a new task
|
||||
pub fn start(file_name: &str, project_name: &str, task_description: &str) {
|
||||
let mut file_content = bartib_file::get_file_content(file_name);
|
||||
|
@ -39,14 +49,20 @@ pub fn list_running(file_name: &str) {
|
|||
// lists tracked tasks
|
||||
//
|
||||
// the tasks will be ordered chronologically.
|
||||
pub fn list(file_name: &str, number_of_tasks: Option<usize>) {
|
||||
pub fn list(file_name: &str, filter: TaskFilter, do_group_tasks: bool) {
|
||||
let file_content = bartib_file::get_file_content(file_name);
|
||||
let mut all_tasks : Vec<&task::Task> = get_tasks(&file_content).collect();
|
||||
let tasks = get_tasks(&file_content);
|
||||
let mut filtered_tasks : Vec<&task::Task> = filter_tasks(tasks, &filter).collect();
|
||||
|
||||
all_tasks.sort_by_key(|task| task.start);
|
||||
filtered_tasks.sort_by_key(|task| task.start);
|
||||
|
||||
let first_element = get_index_of_first_element(all_tasks.len(), number_of_tasks);
|
||||
output::list_tasks_grouped_by_date(&all_tasks[first_element .. all_tasks.len()]);
|
||||
let first_element = get_index_of_first_element(filtered_tasks.len(), filter.number_of_tasks);
|
||||
|
||||
if do_group_tasks {
|
||||
output::list_tasks_grouped_by_date(&filtered_tasks[first_element .. filtered_tasks.len()]);
|
||||
} else {
|
||||
output::list_tasks(&filtered_tasks[first_element .. filtered_tasks.len()], true);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_index_of_first_element(length: usize, sub: Option<usize>) -> usize {
|
||||
|
@ -78,4 +94,19 @@ fn get_tasks(file_content: &[bartib_file::Line]) -> impl Iterator<Item = &task::
|
|||
file_content.iter()
|
||||
.map(|line| line.task.as_ref())
|
||||
.filter_map(|task_result| task_result.ok())
|
||||
}
|
||||
|
||||
fn filter_tasks<'a>(tasks : impl Iterator<Item = &'a task::Task>, filter : &TaskFilter) -> impl Iterator<Item = &'a task::Task> {
|
||||
let from_date : NaiveDate;
|
||||
let to_date : NaiveDate;
|
||||
|
||||
if let Some(date) = filter.date {
|
||||
from_date = date;
|
||||
to_date = date;
|
||||
} else {
|
||||
from_date = filter.from_date.unwrap_or(naive::MIN_DATE);
|
||||
to_date = filter.to_date.unwrap_or(naive::MAX_DATE);
|
||||
}
|
||||
|
||||
tasks.filter(move |task| task.start.date() >= from_date && task.start.date() <= to_date)
|
||||
}
|
60
src/main.rs
60
src/main.rs
|
@ -1,4 +1,5 @@
|
|||
use clap::{App, AppSettings, Arg, SubCommand};
|
||||
use chrono::NaiveDate;
|
||||
|
||||
fn main() {
|
||||
let matches = App::new("bartib")
|
||||
|
@ -50,11 +51,43 @@ fn main() {
|
|||
.arg(
|
||||
Arg::with_name("number")
|
||||
.short("n")
|
||||
.long("number")
|
||||
.value_name("NUMBER")
|
||||
.help("maximum number of tasks to display")
|
||||
.required(false)
|
||||
.takes_value(true)
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("from_date")
|
||||
.long("from")
|
||||
.value_name("FROM_DATE")
|
||||
.help("begin of date range (inclusive)")
|
||||
.requires("to_date")
|
||||
.takes_value(true)
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("to_date")
|
||||
.long("to")
|
||||
.value_name("TO_DATE")
|
||||
.help("end of date range (inclusive)")
|
||||
.requires("from_date")
|
||||
.takes_value(true)
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("date")
|
||||
.short("d")
|
||||
.long("date")
|
||||
.value_name("DATE")
|
||||
.help("show tasks of a certain date only")
|
||||
.required(false)
|
||||
.conflicts_with_all(&["from_date", "to_date"])
|
||||
.takes_value(true)
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("no_grouping")
|
||||
.long("no_grouping")
|
||||
.help("do not group tasks by date in list")
|
||||
)
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
|
@ -71,8 +104,15 @@ fn main() {
|
|||
("stop", Some(_)) => bartib::stop(file_name),
|
||||
("current", Some(_)) => bartib::list_running(file_name),
|
||||
("list", Some(sub_m)) => {
|
||||
let number_of_tasks : Option<usize> = get_number_argument_or_ignore(sub_m.value_of("number"), "-n/--number");
|
||||
bartib::list(file_name, number_of_tasks)
|
||||
let filter = bartib::TaskFilter {
|
||||
number_of_tasks : get_number_argument_or_ignore(sub_m.value_of("number"), "-n/--number"),
|
||||
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")
|
||||
};
|
||||
|
||||
let do_group_tasks = !sub_m.is_present("no_grouping");
|
||||
bartib::list(file_name, filter, do_group_tasks);
|
||||
},
|
||||
_ => println!("Unknown command")
|
||||
}
|
||||
|
@ -92,3 +132,19 @@ fn get_number_argument_or_ignore(number_argument : Option<&str>, argument_name :
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn get_date_argument_or_ignore(date_argument : Option<&str>, argument_name : &str) -> Option<NaiveDate> {
|
||||
if let Some(date_string) = date_argument {
|
||||
let parsing_result = NaiveDate::parse_from_str(date_string, bartib::conf::FORMAT_DATE);
|
||||
|
||||
match parsing_result {
|
||||
Ok(date) => Some(date),
|
||||
Err(parsing_error) => {
|
||||
println!("Can not parse \"{}\" as date. Argument for {} is ignored ({})", date_string, argument_name, parsing_error);
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::table;
|
|||
use crate::conf;
|
||||
|
||||
// displays a table with tasks
|
||||
pub fn list_tasks(tasks: &[&task::Task]) {
|
||||
pub fn list_tasks(tasks: &[&task::Task], with_start_dates: bool) {
|
||||
if tasks.is_empty() {
|
||||
println!("No task to display");
|
||||
return
|
||||
|
@ -16,7 +16,7 @@ pub fn list_tasks(tasks: &[&task::Task]) {
|
|||
let mut task_table = table::Table::new(vec!["Started", "Stopped", "Description", "Project", "Duration"]);
|
||||
|
||||
tasks.iter()
|
||||
.map(get_task_table_row_without_dates)
|
||||
.map(|t| get_task_table_row(&t, with_start_dates))
|
||||
.for_each(|row| task_table.add_row(row));
|
||||
|
||||
println!("\n{}", task_table);
|
||||
|
@ -33,7 +33,7 @@ pub fn list_tasks_grouped_by_date(tasks: &[&task::Task]) {
|
|||
|
||||
for (date, task_list) in tasks_by_date {
|
||||
println!("{}", date);
|
||||
list_tasks(&task_list);
|
||||
list_tasks(&task_list, false);
|
||||
println!();
|
||||
}
|
||||
}
|
||||
|
@ -58,10 +58,10 @@ pub fn list_running_tasks(running_tasks: &[&task::Task]) {
|
|||
}
|
||||
}
|
||||
|
||||
// create a row for a task without showing dates
|
||||
// create a row for a task
|
||||
//
|
||||
// the date of the end is shown when it is not the same date as the start
|
||||
fn get_task_table_row_without_dates(task: &&task::Task) -> table::Row {
|
||||
fn get_task_table_row(task: &&task::Task, with_start_dates : bool) -> table::Row {
|
||||
let end = task.end.map_or_else(
|
||||
|| "-".to_string(),
|
||||
|end| if task.start.date() == end.date() {
|
||||
|
@ -72,8 +72,10 @@ fn get_task_table_row_without_dates(task: &&task::Task) -> table::Row {
|
|||
}
|
||||
);
|
||||
|
||||
let start_format = if with_start_dates {conf::FORMAT_DATETIME} else {conf::FORMAT_TIME};
|
||||
|
||||
table::Row::new(vec![
|
||||
task.start.format(conf::FORMAT_TIME).to_string(),
|
||||
task.start.format(start_format).to_string(),
|
||||
end,
|
||||
task.description.clone(),
|
||||
task.project.to_string(),
|
||||
|
|
Loading…
Reference in a new issue