From a65a1cc9b800578c39a168b45695934b5a69fa37 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Mon, 27 Feb 2023 21:35:38 +0100 Subject: [PATCH] allow cancelling in save path input prompt --- src/editor.rs | 22 ++++++++-------------- src/main.rs | 1 + src/util.rs | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 src/util.rs diff --git a/src/editor.rs b/src/editor.rs index 9c80be4..db2f0e8 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -12,6 +12,8 @@ use termion::{ terminal_size, }; +use crate::util::read_line; + const TAB_SIZE: usize = 4; pub struct Editor { @@ -20,7 +22,7 @@ pub struct Editor { scroll: usize, cursor: Cursor, path: Option, - term: RawTerminal, + _term: RawTerminal, quit: bool, } @@ -52,7 +54,7 @@ impl Editor { lines: Vec::new(), scroll: 0, cursor: Cursor { line: 0, column: 0 }, - term, + _term: term, path, quit: false, } @@ -255,20 +257,12 @@ impl Editor { fn save(&mut self) { if self.path.is_none() { - self.path = Some(self.read_line("Save as: ")); + self.path = read_line("Enter path: "); + if self.path.is_none() { + return; + } } let mut file = File::create(self.path.as_ref().unwrap()).unwrap(); file.write_all(self.text.as_bytes()).unwrap(); } - - fn read_line(&self, prompt: &str) -> String { - // TODO: use events instead and allow cancelling with esc - self.term.suspend_raw_mode().unwrap(); - print!("{}{prompt}", cursor::Goto(1, terminal_size().unwrap().1)); - stdout().flush().unwrap(); - let mut response = String::new(); - stdin().read_line(&mut response).unwrap(); - self.term.activate_raw_mode().unwrap(); - response.trim_end().into() - } } diff --git a/src/main.rs b/src/main.rs index d25ad80..d93b448 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ use std::env; mod editor; +mod util; use editor::Editor; fn main() { diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..40d96ba --- /dev/null +++ b/src/util.rs @@ -0,0 +1,38 @@ +use std::io::{stdin, stdout, Write}; + +use termion::{ + cursor, + event::{Event, Key}, + input::TermRead, + terminal_size, +}; + +pub fn read_line(prompt: &str) -> Option { + let mut response = String::new(); + let size = terminal_size().unwrap(); + let start_pos = cursor::Goto(1, size.1); + let width = size.0 as usize; + + print!("{start_pos}{prompt}{response}",); + stdout().flush().unwrap(); + + for event in stdin().events() { + if let Ok(Event::Key(key)) = event { + match key { + Key::Char('\n') => break, + Key::Char(ch) => response.push(ch), + Key::Backspace => { + if !response.is_empty() { + response.remove(response.len() - 1); + } + print!("{start_pos}{:width$}", " "); + } + Key::Esc => return None, + _ => (), + } + } + print!("{start_pos}{prompt}{response}",); + stdout().flush().unwrap(); + } + Some(response.trim().into()) +}