diff options
Diffstat (limited to 'src/command.rs')
-rw-r--r-- | src/command.rs | 87 |
1 files changed, 74 insertions, 13 deletions
diff --git a/src/command.rs b/src/command.rs index f856b00..4f3e491 100644 --- a/src/command.rs +++ b/src/command.rs | |||
@@ -1,21 +1,73 @@ | |||
1 | use std::fmt; | 1 | use std::fmt; |
2 | 2 | ||
3 | use cursive::event::{Event, EventResult, Key}; | ||
3 | use cursive::theme::{BaseColor, Color, ColorStyle}; | 4 | use cursive::theme::{BaseColor, Color, ColorStyle}; |
4 | use cursive::view::Resizable; | 5 | use cursive::view::Resizable; |
5 | use cursive::views::{EditView, LinearLayout, TextView}; | 6 | use cursive::views::{EditView, LinearLayout, OnEventView, TextView}; |
6 | use cursive::Cursive; | 7 | use cursive::Cursive; |
7 | 8 | ||
8 | use crate::{app::App, CONFIGURATION}; | 9 | use crate::app::App; |
10 | use crate::utils::{GRID_WIDTH, VIEW_WIDTH}; | ||
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 | "write", | ||
22 | "help", | ||
23 | ]; | ||
24 | |||
25 | fn get_command_completion(prefix: &str) -> Option<String> { | ||
26 | let first_match = COMMANDS.iter().filter(|&x| x.starts_with(prefix)).next(); | ||
27 | return first_match.map(|&x| x.into()); | ||
28 | } | ||
29 | |||
30 | fn get_habit_completion(prefix: &str, habit_names: &[String]) -> Option<String> { | ||
31 | let first_match = habit_names.iter().filter(|&x| x.starts_with(prefix)).next(); | ||
32 | return first_match.map(|x| x.into()); | ||
33 | } | ||
9 | 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 | if let Some(c) = completion { | ||
63 | let cb = view.set_content(format!("{}", contents) + &c[word.len()..]); | ||
64 | return Some(EventResult::Consumed(Some(cb))); | ||
65 | }; | ||
66 | return None; | ||
67 | } | ||
68 | }, | ||
69 | ) | ||
70 | .fixed_width(VIEW_WIDTH * GRID_WIDTH); | ||
19 | s.call_on_name("Frame", |view: &mut LinearLayout| { | 71 | s.call_on_name("Frame", |view: &mut LinearLayout| { |
20 | let mut commandline = LinearLayout::horizontal() | 72 | let mut commandline = LinearLayout::horizontal() |
21 | .child(TextView::new(":")) | 73 | .child(TextView::new(":")) |
@@ -59,15 +111,17 @@ pub enum Command { | |||
59 | Delete(String), | 111 | Delete(String), |
60 | TrackUp(String), | 112 | TrackUp(String), |
61 | TrackDown(String), | 113 | TrackDown(String), |
114 | Help(Option<String>), | ||
115 | Write, | ||
62 | Quit, | 116 | Quit, |
63 | Blank, | 117 | Blank, |
64 | } | 118 | } |
65 | 119 | ||
66 | #[derive(Debug)] | 120 | #[derive(Debug)] |
67 | pub enum CommandLineError { | 121 | pub enum CommandLineError { |
68 | InvalidCommand(String), | 122 | InvalidCommand(String), // command name |
69 | InvalidArg(u32), // position | 123 | InvalidArg(u32), // position |
70 | NotEnoughArgs(String, u32), | 124 | NotEnoughArgs(String, u32), // command name, required no. of args |
71 | } | 125 | } |
72 | 126 | ||
73 | impl std::error::Error for CommandLineError {} | 127 | impl std::error::Error for CommandLineError {} |
@@ -134,9 +188,16 @@ impl Command { | |||
134 | } | 188 | } |
135 | return Ok(Command::TrackDown(args[0].to_string())); | 189 | return Ok(Command::TrackDown(args[0].to_string())); |
136 | } | 190 | } |
191 | "h" | "?" | "help" => { | ||
192 | if args.is_empty() { | ||
193 | return Ok(Command::Help(None)); | ||
194 | } | ||
195 | return Ok(Command::Help(Some(args[0].to_string()))); | ||
196 | } | ||
137 | "mprev" | "month-prev" => return Ok(Command::MonthPrev), | 197 | "mprev" | "month-prev" => return Ok(Command::MonthPrev), |
138 | "mnext" | "month-next" => return Ok(Command::MonthNext), | 198 | "mnext" | "month-next" => return Ok(Command::MonthNext), |
139 | "q" | "quit" => return Ok(Command::Quit), | 199 | "q" | "quit" => return Ok(Command::Quit), |
200 | "w" | "write" => return Ok(Command::Write), | ||
140 | "" => return Ok(Command::Blank), | 201 | "" => return Ok(Command::Blank), |
141 | s => return Err(CommandLineError::InvalidCommand(s.into())), | 202 | s => return Err(CommandLineError::InvalidCommand(s.into())), |
142 | } | 203 | } |