toddi 0.3.2

A TODO focuser built on top of todo.txt
Documentation
use core::f64;
use std::io::{self, Write};

use indicatif::{ProgressBar, ProgressStyle};
use toddi::model::{Project, Task};

/// Displays Project status on the terminal.
pub(crate) fn display_project_status(project: &Project) {
    let pos = project.done as u64;
    let len = project.todo as u64 + pos;

    let completion = pos as f64 / len as f64;
    let msg = if completion == 1.0 {
        "DONE"
    } else if completion > 0.9 {
        "Almost there!!"
    } else if completion > 0.5 {
        "Good Progress!"
    } else if completion > 0.2 {
        "Progressing"
    } else if completion > 0. {
        "Getting started"
    } else {
        ""
    };

    println!();
    if !project.name.is_empty() {
        display_project_name(&project.name);
    }
    if len > 0 {
        // There is at least 1 task
        let bar = ProgressBar::new(len);
        let progress_style = match ProgressStyle::with_template(
            "[{pos}/{len}] {bar:40.cyan/blue} {percent}% done - {msg}",
        ) {
            Ok(style) => style,
            Err(err) => panic!("cannot handle TemplateError from indicatif.\n{}", err),
        };
        bar.set_style(progress_style.progress_chars("##-"));
        bar.set_position(pos);
        bar.set_message(msg);
        bar.abandon();
        if let Some(current_task) = project.clone().get_current_task() {
            println!("todo: <<< {} >>>", current_task.description)
        }
    } else {
        println!("This project contains no task as of now.")
    }
}

fn display_project_name(name: &str) {
    println!("==> Project {}", name.to_uppercase());
}

pub(crate) fn display_project_not_found(name: &str) {
    println!();
    println!("Project `{}` contains no task as of now.", name);
}

pub(crate) fn display_task(task: Task) {
    let project = task.project;
    if !project.is_empty() {
        display_project_name(&project);
    }
    println!("todo: <<< {} >>>", task.description);
}

pub(crate) fn display_empty_todo_list() {
    println!();
    println!("todo list is empty!")
}

pub(crate) fn display_no_projects() {
    println!("No project to dispay on.")
}

pub(crate) fn query_user() -> Result<String, anyhow::Error> {
    print!("Is it done? (y/n/q): ");
    io::stdout().flush()?;
    let mut buffer = String::new();
    io::stdin()
        .read_line(&mut buffer)
        .expect("Failed to read user input");
    Ok(buffer)
}