diff options
Diffstat (limited to 'src/app')
-rw-r--r-- | src/app/cursor.rs | 51 | ||||
-rw-r--r-- | src/app/impl_self.rs | 14 | ||||
-rw-r--r-- | src/app/impl_view.rs | 18 | ||||
-rw-r--r-- | src/app/message.rs | 3 | ||||
-rw-r--r-- | src/app/mod.rs | 3 |
5 files changed, 86 insertions, 3 deletions
diff --git a/src/app/cursor.rs b/src/app/cursor.rs new file mode 100644 index 0000000..ed6bd65 --- /dev/null +++ b/src/app/cursor.rs | |||
@@ -0,0 +1,51 @@ | |||
1 | use chrono::{Duration, Local, NaiveDate}; | ||
2 | use cursive::direction::Absolute; | ||
3 | |||
4 | #[derive(Debug, Copy, Clone)] | ||
5 | pub struct Cursor(pub NaiveDate); | ||
6 | |||
7 | impl std::default::Default for Cursor { | ||
8 | fn default() -> Self { | ||
9 | Cursor::new() | ||
10 | } | ||
11 | } | ||
12 | |||
13 | impl Cursor { | ||
14 | pub fn new() -> Self { | ||
15 | Cursor { | ||
16 | 0: Local::now().naive_local().date(), | ||
17 | } | ||
18 | } | ||
19 | pub fn do_move(&mut self, d: Absolute) { | ||
20 | let today = Local::now().naive_local().date(); | ||
21 | let cursor = self.0; | ||
22 | match d { | ||
23 | Absolute::Right => { | ||
24 | // forward by 1 day | ||
25 | let next = cursor.succ_opt().unwrap_or(cursor); | ||
26 | if next <= today { | ||
27 | self.0 = next; | ||
28 | } | ||
29 | } | ||
30 | Absolute::Left => { | ||
31 | // backward by 1 day | ||
32 | // assumes an infinite past | ||
33 | self.0 = cursor.pred_opt().unwrap_or(cursor); | ||
34 | } | ||
35 | Absolute::Down => { | ||
36 | // forward by 1 week | ||
37 | let next = cursor.checked_add_signed(Duration::weeks(1)).unwrap(); | ||
38 | if next <= today { | ||
39 | self.0 = next; | ||
40 | } | ||
41 | } | ||
42 | Absolute::Up => { | ||
43 | // backward by 1 week | ||
44 | // assumes an infinite past | ||
45 | let next = cursor.checked_sub_signed(Duration::weeks(1)).unwrap(); | ||
46 | self.0 = next; | ||
47 | } | ||
48 | Absolute::None => {} | ||
49 | } | ||
50 | } | ||
51 | } | ||
diff --git a/src/app/impl_self.rs b/src/app/impl_self.rs index 1114d50..abf5209 100644 --- a/src/app/impl_self.rs +++ b/src/app/impl_self.rs | |||
@@ -15,7 +15,7 @@ use crate::command::{Command, CommandLineError}; | |||
15 | use crate::habit::{Bit, Count, HabitWrapper, TrackEvent, ViewMode}; | 15 | use crate::habit::{Bit, Count, HabitWrapper, TrackEvent, ViewMode}; |
16 | use crate::utils::{self, GRID_WIDTH, VIEW_HEIGHT, VIEW_WIDTH}; | 16 | use crate::utils::{self, GRID_WIDTH, VIEW_HEIGHT, VIEW_WIDTH}; |
17 | 17 | ||
18 | use crate::app::{App, MessageKind, StatusLine}; | 18 | use crate::app::{App, Cursor, Message, MessageKind, StatusLine}; |
19 | 19 | ||
20 | impl App { | 20 | impl App { |
21 | pub fn new() -> Self { | 21 | pub fn new() -> Self { |
@@ -28,7 +28,8 @@ impl App { | |||
28 | _file_watcher: watcher, | 28 | _file_watcher: watcher, |
29 | file_event_recv: rx, | 29 | file_event_recv: rx, |
30 | view_month_offset: 0, | 30 | view_month_offset: 0, |
31 | message: "Type :add <habit-name> <goal> to get started, Ctrl-L to dismiss".into(), | 31 | cursor: Cursor::new(), |
32 | message: Message::startup(), | ||
32 | }; | 33 | }; |
33 | } | 34 | } |
34 | 35 | ||
@@ -85,6 +86,13 @@ impl App { | |||
85 | } | 86 | } |
86 | } | 87 | } |
87 | 88 | ||
89 | pub fn move_cursor(&mut self, d: Absolute) { | ||
90 | self.cursor.do_move(d); | ||
91 | for v in self.habits.iter_mut() { | ||
92 | v.move_cursor(d); | ||
93 | } | ||
94 | } | ||
95 | |||
88 | pub fn set_focus(&mut self, d: Absolute) { | 96 | pub fn set_focus(&mut self, d: Absolute) { |
89 | match d { | 97 | match d { |
90 | Absolute::Right => { | 98 | Absolute::Right => { |
@@ -129,7 +137,7 @@ impl App { | |||
129 | format!("{}", Local::now().naive_local().date().format("%d/%b/%y"),) | 137 | format!("{}", Local::now().naive_local().date().format("%d/%b/%y"),) |
130 | } else { | 138 | } else { |
131 | let months = self.view_month_offset; | 139 | let months = self.view_month_offset; |
132 | format!("{}", format!("{} months ago", months),) | 140 | format!("{}", format!("{} month(s) ago", months),) |
133 | }; | 141 | }; |
134 | 142 | ||
135 | StatusLine { | 143 | StatusLine { |
diff --git a/src/app/impl_view.rs b/src/app/impl_view.rs index 395cac4..0ec47f1 100644 --- a/src/app/impl_view.rs +++ b/src/app/impl_view.rs | |||
@@ -95,6 +95,24 @@ impl View for App { | |||
95 | self.set_focus(Absolute::Down); | 95 | self.set_focus(Absolute::Down); |
96 | return EventResult::Consumed(None); | 96 | return EventResult::Consumed(None); |
97 | } | 97 | } |
98 | |||
99 | Event::Char('w') => { | ||
100 | self.move_cursor(Absolute::Up); | ||
101 | return EventResult::Consumed(None); | ||
102 | } | ||
103 | Event::Char('a') => { | ||
104 | self.move_cursor(Absolute::Left); | ||
105 | return EventResult::Consumed(None); | ||
106 | } | ||
107 | Event::Char('s') => { | ||
108 | self.move_cursor(Absolute::Down); | ||
109 | return EventResult::Consumed(None); | ||
110 | } | ||
111 | Event::Char('d') => { | ||
112 | self.move_cursor(Absolute::Right); | ||
113 | return EventResult::Consumed(None); | ||
114 | } | ||
115 | |||
98 | Event::Char('v') => { | 116 | Event::Char('v') => { |
99 | if self.habits.is_empty() { | 117 | if self.habits.is_empty() { |
100 | return EventResult::Consumed(None); | 118 | return EventResult::Consumed(None); |
diff --git a/src/app/message.rs b/src/app/message.rs index 65f0a5c..a1d3d57 100644 --- a/src/app/message.rs +++ b/src/app/message.rs | |||
@@ -35,6 +35,9 @@ pub struct Message { | |||
35 | } | 35 | } |
36 | 36 | ||
37 | impl Message { | 37 | impl Message { |
38 | pub fn startup() -> Self { | ||
39 | "Type :add <habit-name> <goal> to get started, Ctrl-L to dismiss".into() | ||
40 | } | ||
38 | pub fn contents(&self) -> &str { | 41 | pub fn contents(&self) -> &str { |
39 | &self.msg | 42 | &self.msg |
40 | } | 43 | } |
diff --git a/src/app/mod.rs b/src/app/mod.rs index 2aecb33..9432f0d 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs | |||
@@ -5,11 +5,13 @@ use notify::{DebouncedEvent, RecommendedWatcher}; | |||
5 | 5 | ||
6 | use crate::habit::HabitWrapper; | 6 | use crate::habit::HabitWrapper; |
7 | 7 | ||
8 | mod cursor; | ||
8 | mod impl_self; | 9 | mod impl_self; |
9 | mod impl_view; | 10 | mod impl_view; |
10 | mod message; | 11 | mod message; |
11 | 12 | ||
12 | pub struct StatusLine(String, String); | 13 | pub struct StatusLine(String, String); |
14 | pub use cursor::Cursor; | ||
13 | pub use message::{Message, MessageKind}; | 15 | pub use message::{Message, MessageKind}; |
14 | 16 | ||
15 | pub struct App { | 17 | pub struct App { |
@@ -20,6 +22,7 @@ pub struct App { | |||
20 | file_event_recv: Receiver<DebouncedEvent>, | 22 | file_event_recv: Receiver<DebouncedEvent>, |
21 | focus: usize, | 23 | focus: usize, |
22 | view_month_offset: u32, | 24 | view_month_offset: u32, |
25 | cursor: Cursor, | ||
23 | message: Message, | 26 | message: Message, |
24 | } | 27 | } |
25 | 28 | ||