on master help sign in
Bugfix
bc2c652Blaž Hrastnik
helix-core/src/state.rs−1
@@ -10,7 +10,6 @@ pub enum Mode {
10 Normal,
10 Normal,
11 Insert,
11 Insert,
12 Goto,
12 Goto,
13− Command,
14}
13}
15
14
16/// A state represents the current editor state of a single buffer.
15/// A state represents the current editor state of a single buffer.
helix-term/src/application.rs+35−16
@@ -225,7 +225,6 @@ impl Renderer {
225 Mode::Insert => "INS",
225 Mode::Insert => "INS",
226 Mode::Normal => "NOR",
226 Mode::Normal => "NOR",
227 Mode::Goto => "GOTO",
227 Mode::Goto => "GOTO",
228− Mode::Command => "COM", // command?
229 };
228 };
230 // statusline
229 // statusline
231 self.surface.set_style(
230 self.surface.set_style(
@@ -237,13 +236,15 @@ impl Renderer {
237 }
236 }
238
237
239 pub fn render_prompt(&mut self, prompt: &Prompt) {
238 pub fn render_prompt(&mut self, prompt: &Prompt) {
240− use tui::backend::Backend;
241 // render buffer text
239 // render buffer text
242 self.surface
240 self.surface
243− .set_string(1, self.size.1 - 1, String::from(":"), self.text_color);
241+ .set_string(1, self.size.1 - 1, &prompt.prompt, self.text_color);
244 self.surface
242 self.surface
245− .set_string(2, self.size.1 - 1, &prompt.buffer, self.text_color);
243+ .set_string(2, self.size.1 - 1, &prompt.line, self.text_color);
244+ }
246
245
246+ pub fn draw(&mut self) {
247+ use tui::backend::Backend;
247 // TODO: theres probably a better place for this
248 // TODO: theres probably a better place for this
248 self.terminal
249 self.terminal
249 .backend_mut()
250 .backend_mut()
@@ -259,7 +260,7 @@ impl Renderer {
259 mode => write!(stdout, "\x1B[2 q"),
260 mode => write!(stdout, "\x1B[2 q"),
260 };
261 };
261 let pos = if let Some(prompt) = prompt {
262 let pos = if let Some(prompt) = prompt {
262− Position::new(self.size.0 as usize, 2 + prompt.cursor_loc)
263+ Position::new(self.size.0 as usize, 2 + prompt.cursor)
263 } else {
264 } else {
264 if let Some(path) = view.state.path() {
265 if let Some(path) = view.state.path() {
265 self.surface.set_string(
266 self.surface.set_string(
@@ -303,15 +304,6 @@ impl Application {
303 Ok(app)
304 Ok(app)
304 }
305 }
305
306
306− pub fn set_prompt(&mut self) {
307− let commands = |editor: &mut Editor, input: &str| match input {
308− "q" => editor.should_close = true,
309− _ => (),
310− };
311− let prompt = Prompt::new(|input| None, commands);
312− self.prompt = Some(prompt);
313− }
314−
315 fn render(&mut self) {
307 fn render(&mut self) {
316 let viewport = Rect::new(OFFSET, 0, self.terminal.size.0, self.terminal.size.1 - 2); // - 2 for statusline and prompt
308 let viewport = Rect::new(OFFSET, 0, self.terminal.size.0, self.terminal.size.1 - 2); // - 2 for statusline and prompt
317
309
@@ -323,6 +315,8 @@ impl Application {
323 self.terminal.render_prompt(prompt);
315 self.terminal.render_prompt(prompt);
324 }
316 }
325
317
318+ self.terminal.draw();
319+
326 // TODO: drop unwrap
320 // TODO: drop unwrap
327 self.terminal.render_cursor(
321 self.terminal.render_cursor(
328 self.editor.view.as_ref().unwrap(),
322 self.editor.view.as_ref().unwrap(),
@@ -335,7 +329,6 @@ impl Application {
335 let mut reader = EventStream::new();
329 let mut reader = EventStream::new();
336 let keymap = keymap::default();
330 let keymap = keymap::default();
337
331
338− self.set_prompt();
339 self.render();
332 self.render();
340
333
341 loop {
334 loop {
@@ -363,6 +356,8 @@ impl Application {
363 .as_mut()
356 .as_mut()
364 .unwrap()
357 .unwrap()
365 .handle_input(event, &mut self.editor);
358 .handle_input(event, &mut self.editor);
359+
360+ self.render();
366 } else if let Some(view) = &mut self.editor.view {
361 } else if let Some(view) = &mut self.editor.view {
367 let keys = vec![event];
362 let keys = vec![event];
368 // TODO: sequences (`gg`)
363 // TODO: sequences (`gg`)
@@ -380,7 +375,31 @@ impl Application {
380 }
375 }
381 view.ensure_cursor_in_view();
376 view.ensure_cursor_in_view();
382 }
377 }
383− Mode::Command => unreachable!(),
378+ Mode::Normal => {
379+ if let &[KeyEvent {
380+ code: KeyCode::Char(':'),
381+ ..
382+ }] = keys.as_slice()
383+ {
384+ let prompt = Prompt::new(
385+ ":".to_owned(),
386+ |_input: &str| None, // completion
387+ |editor: &mut Editor, input: &str| match input {
388+ "q" => editor.should_close = true,
389+ _ => (),
390+ },
391+ );
392+
393+ self.prompt = Some(prompt);
394+
395+ // HAXX: special casing for command mode
396+ } else if let Some(command) = keymap[&Mode::Normal].get(&keys) {
397+ command(view, 1);
398+
399+ // TODO: simplistic ensure cursor in view for now
400+ view.ensure_cursor_in_view();
401+ }
402+ }
384 mode => {
403 mode => {
385 if let Some(command) = keymap[&mode].get(&keys) {
404 if let Some(command) = keymap[&mode].get(&keys) {
386 command(view, 1);
405 command(view, 1);
helix-view/src/commands.rs+14−3
@@ -307,8 +307,19 @@ pub fn append_mode(view: &mut View, _count: usize) {
307 })
307 })
308}
308}
309
309
310−pub fn command_mode(view: &mut View, _count: usize) {
310+pub fn command_mode(_view: &mut View, _count: usize) {
311− view.state.mode = Mode::Command;
311+ use crate::Editor;
312+
313+ let prompt = Prompt::new(
314+ ":".to_owned(),
315+ |_input: &str| None, // completion
316+ |editor: &mut Editor, input: &str| match input {
317+ "q" => editor.should_close = true,
318+ _ => (),
319+ },
320+ );
321+
322+ // set_prompt(prompt)
312}
323}
313
324
314// TODO: I, A, o and O can share a lot of the primitives.
325// TODO: I, A, o and O can share a lot of the primitives.
@@ -627,7 +638,7 @@ pub fn unindent(view: &mut View, _count: usize) {
627 append_changes_to_history(view);
638 append_changes_to_history(view);
628}
639}
629
640
630−pub fn indent_selection(view: &mut View, _count: usize) {
641+pub fn indent_selection(_view: &mut View, _count: usize) {
631 // loop over each line and recompute proper indentation
642 // loop over each line and recompute proper indentation
632 unimplemented!()
643 unimplemented!()
633}
644}
helix-view/src/prompt.rs+19−16
@@ -4,54 +4,57 @@ use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
4use std::string::String;
4use std::string::String;
5
5
6pub struct Prompt {
6pub struct Prompt {
7− pub buffer: String,
7+ pub prompt: String,
8− pub cursor_loc: usize,
8+ pub line: String,
9+ pub cursor: usize,
9 completion_fn: Box<dyn FnMut(&str) -> Option<Vec<&str>>>,
10 completion_fn: Box<dyn FnMut(&str) -> Option<Vec<&str>>>,
10 callback_fn: Box<dyn FnMut(&mut Editor, &str)>,
11 callback_fn: Box<dyn FnMut(&mut Editor, &str)>,
11}
12}
12
13
13impl Prompt {
14impl Prompt {
14 pub fn new(
15 pub fn new(
16+ prompt: String,
15 completion_fn: impl FnMut(&str) -> Option<Vec<&str>> + 'static,
17 completion_fn: impl FnMut(&str) -> Option<Vec<&str>> + 'static,
16 callback_fn: impl FnMut(&mut Editor, &str) + 'static,
18 callback_fn: impl FnMut(&mut Editor, &str) + 'static,
17 ) -> Prompt {
19 ) -> Prompt {
18 Prompt {
20 Prompt {
21+ prompt,
19− buffer: String::from(""),
22+ line: String::new(),
20− cursor_loc: 0,
23+ cursor: 0,
21 completion_fn: Box::new(completion_fn),
24 completion_fn: Box::new(completion_fn),
22 callback_fn: Box::new(callback_fn),
25 callback_fn: Box::new(callback_fn),
23 }
26 }
24 }
27 }
25
28
26 pub fn insert_char(&mut self, c: char) {
29 pub fn insert_char(&mut self, c: char) {
27− self.buffer.insert(self.cursor_loc, c);
30+ self.line.insert(self.cursor, c);
28− self.cursor_loc += 1;
31+ self.cursor += 1;
29 }
32 }
30
33
31 pub fn move_char_left(&mut self) {
34 pub fn move_char_left(&mut self) {
32− if self.cursor_loc > 1 {
35+ if self.cursor > 1 {
33− self.cursor_loc -= 1;
36+ self.cursor -= 1;
34 }
37 }
35 }
38 }
36
39
37 pub fn move_char_right(&mut self) {
40 pub fn move_char_right(&mut self) {
38− if self.cursor_loc < self.buffer.len() {
41+ if self.cursor < self.line.len() {
39− self.cursor_loc += 1;
42+ self.cursor += 1;
40 }
43 }
41 }
44 }
42
45
43 pub fn move_start(&mut self) {
46 pub fn move_start(&mut self) {
44− self.cursor_loc = 0;
47+ self.cursor = 0;
45 }
48 }
46
49
47 pub fn move_end(&mut self) {
50 pub fn move_end(&mut self) {
48− self.cursor_loc = self.buffer.len();
51+ self.cursor = self.line.len();
49 }
52 }
50
53
51 pub fn delete_char_backwards(&mut self) {
54 pub fn delete_char_backwards(&mut self) {
52− if self.cursor_loc > 0 {
55+ if self.cursor > 0 {
53− self.buffer.remove(self.cursor_loc - 1);
56+ self.line.remove(self.cursor - 1);
54− self.cursor_loc -= 1;
57+ self.cursor -= 1;
55 }
58 }
56 }
59 }
57
60
@@ -87,7 +90,7 @@ impl Prompt {
87 KeyEvent {
90 KeyEvent {
88 code: KeyCode::Enter,
91 code: KeyCode::Enter,
89 ..
92 ..
90− } => (self.callback_fn)(editor, &self.buffer),
93+ } => (self.callback_fn)(editor, &self.line),
91 _ => (),
94 _ => (),
92 }
95 }
93 }
96 }