1use std::io::{self, stdin, stdout, Stdout, Write};
2use termion::input::TermRead;
3use termion::raw::{IntoRawMode, RawTerminal};
4
5use super::*;
6use keymap;
7
8pub fn get_buffer_words(buf: &Buffer) -> Vec<(usize, usize)> {
10 let mut res = Vec::new();
11
12 let mut word_start = None;
13 let mut just_had_backslash = false;
14
15 for (i, &c) in buf.chars().enumerate() {
16 if c == '\\' {
17 just_had_backslash = true;
18 continue;
19 }
20
21 if let Some(start) = word_start {
22 if c == ' ' && !just_had_backslash {
23 res.push((start, i));
24 word_start = None;
25 }
26 } else {
27 if c != ' ' {
28 word_start = Some(i);
29 }
30 }
31
32 just_had_backslash = false;
33 }
34
35 if let Some(start) = word_start {
36 res.push((start, buf.num_chars()));
37 }
38
39 res
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub enum KeyBindings {
45 Vi,
46 Emacs,
47}
48
49pub struct Context {
50 pub history: History,
51 pub completer: Option<Box<Completer>>,
52 pub word_divider_fn: Box<Fn(&Buffer) -> Vec<(usize, usize)>>,
53 pub key_bindings: KeyBindings,
54}
55
56impl Context {
57 pub fn new() -> Self {
58 Context {
59 history: History::new(),
60 completer: None,
61 word_divider_fn: Box::new(get_buffer_words),
62 key_bindings: KeyBindings::Emacs,
63 }
64 }
65
66 pub fn read_line<P: Into<String>>(
71 &mut self,
72 prompt: P,
73 mut handler: &mut EventHandler<RawTerminal<Stdout>>,
74 ) -> io::Result<String> {
75 self.read_line_with_init_buffer(prompt, handler, Buffer::new())
76 }
77
78 pub fn read_line_with_init_buffer<P: Into<String>, B: Into<Buffer>>(
89 &mut self,
90 prompt: P,
91 mut handler: &mut EventHandler<RawTerminal<Stdout>>,
92 buffer: B,
93 ) -> io::Result<String> {
94 let res = {
95 let stdout = stdout().into_raw_mode().unwrap();
96 let ed = try!(Editor::new_with_init_buffer(stdout, prompt, self, buffer));
97 match self.key_bindings {
98 KeyBindings::Emacs => Self::handle_keys(keymap::Emacs::new(ed), handler),
99 KeyBindings::Vi => Self::handle_keys(keymap::Vi::new(ed), handler),
100 }
101 };
102
103 self.revert_all_history();
104 res
105 }
106
107 fn handle_keys<'a, T, W: Write, M: KeyMap<'a, W, T>>(
108 mut keymap: M,
109 mut handler: &mut EventHandler<W>,
110 ) -> io::Result<String>
111 where
112 String: From<M>,
113 {
114 let stdin = stdin();
115 for c in stdin.keys() {
116 if try!(keymap.handle_key(c.unwrap(), handler)) {
117 break;
118 }
119 }
120
121 Ok(keymap.into())
122 }
123
124 pub fn revert_all_history(&mut self) {
125 for buf in &mut self.history.buffers {
126 buf.revert();
127 }
128 }
129}