mod commands;
use clap::{App, Arg, SubCommand};
use commands::task;
use std::{env, path::Path};
use color_eyre::eyre::Result;
fn main() -> Result<()> {
color_eyre::install()?;
let matches = App::new("rustask")
.version("0.7")
.author("bsdinis <baltasar.dinis@tecnico.ulisboa.pt>")
.about("Task Manager")
.arg(
Arg::with_name("file")
.short("-f")
.help("task file")
.takes_value(true),
)
.subcommand(
SubCommand::with_name("list")
.aliases(&["l"])
.help("List tasks")
.arg(
Arg::with_name("project")
.help("project to be listed")
.index(1),
),
)
.subcommand(
SubCommand::with_name("listall")
.aliases(&["la"])
.help("List all tasks")
.arg(
Arg::with_name("project")
.help("project to be listed")
.index(1),
),
)
.subcommand(
SubCommand::with_name("rename")
.aliases(&["r"])
.help("Rename a project")
.arg(
Arg::with_name("project")
.help("project to rename")
.index(1)
.required(true),
)
.arg(
Arg::with_name("name")
.help("new name")
.index(2)
.required(true),
),
)
.subcommand(
SubCommand::with_name("add")
.aliases(&["a"])
.help("Add a task")
.arg(
Arg::with_name("project")
.help("project to assign the task to")
.index(1)
.required(true),
)
.arg(
Arg::with_name("task")
.help("the task to be added")
.index(2)
.required(true),
)
.arg(
Arg::with_name("priority")
.help("priority (urgency) for the task")
.takes_value(true)
.short("-p"),
)
.arg(
Arg::with_name("deadline")
.help("deadline of the task")
.takes_value(true)
.short("-d"),
),
)
.subcommand(
SubCommand::with_name("done")
.aliases(&["d"])
.help("Conclude the task")
.arg(
Arg::with_name("project")
.help("project where the task is assigned to")
.index(1)
.required(true),
)
.arg(Arg::with_name("task index").index(2).required(true)),
)
.subcommand(
SubCommand::with_name("move")
.aliases(&["m"])
.help("Move a task between projects")
.arg(
Arg::with_name("old project")
.help("project where the task is")
.index(1)
.required(true),
)
.arg(
Arg::with_name("id")
.help("id of the task being moved")
.index(2)
.required(true),
)
.arg(
Arg::with_name("new project")
.help("new project for the task")
.index(3)
.required(true),
),
)
.subcommand(
SubCommand::with_name("edit")
.aliases(&["e"])
.help("Change a task")
.arg(
Arg::with_name("project")
.help("project to where the task assigned to")
.index(1)
.required(true),
)
.arg(
Arg::with_name("task index")
.help("the index of the task to be changed")
.index(2)
.required(true),
)
.arg(
Arg::with_name("descript")
.help("the new description")
.index(3),
)
.arg(
Arg::with_name("priority")
.help("priority (urgency) for the task")
.takes_value(true)
.short("-p"),
)
.arg(
Arg::with_name("deadline")
.help("deadline of the task")
.takes_value(true)
.short("-d"),
),
)
.get_matches();
if !matches.is_present("file") && env::var("RUSTASK_TASKFILE").is_err() {
eprintln!("Could not find rustask file");
eprintln!("Maybe set RUSTASK_TASKFILE env var or pass in -f flag");
std::process::exit(1);
}
let task_location = if matches.is_present("file") {
matches.value_of("file").unwrap().to_string()
} else {
env::var("RUSTASK_TASKFILE")?
};
let path = Path::new(&task_location);
match matches.subcommand_name() {
Some("list") => {
let sub_matches = matches.subcommand_matches("list").unwrap();
let project = sub_matches
.value_of("project")
.and_then(|s| s.to_string().parse::<String>().ok());
commands::list(path, project)?
}
Some("listall") => {
let sub_matches = matches.subcommand_matches("listall").unwrap();
let project = sub_matches
.value_of("project")
.and_then(|s| s.to_string().parse::<String>().ok());
commands::list_all(path, project)?
}
Some("rename") => {
let sub_matches = matches.subcommand_matches("rename").unwrap();
let project = sub_matches.value_of("project").unwrap().parse::<String>()?;
let name = sub_matches.value_of("name").unwrap().parse::<String>()?;
commands::rename(path, project, name)?
}
Some("move") => {
let sub_matches = matches.subcommand_matches("move").unwrap();
let old_project = sub_matches
.value_of("old project")
.unwrap()
.parse::<String>()?;
let id = sub_matches.value_of("id").unwrap().parse::<usize>()?;
let new_project = sub_matches
.value_of("new project")
.unwrap()
.parse::<String>()?;
commands::move_task(path, old_project, id, new_project)?
}
Some("add") => {
let sub_matches = matches.subcommand_matches("add").unwrap();
let task_descript = sub_matches.value_of("task").unwrap().parse::<String>()?;
let project = sub_matches
.value_of("project")
.unwrap_or("")
.parse::<String>()?;
let priority = sub_matches
.value_of("priority")
.and_then(|s| s.parse::<task::Priority>().ok());
let deadline = if let Some(p_str) = sub_matches.value_of("deadline") {
Some(task::parse_deadline(p_str)?)
} else {
None
};
let task_b = task::TaskBuilder::new(task_descript);
let task_b = if let Some(p) = priority {
task_b.priority(p)
} else {
task_b
};
let task_b = if let Some(d) = deadline {
task_b.deadline(d)
} else {
task_b
};
commands::add_task(path, task_b.build(), project)?;
}
Some("done") => {
let sub_matches = matches.subcommand_matches("done").unwrap();
let project = sub_matches
.value_of("project")
.unwrap_or("")
.parse::<String>()?;
if let Ok(idx) = sub_matches.value_of("task index").unwrap().parse::<usize>() {
let task = commands::remove_task(path, idx, project)?;
println!("finished task {}: {}", idx, task);
} else {
eprintln!("error: Refer to the task done by its id");
}
}
Some("edit") => {
let sub_matches = matches.subcommand_matches("edit").unwrap();
let project = sub_matches
.value_of("project")
.unwrap_or("")
.parse::<String>()?;
if let Ok(idx) = sub_matches.value_of("task index").unwrap().parse::<usize>() {
let task_descript = sub_matches
.value_of("descript")
.and_then(|d_str| d_str.parse::<String>().ok());
let priority = sub_matches
.value_of("priority")
.and_then(|p_str| p_str.parse::<task::Priority>().ok());
let deadline = if let Some(p_str) = sub_matches.value_of("deadline") {
Some(task::parse_deadline(p_str)?)
} else {
None
};
commands::edit_task(path, idx, project, task_descript, priority, deadline)?;
} else {
eprintln!("error: Refer to the task done by its id");
}
}
_ => {
eprintln!("No subcommand supplied");
}
};
Ok(())
}