allow cancelling in save path input prompt

This commit is contained in:
Crispy 2023-02-27 21:35:38 +01:00
parent ad6e458812
commit a65a1cc9b8
3 changed files with 47 additions and 14 deletions

View file

@ -12,6 +12,8 @@ use termion::{
terminal_size, terminal_size,
}; };
use crate::util::read_line;
const TAB_SIZE: usize = 4; const TAB_SIZE: usize = 4;
pub struct Editor { pub struct Editor {
@ -20,7 +22,7 @@ pub struct Editor {
scroll: usize, scroll: usize,
cursor: Cursor, cursor: Cursor,
path: Option<String>, path: Option<String>,
term: RawTerminal<Stdout>, _term: RawTerminal<Stdout>,
quit: bool, quit: bool,
} }
@ -52,7 +54,7 @@ impl Editor {
lines: Vec::new(), lines: Vec::new(),
scroll: 0, scroll: 0,
cursor: Cursor { line: 0, column: 0 }, cursor: Cursor { line: 0, column: 0 },
term, _term: term,
path, path,
quit: false, quit: false,
} }
@ -255,20 +257,12 @@ impl Editor {
fn save(&mut self) { fn save(&mut self) {
if self.path.is_none() { 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(); let mut file = File::create(self.path.as_ref().unwrap()).unwrap();
file.write_all(self.text.as_bytes()).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()
}
} }

View file

@ -1,6 +1,7 @@
use std::env; use std::env;
mod editor; mod editor;
mod util;
use editor::Editor; use editor::Editor;
fn main() { fn main() {

38
src/util.rs Normal file
View file

@ -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<String> {
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())
}