complish 0.0.1

Core library for project-aware task management with git integration
Documentation
use std::{
  fmt::{Display, Formatter, Result as FmtResult},
  str::FromStr,
};

use eyre::{Error, Result, eyre};
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum TaskResolution {
  Cancelled,
  #[default]
  Completed,
  Delegated,
}

impl Display for TaskResolution {
  fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
    match self {
      Self::Cancelled => write!(f, "cancelled"),
      Self::Completed => write!(f, "completed"),
      Self::Delegated => write!(f, "delegated"),
    }
  }
}

impl FromStr for TaskResolution {
  type Err = Error;

  fn from_str(s: &str) -> Result<Self> {
    match s.to_lowercase().as_str() {
      "cancelled" => Ok(Self::Cancelled),
      "completed" => Ok(Self::Completed),
      "delegated" => Ok(Self::Delegated),
      _ => Err(eyre!("invalid task resolution")),
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;

  mod display {
    use pretty_assertions::assert_eq;

    use super::*;

    #[test]
    fn it_displays_correctly() {
      assert_eq!(TaskResolution::Cancelled.to_string(), "cancelled");
      assert_eq!(TaskResolution::Completed.to_string(), "completed");
      assert_eq!(TaskResolution::Delegated.to_string(), "delegated");
    }
  }

  mod from_str {
    use pretty_assertions::assert_eq;

    use super::*;

    #[test]
    fn it_parses_correctly() {
      assert_eq!(
        TaskResolution::from_str("cancelled").unwrap(),
        TaskResolution::Cancelled
      );
      assert_eq!(
        TaskResolution::from_str("completed").unwrap(),
        TaskResolution::Completed
      );
      assert_eq!(
        TaskResolution::from_str("delegated").unwrap(),
        TaskResolution::Delegated
      );
    }

    #[test]
    fn it_errors_on_invalid_input() {
      assert!(TaskResolution::from_str("invalid").is_err());
    }

    #[test]
    fn it_parses_case_insensitively() {
      for str in &["CANCELLED", "Cancelled", "CaNcElLeD"] {
        assert_eq!(
          TaskResolution::from_str(str).unwrap(),
          TaskResolution::Cancelled
        );
      }
    }
  }
}