pull/4/head
Blaž Hrastnik 4 years ago
parent 49b4cdb566
commit bc2c652fe8

@ -10,7 +10,6 @@ pub enum Mode {
Normal, Normal,
Insert, Insert,
Goto, Goto,
Command,
} }
/// A state represents the current editor state of a single buffer. /// A state represents the current editor state of a single buffer.

@ -225,7 +225,6 @@ impl Renderer {
Mode::Insert => "INS", Mode::Insert => "INS",
Mode::Normal => "NOR", Mode::Normal => "NOR",
Mode::Goto => "GOTO", Mode::Goto => "GOTO",
Mode::Command => "COM", // command?
}; };
// statusline // statusline
self.surface.set_style( self.surface.set_style(
@ -237,13 +236,15 @@ impl Renderer {
} }
pub fn render_prompt(&mut self, prompt: &Prompt) { pub fn render_prompt(&mut self, prompt: &Prompt) {
use tui::backend::Backend;
// render buffer text // render buffer text
self.surface self.surface
.set_string(1, self.size.1 - 1, String::from(":"), self.text_color); .set_string(1, self.size.1 - 1, &prompt.prompt, self.text_color);
self.surface self.surface
.set_string(2, self.size.1 - 1, &prompt.buffer, self.text_color); .set_string(2, self.size.1 - 1, &prompt.line, self.text_color);
}
pub fn draw(&mut self) {
use tui::backend::Backend;
// TODO: theres probably a better place for this // TODO: theres probably a better place for this
self.terminal self.terminal
.backend_mut() .backend_mut()
@ -259,7 +260,7 @@ impl Renderer {
mode => write!(stdout, "\x1B[2 q"), mode => write!(stdout, "\x1B[2 q"),
}; };
let pos = if let Some(prompt) = prompt { let pos = if let Some(prompt) = prompt {
Position::new(self.size.0 as usize, 2 + prompt.cursor_loc) Position::new(self.size.0 as usize, 2 + prompt.cursor)
} else { } else {
if let Some(path) = view.state.path() { if let Some(path) = view.state.path() {
self.surface.set_string( self.surface.set_string(
@ -303,15 +304,6 @@ impl Application {
Ok(app) Ok(app)
} }
pub fn set_prompt(&mut self) {
let commands = |editor: &mut Editor, input: &str| match input {
"q" => editor.should_close = true,
_ => (),
};
let prompt = Prompt::new(|input| None, commands);
self.prompt = Some(prompt);
}
fn render(&mut self) { fn render(&mut self) {
let viewport = Rect::new(OFFSET, 0, self.terminal.size.0, self.terminal.size.1 - 2); // - 2 for statusline and prompt let viewport = Rect::new(OFFSET, 0, self.terminal.size.0, self.terminal.size.1 - 2); // - 2 for statusline and prompt
@ -323,6 +315,8 @@ impl Application {
self.terminal.render_prompt(prompt); self.terminal.render_prompt(prompt);
} }
self.terminal.draw();
// TODO: drop unwrap // TODO: drop unwrap
self.terminal.render_cursor( self.terminal.render_cursor(
self.editor.view.as_ref().unwrap(), self.editor.view.as_ref().unwrap(),
@ -335,7 +329,6 @@ impl Application {
let mut reader = EventStream::new(); let mut reader = EventStream::new();
let keymap = keymap::default(); let keymap = keymap::default();
self.set_prompt();
self.render(); self.render();
loop { loop {
@ -363,6 +356,8 @@ impl Application {
.as_mut() .as_mut()
.unwrap() .unwrap()
.handle_input(event, &mut self.editor); .handle_input(event, &mut self.editor);
self.render();
} else if let Some(view) = &mut self.editor.view { } else if let Some(view) = &mut self.editor.view {
let keys = vec![event]; let keys = vec![event];
// TODO: sequences (`gg`) // TODO: sequences (`gg`)
@ -380,7 +375,31 @@ impl Application {
} }
view.ensure_cursor_in_view(); view.ensure_cursor_in_view();
} }
Mode::Command => unreachable!(), Mode::Normal => {
if let &[KeyEvent {
code: KeyCode::Char(':'),
..
}] = keys.as_slice()
{
let prompt = Prompt::new(
":".to_owned(),
|_input: &str| None, // completion
|editor: &mut Editor, input: &str| match input {
"q" => editor.should_close = true,
_ => (),
},
);
self.prompt = Some(prompt);
// HAXX: special casing for command mode
} else if let Some(command) = keymap[&Mode::Normal].get(&keys) {
command(view, 1);
// TODO: simplistic ensure cursor in view for now
view.ensure_cursor_in_view();
}
}
mode => { mode => {
if let Some(command) = keymap[&mode].get(&keys) { if let Some(command) = keymap[&mode].get(&keys) {
command(view, 1); command(view, 1);

@ -307,8 +307,19 @@ pub fn append_mode(view: &mut View, _count: usize) {
}) })
} }
pub fn command_mode(view: &mut View, _count: usize) { pub fn command_mode(_view: &mut View, _count: usize) {
view.state.mode = Mode::Command; use crate::Editor;
let prompt = Prompt::new(
":".to_owned(),
|_input: &str| None, // completion
|editor: &mut Editor, input: &str| match input {
"q" => editor.should_close = true,
_ => (),
},
);
// set_prompt(prompt)
} }
// TODO: I, A, o and O can share a lot of the primitives. // 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) {
append_changes_to_history(view); append_changes_to_history(view);
} }
pub fn indent_selection(view: &mut View, _count: usize) { pub fn indent_selection(_view: &mut View, _count: usize) {
// loop over each line and recompute proper indentation // loop over each line and recompute proper indentation
unimplemented!() unimplemented!()
} }

@ -4,54 +4,57 @@ use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use std::string::String; use std::string::String;
pub struct Prompt { pub struct Prompt {
pub buffer: String, pub prompt: String,
pub cursor_loc: usize, pub line: String,
pub cursor: usize,
completion_fn: Box<dyn FnMut(&str) -> Option<Vec<&str>>>, completion_fn: Box<dyn FnMut(&str) -> Option<Vec<&str>>>,
callback_fn: Box<dyn FnMut(&mut Editor, &str)>, callback_fn: Box<dyn FnMut(&mut Editor, &str)>,
} }
impl Prompt { impl Prompt {
pub fn new( pub fn new(
prompt: String,
completion_fn: impl FnMut(&str) -> Option<Vec<&str>> + 'static, completion_fn: impl FnMut(&str) -> Option<Vec<&str>> + 'static,
callback_fn: impl FnMut(&mut Editor, &str) + 'static, callback_fn: impl FnMut(&mut Editor, &str) + 'static,
) -> Prompt { ) -> Prompt {
Prompt { Prompt {
buffer: String::from(""), prompt,
cursor_loc: 0, line: String::new(),
cursor: 0,
completion_fn: Box::new(completion_fn), completion_fn: Box::new(completion_fn),
callback_fn: Box::new(callback_fn), callback_fn: Box::new(callback_fn),
} }
} }
pub fn insert_char(&mut self, c: char) { pub fn insert_char(&mut self, c: char) {
self.buffer.insert(self.cursor_loc, c); self.line.insert(self.cursor, c);
self.cursor_loc += 1; self.cursor += 1;
} }
pub fn move_char_left(&mut self) { pub fn move_char_left(&mut self) {
if self.cursor_loc > 1 { if self.cursor > 1 {
self.cursor_loc -= 1; self.cursor -= 1;
} }
} }
pub fn move_char_right(&mut self) { pub fn move_char_right(&mut self) {
if self.cursor_loc < self.buffer.len() { if self.cursor < self.line.len() {
self.cursor_loc += 1; self.cursor += 1;
} }
} }
pub fn move_start(&mut self) { pub fn move_start(&mut self) {
self.cursor_loc = 0; self.cursor = 0;
} }
pub fn move_end(&mut self) { pub fn move_end(&mut self) {
self.cursor_loc = self.buffer.len(); self.cursor = self.line.len();
} }
pub fn delete_char_backwards(&mut self) { pub fn delete_char_backwards(&mut self) {
if self.cursor_loc > 0 { if self.cursor > 0 {
self.buffer.remove(self.cursor_loc - 1); self.line.remove(self.cursor - 1);
self.cursor_loc -= 1; self.cursor -= 1;
} }
} }
@ -87,7 +90,7 @@ impl Prompt {
KeyEvent { KeyEvent {
code: KeyCode::Enter, code: KeyCode::Enter,
.. ..
} => (self.callback_fn)(editor, &self.buffer), } => (self.callback_fn)(editor, &self.line),
_ => (), _ => (),
} }
} }

Loading…
Cancel
Save