todo_tree_core/
priority.rs

1use serde::{Deserialize, Serialize};
2
3/// Priority levels for different tag types
4#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
5pub enum Priority {
6    Low,
7    Medium,
8    High,
9    Critical,
10}
11
12impl Priority {
13    /// Infer priority from tag name
14    pub fn from_tag(tag: &str) -> Self {
15        match tag.to_uppercase().as_str() {
16            "BUG" | "FIXME" | "ERROR" => Priority::Critical,
17            "HACK" | "WARN" | "WARNING" | "FIX" => Priority::High,
18            "TODO" | "WIP" | "MAYBE" => Priority::Medium,
19            "NOTE" | "XXX" | "INFO" | "DOCS" | "PERF" | "TEST" | "IDEA" => Priority::Low,
20            _ => Priority::Medium,
21        }
22    }
23
24    /// Get emoji representation for the priority
25    pub fn emoji(&self) -> &'static str {
26        match self {
27            Priority::Critical => "🔴",
28            Priority::High => "🟡",
29            Priority::Medium => "🔵",
30            Priority::Low => "🟢",
31        }
32    }
33
34    /// Get display name for the priority
35    pub fn display_name(&self) -> &'static str {
36        match self {
37            Priority::Critical => "Critical",
38            Priority::High => "High",
39            Priority::Medium => "Medium",
40            Priority::Low => "Low",
41        }
42    }
43}
44
45impl std::fmt::Display for Priority {
46    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47        write!(f, "{}", self.display_name())
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn test_priority_from_tag() {
57        // Critical
58        assert_eq!(Priority::from_tag("BUG"), Priority::Critical);
59        assert_eq!(Priority::from_tag("FIXME"), Priority::Critical);
60        assert_eq!(Priority::from_tag("ERROR"), Priority::Critical);
61        // High
62        assert_eq!(Priority::from_tag("HACK"), Priority::High);
63        assert_eq!(Priority::from_tag("WARN"), Priority::High);
64        assert_eq!(Priority::from_tag("WARNING"), Priority::High);
65        assert_eq!(Priority::from_tag("FIX"), Priority::High);
66        // Medium
67        assert_eq!(Priority::from_tag("TODO"), Priority::Medium);
68        assert_eq!(Priority::from_tag("WIP"), Priority::Medium);
69        assert_eq!(Priority::from_tag("MAYBE"), Priority::Medium);
70        // Low
71        assert_eq!(Priority::from_tag("NOTE"), Priority::Low);
72        assert_eq!(Priority::from_tag("XXX"), Priority::Low);
73        assert_eq!(Priority::from_tag("INFO"), Priority::Low);
74        assert_eq!(Priority::from_tag("DOCS"), Priority::Low);
75        assert_eq!(Priority::from_tag("PERF"), Priority::Low);
76        assert_eq!(Priority::from_tag("TEST"), Priority::Low);
77        assert_eq!(Priority::from_tag("IDEA"), Priority::Low);
78    }
79
80    #[test]
81    fn test_priority_from_tag_case_variations() {
82        assert_eq!(Priority::from_tag("bug"), Priority::Critical);
83        assert_eq!(Priority::from_tag("Bug"), Priority::Critical);
84        assert_eq!(Priority::from_tag("hack"), Priority::High);
85        assert_eq!(Priority::from_tag("Hack"), Priority::High);
86        assert_eq!(Priority::from_tag("warn"), Priority::High);
87        assert_eq!(Priority::from_tag("wip"), Priority::Medium);
88        assert_eq!(Priority::from_tag("info"), Priority::Low);
89    }
90
91    #[test]
92    fn test_priority_from_unknown_tag() {
93        assert_eq!(Priority::from_tag("UNKNOWN"), Priority::Medium);
94        assert_eq!(Priority::from_tag("CUSTOM"), Priority::Medium);
95        assert_eq!(Priority::from_tag("RANDOM"), Priority::Medium);
96    }
97
98    #[test]
99    fn test_priority_ordering() {
100        assert!(Priority::Critical > Priority::High);
101        assert!(Priority::High > Priority::Medium);
102        assert!(Priority::Medium > Priority::Low);
103    }
104
105    #[test]
106    fn test_priority_emoji() {
107        assert_eq!(Priority::Critical.emoji(), "🔴");
108        assert_eq!(Priority::High.emoji(), "🟡");
109        assert_eq!(Priority::Medium.emoji(), "🔵");
110        assert_eq!(Priority::Low.emoji(), "🟢");
111    }
112
113    #[test]
114    fn test_priority_display_name() {
115        assert_eq!(Priority::Critical.display_name(), "Critical");
116        assert_eq!(Priority::High.display_name(), "High");
117        assert_eq!(Priority::Medium.display_name(), "Medium");
118        assert_eq!(Priority::Low.display_name(), "Low");
119    }
120
121    #[test]
122    fn test_priority_display() {
123        assert_eq!(format!("{}", Priority::Critical), "Critical");
124        assert_eq!(format!("{}", Priority::High), "High");
125        assert_eq!(format!("{}", Priority::Medium), "Medium");
126        assert_eq!(format!("{}", Priority::Low), "Low");
127    }
128
129    #[test]
130    fn test_priority_serialization() {
131        let priority = Priority::Critical;
132        let json = serde_json::to_string(&priority).unwrap();
133        let deserialized: Priority = serde_json::from_str(&json).unwrap();
134        assert_eq!(priority, deserialized);
135    }
136
137    #[test]
138    fn test_priority_equality() {
139        assert_eq!(Priority::Critical, Priority::Critical);
140        assert_ne!(Priority::Critical, Priority::High);
141    }
142}