diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app.rs | 10 | ||||
-rw-r--r-- | src/command.rs | 4 | ||||
-rw-r--r-- | src/habit/bit.rs | 10 | ||||
-rw-r--r-- | src/habit/count.rs | 10 | ||||
-rw-r--r-- | src/habit/prelude.rs | 4 | ||||
-rw-r--r-- | src/habit/traits.rs | 28 | ||||
-rw-r--r-- | src/views.rs | 8 |
7 files changed, 55 insertions, 19 deletions
@@ -190,11 +190,15 @@ impl App { | |||
190 | pub fn parse_command(&mut self, input: &str) { | 190 | pub fn parse_command(&mut self, input: &str) { |
191 | let c = Command::from_string(input); | 191 | let c = Command::from_string(input); |
192 | match c { | 192 | match c { |
193 | Command::Add(name, kind, goal) => { | 193 | Command::Add(name, kind, goal, auto) => { |
194 | if kind == "count" { | 194 | if kind == "count" { |
195 | self.add_habit(Box::new(Count::new(name, goal.unwrap_or(0)))); | 195 | self.add_habit(Box::new(Count::new( |
196 | name, | ||
197 | goal.unwrap_or(0), | ||
198 | auto.unwrap_or(false), | ||
199 | ))); | ||
196 | } else if kind == "bit" { | 200 | } else if kind == "bit" { |
197 | self.add_habit(Box::new(Bit::new(name))); | 201 | self.add_habit(Box::new(Bit::new(name, auto.unwrap_or(false)))); |
198 | } | 202 | } |
199 | } | 203 | } |
200 | Command::Delete(name) => { | 204 | Command::Delete(name) => { |
diff --git a/src/command.rs b/src/command.rs index afc00ba..c1a855e 100644 --- a/src/command.rs +++ b/src/command.rs | |||
@@ -27,7 +27,7 @@ fn call_on_app(s: &mut Cursive, input: &str) { | |||
27 | 27 | ||
28 | #[derive(PartialEq)] | 28 | #[derive(PartialEq)] |
29 | pub enum Command { | 29 | pub enum Command { |
30 | Add(String, String, Option<u32>), // habit name, habit type, optional goal | 30 | Add(String, String, Option<u32>, Option<bool>), // habit name, habit type, optional goal, auto tracked |
31 | MonthPrev, | 31 | MonthPrev, |
32 | MonthNext, | 32 | MonthNext, |
33 | Delete(String), | 33 | Delete(String), |
@@ -50,10 +50,12 @@ impl Command { | |||
50 | return Command::Blank; | 50 | return Command::Blank; |
51 | } | 51 | } |
52 | let goal = args.get(2).map(|g| g.parse::<u32>().ok()).flatten(); | 52 | let goal = args.get(2).map(|g| g.parse::<u32>().ok()).flatten(); |
53 | let auto = args.get(3).map(|g| g.parse::<bool>().ok()).flatten(); | ||
53 | return Command::Add( | 54 | return Command::Add( |
54 | args.get_mut(0).unwrap().to_string(), | 55 | args.get_mut(0).unwrap().to_string(), |
55 | args.get_mut(1).unwrap().to_string(), | 56 | args.get_mut(1).unwrap().to_string(), |
56 | goal, | 57 | goal, |
58 | auto, | ||
57 | ); | 59 | ); |
58 | } | 60 | } |
59 | "delete" | "d" => { | 61 | "delete" | "d" => { |
diff --git a/src/habit/bit.rs b/src/habit/bit.rs index 292b96a..3386182 100644 --- a/src/habit/bit.rs +++ b/src/habit/bit.rs | |||
@@ -3,6 +3,7 @@ use std::collections::HashMap; | |||
3 | use chrono::NaiveDate; | 3 | use chrono::NaiveDate; |
4 | use serde::{Deserialize, Serialize}; | 4 | use serde::{Deserialize, Serialize}; |
5 | 5 | ||
6 | use crate::habit::prelude::default_auto; | ||
6 | use crate::habit::traits::Habit; | 7 | use crate::habit::traits::Habit; |
7 | use crate::habit::{TrackEvent, ViewMode}; | 8 | use crate::habit::{TrackEvent, ViewMode}; |
8 | use crate::CONFIGURATION; | 9 | use crate::CONFIGURATION; |
@@ -37,6 +38,9 @@ pub struct Bit { | |||
37 | stats: HashMap<NaiveDate, CustomBool>, | 38 | stats: HashMap<NaiveDate, CustomBool>, |
38 | goal: CustomBool, | 39 | goal: CustomBool, |
39 | 40 | ||
41 | #[serde(default = "default_auto")] | ||
42 | auto: bool, | ||
43 | |||
40 | #[serde(skip)] | 44 | #[serde(skip)] |
41 | view_month_offset: u32, | 45 | view_month_offset: u32, |
42 | 46 | ||
@@ -45,11 +49,12 @@ pub struct Bit { | |||
45 | } | 49 | } |
46 | 50 | ||
47 | impl Bit { | 51 | impl Bit { |
48 | pub fn new(name: impl AsRef<str>) -> Self { | 52 | pub fn new(name: impl AsRef<str>, auto: bool) -> Self { |
49 | return Bit { | 53 | return Bit { |
50 | name: name.as_ref().to_owned(), | 54 | name: name.as_ref().to_owned(), |
51 | stats: HashMap::new(), | 55 | stats: HashMap::new(), |
52 | goal: CustomBool(true), | 56 | goal: CustomBool(true), |
57 | auto, | ||
53 | view_month_offset: 0, | 58 | view_month_offset: 0, |
54 | view_mode: ViewMode::Day, | 59 | view_mode: ViewMode::Day, |
55 | }; | 60 | }; |
@@ -114,4 +119,7 @@ impl Habit for Bit { | |||
114 | fn view_mode(&self) -> ViewMode { | 119 | fn view_mode(&self) -> ViewMode { |
115 | self.view_mode | 120 | self.view_mode |
116 | } | 121 | } |
122 | fn is_auto(&self) -> bool { | ||
123 | self.auto | ||
124 | } | ||
117 | } | 125 | } |
diff --git a/src/habit/count.rs b/src/habit/count.rs index a0e0aee..1bdf920 100644 --- a/src/habit/count.rs +++ b/src/habit/count.rs | |||
@@ -3,6 +3,7 @@ use std::collections::HashMap; | |||
3 | use chrono::NaiveDate; | 3 | use chrono::NaiveDate; |
4 | use serde::{Deserialize, Serialize}; | 4 | use serde::{Deserialize, Serialize}; |
5 | 5 | ||
6 | use crate::habit::prelude::default_auto; | ||
6 | use crate::habit::traits::Habit; | 7 | use crate::habit::traits::Habit; |
7 | use crate::habit::{TrackEvent, ViewMode}; | 8 | use crate::habit::{TrackEvent, ViewMode}; |
8 | 9 | ||
@@ -12,6 +13,9 @@ pub struct Count { | |||
12 | stats: HashMap<NaiveDate, u32>, | 13 | stats: HashMap<NaiveDate, u32>, |
13 | goal: u32, | 14 | goal: u32, |
14 | 15 | ||
16 | #[serde(default = "default_auto")] | ||
17 | auto: bool, | ||
18 | |||
15 | #[serde(skip)] | 19 | #[serde(skip)] |
16 | view_month_offset: u32, | 20 | view_month_offset: u32, |
17 | 21 | ||
@@ -20,11 +24,12 @@ pub struct Count { | |||
20 | } | 24 | } |
21 | 25 | ||
22 | impl Count { | 26 | impl Count { |
23 | pub fn new(name: impl AsRef<str>, goal: u32) -> Self { | 27 | pub fn new(name: impl AsRef<str>, goal: u32, auto: bool) -> Self { |
24 | return Count { | 28 | return Count { |
25 | name: name.as_ref().to_owned(), | 29 | name: name.as_ref().to_owned(), |
26 | stats: HashMap::new(), | 30 | stats: HashMap::new(), |
27 | goal, | 31 | goal, |
32 | auto, | ||
28 | view_month_offset: 0, | 33 | view_month_offset: 0, |
29 | view_mode: ViewMode::Day, | 34 | view_mode: ViewMode::Day, |
30 | }; | 35 | }; |
@@ -99,4 +104,7 @@ impl Habit for Count { | |||
99 | fn view_mode(&self) -> ViewMode { | 104 | fn view_mode(&self) -> ViewMode { |
100 | self.view_mode | 105 | self.view_mode |
101 | } | 106 | } |
107 | fn is_auto(&self) -> bool { | ||
108 | self.auto | ||
109 | } | ||
102 | } | 110 | } |
diff --git a/src/habit/prelude.rs b/src/habit/prelude.rs index 9196f00..b8b2bb2 100644 --- a/src/habit/prelude.rs +++ b/src/habit/prelude.rs | |||
@@ -18,3 +18,7 @@ impl std::default::Default for ViewMode { | |||
18 | ViewMode::Day | 18 | ViewMode::Day |
19 | } | 19 | } |
20 | } | 20 | } |
21 | |||
22 | pub fn default_auto() -> bool { | ||
23 | false | ||
24 | } | ||
diff --git a/src/habit/traits.rs b/src/habit/traits.rs index e28e55d..5092bc5 100644 --- a/src/habit/traits.rs +++ b/src/habit/traits.rs | |||
@@ -26,6 +26,8 @@ pub trait Habit { | |||
26 | 26 | ||
27 | fn set_view_mode(&mut self, mode: ViewMode); | 27 | fn set_view_mode(&mut self, mode: ViewMode); |
28 | fn view_mode(&self) -> ViewMode; | 28 | fn view_mode(&self) -> ViewMode; |
29 | |||
30 | fn is_auto(&self) -> bool; | ||
29 | } | 31 | } |
30 | 32 | ||
31 | #[typetag::serde(tag = "type")] | 33 | #[typetag::serde(tag = "type")] |
@@ -44,21 +46,15 @@ pub trait HabitWrapper: erased_serde::Serialize { | |||
44 | 46 | ||
45 | fn set_view_mode(&mut self, mode: ViewMode); | 47 | fn set_view_mode(&mut self, mode: ViewMode); |
46 | fn view_mode(&self) -> ViewMode; | 48 | fn view_mode(&self) -> ViewMode; |
49 | |||
50 | fn is_auto(&self) -> bool; | ||
47 | } | 51 | } |
48 | 52 | ||
49 | macro_rules! auto_habit_impl { | 53 | macro_rules! auto_habit_impl { |
50 | ($struct_name:ident) => { | 54 | ($struct_name:ident) => { |
51 | #[typetag::serde] | 55 | #[typetag::serde] |
52 | impl HabitWrapper for $struct_name { | 56 | impl HabitWrapper for $struct_name { |
53 | fn remaining(&self, date: NaiveDate) -> u32 { | 57 | // ShadowView |
54 | Habit::remaining(self, date) | ||
55 | } | ||
56 | fn goal(&self) -> u32 { | ||
57 | Habit::goal(self) | ||
58 | } | ||
59 | fn modify(&mut self, date: NaiveDate, event: TrackEvent) { | ||
60 | Habit::modify(self, date, event); | ||
61 | } | ||
62 | fn draw(&self, printer: &Printer) { | 58 | fn draw(&self, printer: &Printer) { |
63 | ShadowView::draw(self, printer) | 59 | ShadowView::draw(self, printer) |
64 | } | 60 | } |
@@ -71,6 +67,17 @@ macro_rules! auto_habit_impl { | |||
71 | fn take_focus(&mut self, d: Direction) -> bool { | 67 | fn take_focus(&mut self, d: Direction) -> bool { |
72 | ShadowView::take_focus(self, d) | 68 | ShadowView::take_focus(self, d) |
73 | } | 69 | } |
70 | |||
71 | // Habit | ||
72 | fn remaining(&self, date: NaiveDate) -> u32 { | ||
73 | Habit::remaining(self, date) | ||
74 | } | ||
75 | fn goal(&self) -> u32 { | ||
76 | Habit::goal(self) | ||
77 | } | ||
78 | fn modify(&mut self, date: NaiveDate, event: TrackEvent) { | ||
79 | Habit::modify(self, date, event); | ||
80 | } | ||
74 | fn get_name(&self) -> String { | 81 | fn get_name(&self) -> String { |
75 | Habit::name(self) | 82 | Habit::name(self) |
76 | } | 83 | } |
@@ -86,6 +93,9 @@ macro_rules! auto_habit_impl { | |||
86 | fn view_mode(&self) -> ViewMode { | 93 | fn view_mode(&self) -> ViewMode { |
87 | Habit::view_mode(self) | 94 | Habit::view_mode(self) |
88 | } | 95 | } |
96 | fn is_auto(&self) -> bool { | ||
97 | Habit::is_auto(self) | ||
98 | } | ||
89 | } | 99 | } |
90 | }; | 100 | }; |
91 | } | 101 | } |
diff --git a/src/views.rs b/src/views.rs index 9e4a844..54d5431 100644 --- a/src/views.rs +++ b/src/views.rs | |||
@@ -63,7 +63,7 @@ where | |||
63 | }, | 63 | }, |
64 | ); | 64 | ); |
65 | 65 | ||
66 | let draw_month = |printer: &Printer| { | 66 | let draw_week = |printer: &Printer| { |
67 | let days = (1..31) | 67 | let days = (1..31) |
68 | .map(|i| NaiveDate::from_ymd_opt(year, month, i)) | 68 | .map(|i| NaiveDate::from_ymd_opt(year, month, i)) |
69 | .flatten() // dates 28-31 may not exist, ignore them if they don't | 69 | .flatten() // dates 28-31 may not exist, ignore them if they don't |
@@ -77,10 +77,10 @@ where | |||
77 | let bars_to_fill = (completions * full as u32) / weekly_goal; | 77 | let bars_to_fill = (completions * full as u32) / weekly_goal; |
78 | let percentage = (completions as f64 * 100.) / weekly_goal as f64; | 78 | let percentage = (completions as f64 * 100.) / weekly_goal as f64; |
79 | printer.with_style(future_style, |p| { | 79 | printer.with_style(future_style, |p| { |
80 | p.print((4, line_nr), &"��".repeat(full)); | 80 | p.print((4, line_nr), &"���".repeat(full)); |
81 | }); | 81 | }); |
82 | printer.with_style(goal_reached_style, |p| { | 82 | printer.with_style(goal_reached_style, |p| { |
83 | p.print((4, line_nr), &"��".repeat(bars_to_fill as usize)); | 83 | p.print((4, line_nr), &"���".repeat(bars_to_fill as usize)); |
84 | }); | 84 | }); |
85 | printer.with_style( | 85 | printer.with_style( |
86 | if is_this_week { | 86 | if is_this_week { |
@@ -120,7 +120,7 @@ where | |||
120 | 120 | ||
121 | match self.view_mode() { | 121 | match self.view_mode() { |
122 | ViewMode::Day => draw_day(printer), | 122 | ViewMode::Day => draw_day(printer), |
123 | ViewMode::Week => draw_month(printer), | 123 | ViewMode::Week => draw_week(printer), |
124 | _ => draw_day(printer), | 124 | _ => draw_day(printer), |
125 | }; | 125 | }; |
126 | } | 126 | } |