1use std::io::{self, stdin, stdout, Write};
2use termion::input::TermRead;
3use termion::raw::IntoRawMode;
4
5use super::*;
6use crate::editor::Prompt;
7
8pub type ColorClosure = Box<dyn Fn(&str) -> String>;
9
10pub fn get_buffer_words(buf: &Buffer) -> Vec<(usize, usize)> {
12 let mut res = Vec::new();
13
14 let mut word_start = None;
15 let mut just_had_backslash = false;
16
17 for (i, &c) in buf.chars().enumerate() {
18 if c == '\\' {
19 just_had_backslash = true;
20 continue;
21 }
22
23 if let Some(start) = word_start {
24 if c == ' ' && !just_had_backslash {
25 res.push((start, i));
26 word_start = None;
27 }
28 } else if c != ' ' {
29 word_start = Some(i);
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 word_divider_fn: Box<dyn Fn(&Buffer) -> Vec<(usize, usize)>>,
52 pub key_bindings: KeyBindings,
53 pub buf: String,
54}
55
56impl Default for Context {
57 fn default() -> Self {
58 Self::new()
59 }
60}
61
62impl Context {
63 pub fn new() -> Self {
64 Context {
65 history: History::new(),
66 word_divider_fn: Box::new(get_buffer_words),
67 key_bindings: KeyBindings::Emacs,
68 buf: String::with_capacity(512),
69 }
70 }
71
72 pub fn read_line<C: Completer>(
77 &mut self,
78 prompt: Prompt,
79 f: Option<ColorClosure>,
80 handler: &mut C,
81 ) -> io::Result<String> {
82 self.read_line_with_init_buffer(prompt, handler, f, Buffer::new())
83 }
84
85 pub fn read_line_with_init_buffer<B: Into<Buffer>, C: Completer>(
106 &mut self,
107 prompt: Prompt,
108 handler: &mut C,
109 f: Option<ColorClosure>,
110 buffer: B,
111 ) -> io::Result<String> {
112 let stdout = stdout().into_raw_mode()?;
113 let keybindings = self.key_bindings;
114 let ed = Editor::new_with_init_buffer(stdout, prompt, f, self, buffer)?;
115 match keybindings {
116 KeyBindings::Emacs => Self::handle_keys(keymap::Emacs::new(), ed, handler),
117 KeyBindings::Vi => Self::handle_keys(keymap::Vi::new(), ed, handler),
118 }
119
120 }
122
123 fn handle_keys<W: Write, M: KeyMap, C: Completer>(
124 mut keymap: M,
125 mut ed: Editor<'_, W>,
126 handler: &mut C,
127 ) -> io::Result<String> {
128 keymap.init(&mut ed);
129 for c in stdin().keys() {
130 if keymap.handle_key(c?, &mut ed, handler)? {
131 break;
132 }
133 }
134
135 Ok(ed.into())
136 }
137
138 pub fn revert_all_history(&mut self) {
139 for buf in &mut self.history.buffers {
140 buf.revert();
141 }
142 }
143}