1use std::io;
2use console::Key::*;
3use console::Term;
4
5pub struct InputHandler {
6 pub line: String,
7 cursor_position: usize,
8 term: Term,
9}
10
11impl InputHandler {
12 pub fn new(input: &str) -> Self {
13 InputHandler {
14 line: input.to_owned(),
15 cursor_position: input.len(),
16 term: Term::stdout(),
17 }
18 }
19
20 pub fn read_key(&mut self) -> io::Result<console::Key> {
21 self.term.write_line(&format!("Search >{}", self.line))?;
22 self.term.move_cursor_up(1)?;
23 self.term.move_cursor_right(self.cursor_position+8)?;
24 match self.term.read_key() {
25 Ok(key) => {
26 match key {
27 Char(c) => self.add_char(c),
28 Backspace => self.backspace_char(),
29 Del => self.del_char(),
30 ArrowLeft => self.move_left(),
31 ArrowRight => self.move_right(),
32 Home => self.move_home(),
33 End => self.move_end(),
34 _ => {}
35 };
36 Ok(key)
37 }
38 Err(_) => Ok(Escape),
39 }
40 }
41
42 fn add_char(&mut self, c: char) {
43 if self.cursor_position == self.line.len() {
44 self.line.push(c);
45 self.cursor_position = self.line.len();
46 } else {
47 self.line.insert(self.cursor_position, c);
48 self.cursor_position +=1;
49 }
50 }
51
52 fn backspace_char(&mut self) {
53 if self.cursor_position == self.line.len() {
54 self.line.pop();
55 self.cursor_position = self.line.len();
56 } else {
57 self.line.remove(self.cursor_position - 1);
58 self.cursor_position -=1;
59 }
60 }
61
62 fn del_char(&mut self) {
63 if self.cursor_position == self.line.len() {
64 self.line.pop();
65 self.cursor_position = self.line.len();
66 } else {
67 self.line.remove(self.cursor_position);
68 }
69 }
70
71 fn move_left(&mut self) {
72 if self.cursor_position == 0 {
73 self.cursor_position = 0;
74 } else {
75 self.cursor_position -= 1;
76 }
77 }
78 fn move_right(&mut self) {
79 if self.cursor_position < self.line.len() {
80 self.cursor_position += 1;
81 }
82 }
83
84 fn move_home(&mut self) {
85 self.cursor_position = 0;
86 }
87
88 fn move_end(&mut self) {
89 self.cursor_position = self.line.len();
90 }
91
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97 #[test]
98 fn test_input() {
99 let mut ih = InputHandler::new("");
100
101 ih.add_char('a');
102 assert_eq!("a", ih.line);
103
104 ih.move_home();
105 ih.add_char('b');
106 assert_eq!("ba", ih.line);
107
108 ih.move_end();
109 ih.add_char('c');
110 assert_eq!("bac", ih.line);
111
112 ih.move_left();
113 ih.backspace_char();
114 assert_eq!("bc", ih.line);
115
116 ih.move_left();
117 ih.add_char('a');
118 assert_eq!("abc", ih.line);
119
120 ih.move_left();
121 ih.move_left();
122 ih.add_char('d');
123 assert_eq!("dabc", ih.line);
124
125 ih.move_right();
126 ih.del_char();
127 assert_eq!("dac", ih.line);
128
129 ih.move_end();
130 ih.del_char();
131 assert_eq!("da", ih.line);
132
133 ih.move_end();
134 ih.backspace_char();
135 assert_eq!("d", ih.line);
136
137 ih.move_home();
138 ih.add_char('b');
139 assert_eq!("bd", ih.line);
140 ih.add_char('c');
141 assert_eq!("bcd", ih.line);
142 ih.move_end();
143 ih.move_left();
144 ih.add_char('x');
145 ih.add_char('y');
146 ih.add_char('z');
147 assert_eq!("bcxyzd", ih.line);
148
149 }
150}