diff options
-rw-r--r-- | src/app/impl_self.rs | 4 | ||||
-rw-r--r-- | src/app/impl_view.rs | 8 | ||||
-rw-r--r-- | src/command.rs | 72 |
3 files changed, 67 insertions, 17 deletions
diff --git a/src/app/impl_self.rs b/src/app/impl_self.rs index 95f1871..7eae853 100644 --- a/src/app/impl_self.rs +++ b/src/app/impl_self.rs | |||
@@ -37,6 +37,10 @@ impl App { | |||
37 | self.habits.push(h); | 37 | self.habits.push(h); |
38 | } | 38 | } |
39 | 39 | ||
40 | pub fn list_habits(&self) -> Vec<String> { | ||
41 | self.habits.iter().map(|x| x.name()).collect::<Vec<_>>() | ||
42 | } | ||
43 | |||
40 | pub fn delete_by_name(&mut self, name: &str) { | 44 | pub fn delete_by_name(&mut self, name: &str) { |
41 | let old_len = self.habits.len(); | 45 | let old_len = self.habits.len(); |
42 | self.habits.retain(|h| h.name() != name); | 46 | self.habits.retain(|h| h.name() != name); |
diff --git a/src/app/impl_view.rs b/src/app/impl_view.rs index 892b00c..b8c4589 100644 --- a/src/app/impl_view.rs +++ b/src/app/impl_view.rs | |||
@@ -102,14 +102,6 @@ impl View for App { | |||
102 | self.set_focus(Absolute::Down); | 102 | self.set_focus(Absolute::Down); |
103 | return EventResult::Consumed(None); | 103 | return EventResult::Consumed(None); |
104 | } | 104 | } |
105 | Event::Char('d') => { | ||
106 | if self.habits.is_empty() { | ||
107 | return EventResult::Consumed(None); | ||
108 | } | ||
109 | self.habits.remove(self.focus); | ||
110 | self.focus = self.focus.checked_sub(1).unwrap_or(0); | ||
111 | return EventResult::Consumed(None); | ||
112 | } | ||
113 | Event::Char('w') => { | 105 | Event::Char('w') => { |
114 | // helper bind to test write to file | 106 | // helper bind to test write to file |
115 | let j = serde_json::to_string_pretty(&self.habits).unwrap(); | 107 | let j = serde_json::to_string_pretty(&self.habits).unwrap(); |
diff --git a/src/command.rs b/src/command.rs index 29908f4..2f6b48a 100644 --- a/src/command.rs +++ b/src/command.rs | |||
@@ -1,21 +1,75 @@ | |||
1 | use std::fmt; | 1 | use std::fmt; |
2 | use std::rc::Rc; | ||
2 | 3 | ||
4 | use cursive::event::{Event, EventResult, Key}; | ||
3 | use cursive::theme::{BaseColor, Color, ColorStyle}; | 5 | use cursive::theme::{BaseColor, Color, ColorStyle}; |
4 | use cursive::view::Resizable; | 6 | use cursive::view::Resizable; |
5 | use cursive::views::{EditView, LinearLayout, TextView}; | 7 | use cursive::views::{EditView, LinearLayout, OnEventView, TextView}; |
6 | use cursive::Cursive; | 8 | use cursive::Cursive; |
7 | 9 | ||
8 | use crate::{app::App, CONFIGURATION}; | 10 | use crate::{app::App, CONFIGURATION}; |
9 | 11 | ||
12 | static COMMANDS: &'static [&'static str] = &[ | ||
13 | "add", | ||
14 | "add-auto", | ||
15 | "delete", | ||
16 | "track-up", | ||
17 | "track-down", | ||
18 | "month-prev", | ||
19 | "month-next", | ||
20 | "quit", | ||
21 | "help", | ||
22 | ]; | ||
23 | |||
24 | fn get_command_completion(prefix: &str) -> Option<String> { | ||
25 | let first_match = COMMANDS.iter().filter(|&x| x.starts_with(prefix)).next(); | ||
26 | return first_match.map(|&x| x.into()); | ||
27 | } | ||
28 | |||
29 | fn get_habit_completion(prefix: &str, habit_names: &[String]) -> Option<String> { | ||
30 | let first_match = habit_names.iter().filter(|&x| x.starts_with(prefix)).next(); | ||
31 | eprintln!("{:?}| {:?}", prefix, first_match); | ||
32 | return first_match.map(|x| x.into()); | ||
33 | } | ||
34 | |||
10 | pub fn open_command_window(s: &mut Cursive) { | 35 | pub fn open_command_window(s: &mut Cursive) { |
11 | let command_window = EditView::new() | 36 | let habit_list: Vec<String> = s |
12 | .filler(" ") | 37 | .call_on_name("Main", |view: &mut App| { |
13 | .on_submit(call_on_app) | 38 | return view.list_habits(); |
14 | .style(ColorStyle::new( | 39 | }) |
15 | Color::Dark(BaseColor::Black), | 40 | .unwrap(); |
16 | Color::Dark(BaseColor::White), | 41 | let style = ColorStyle::new(Color::Dark(BaseColor::Black), Color::Dark(BaseColor::White)); |
17 | )) | 42 | let command_window = OnEventView::new( |
18 | .fixed_width(CONFIGURATION.view_width * CONFIGURATION.grid_width); | 43 | EditView::new() |
44 | .filler(" ") | ||
45 | .on_submit(call_on_app) | ||
46 | .style(style), | ||
47 | ) | ||
48 | .on_event_inner( | ||
49 | Event::Key(Key::Tab), | ||
50 | move |view: &mut EditView, _: &Event| { | ||
51 | let contents = view.get_content(); | ||
52 | if !contents.contains(" ") { | ||
53 | let completion = get_command_completion(&*contents); | ||
54 | if let Some(c) = completion { | ||
55 | let cb = view.set_content(c); | ||
56 | return Some(EventResult::Consumed(Some(cb))); | ||
57 | }; | ||
58 | return None; | ||
59 | } else { | ||
60 | let word = contents.split(' ').last().unwrap(); | ||
61 | let completion = get_habit_completion(word, &habit_list); | ||
62 | eprintln!("{:?} | {:?}", completion, contents); | ||
63 | if let Some(c) = completion { | ||
64 | let cb = | ||
65 | view.set_content(format!("{}", contents) + c.strip_prefix(word).unwrap()); | ||
66 | return Some(EventResult::Consumed(Some(cb))); | ||
67 | }; | ||
68 | return None; | ||
69 | } | ||
70 | }, | ||
71 | ) | ||
72 | .fixed_width(CONFIGURATION.view_width * CONFIGURATION.grid_width); | ||
19 | s.call_on_name("Frame", |view: &mut LinearLayout| { | 73 | s.call_on_name("Frame", |view: &mut LinearLayout| { |
20 | let mut commandline = LinearLayout::horizontal() | 74 | let mut commandline = LinearLayout::horizontal() |
21 | .child(TextView::new(":")) | 75 | .child(TextView::new(":")) |