use std::path::PathBuf;
use anyhow::{anyhow, Context, Result};
use clap::{Parser, Subcommand};
use toddi::{config::Config, get_project, get_top_task};
mod tui;
#[derive(Parser)]
#[command(version, about)]
struct Cli {
#[arg(short, long)]
todo_txt: Option<PathBuf>,
#[arg(short, long)]
done_txt: Option<PathBuf>,
#[arg(short, long)]
config_file: Option<PathBuf>,
#[command(subcommand)]
command: Option<Commands>,
}
#[derive(Subcommand)]
enum Commands {
Focus { projects: Vec<String> },
}
fn main() -> Result<()> {
let args = Cli::parse();
let config = Config::load(args.config_file);
let mut todo_txt_path: PathBuf;
let mut done_txt_path: PathBuf;
match config {
Ok(config) => {
todo_txt_path = config.todo_file;
done_txt_path = config.done_file;
}
Err(err) => {
return Err(anyhow!("Could not load configuration!\nconfig: {:?}", err));
}
}
if let Some(input) = args.todo_txt.as_deref() {
todo_txt_path = input.to_path_buf();
}
if let Some(input) = args.done_txt.as_deref() {
done_txt_path = input.to_path_buf();
}
let todos = get_file_content(&todo_txt_path)?;
let dones = get_file_content(&done_txt_path)?;
match &args.command {
Some(Commands::Focus { projects }) => {
for project in projects {
if let Some(project) = get_project(project.clone(), &todos, &dones)? {
tui::display_project_status(project);
} else {
tui::display_no_project_found(project);
}
}
}
None => {
if let Some(task) = get_top_task(&todos)? {
if task.project.is_empty() {
tui::display_task(task);
} else if let Some(project) = get_project(task.project.clone(), &todos, &dones)? {
tui::display_project_status(project);
} else {
return Err(anyhow!("It should not be possible to match a project in a task and then not be able to retrieve it!\ntask: {:?}", task));
}
} else {
tui::display_empty_todo_list();
}
}
}
Ok(())
}
fn get_file_content(file_path: &std::path::Path) -> Result<String> {
std::fs::read_to_string(file_path)
.with_context(|| format!("could not read file `{}`", file_path.display()))
}