Restoring of tty state on panic

master
itycodes 6 hours ago
parent c249c3a7bc
commit 12824e638c

@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
libc = "0.2.181" libc = { version = "0.2.181", features = ["extra_traits"] }

@ -1,18 +1,25 @@
pub mod reader; pub mod reader;
use std::sync::{Arc, Mutex};
use reader::ReaderState; use reader::ReaderState;
fn main() { fn main() {
let mut state = ReaderState::new("uwu> "); let state = Arc::new(Mutex::new(ReaderState::new("uwu> ")));
assert!(ReaderState::init_tty().is_ok()); let state_r = state.clone();
assert!(state.lock().unwrap().init_tty().is_ok());
std::panic::set_hook(Box::new(move |_| {
let _ = state_r.lock().unwrap().restore_tty();
}));
loop { loop {
let line = state.read_line(); let line = state.lock().unwrap().read_line();
match line { match line {
Ok(s) => println!("{}", s), Ok(s) => println!("{}", s),
Err(e) => { Err(e) => {
eprintln!("Error: {:?}", e); eprintln!("\nError: {:?}", e);
break; break;
} }
} }
} }
let _ = state.lock().unwrap().restore_tty();
} }

@ -8,6 +8,7 @@ pub mod esc_parse;
#[derive(Default)] #[derive(Default)]
pub struct ReaderState { pub struct ReaderState {
saved_termios: Option<libc::termios>,
prompt: String, prompt: String,
line: String, line: String,
cursor: usize, cursor: usize,
@ -63,7 +64,7 @@ impl ReaderState {
pub fn empty(&mut self) { pub fn empty(&mut self) {
self.set_line(String::from("")); self.set_line(String::from(""));
} }
pub fn init_tty() -> Result<(), InitTTYError> { pub fn init_tty(&mut self) -> Result<(), InitTTYError> {
unsafe { unsafe {
use libc::{isatty, termios, ECHO, ICANON, INPCK, TCSANOW, tcgetattr, tcsetattr}; use libc::{isatty, termios, ECHO, ICANON, INPCK, TCSANOW, tcgetattr, tcsetattr};
if !(isatty(0) == 1) { if !(isatty(0) == 1) {
@ -71,12 +72,26 @@ impl ReaderState {
} }
let mut termios: termios = MaybeUninit::zeroed().assume_init(); let mut termios: termios = MaybeUninit::zeroed().assume_init();
tcgetattr(0, &mut termios); tcgetattr(0, &mut termios);
self.saved_termios = Some(termios.clone());
termios.c_lflag &= !(ECHO | ICANON); termios.c_lflag &= !(ECHO | ICANON);
termios.c_iflag &= !(INPCK); termios.c_iflag &= !(INPCK);
tcsetattr(0, TCSANOW, &termios); tcsetattr(0, TCSANOW, &termios);
return Ok(()); return Ok(());
} }
} }
pub fn restore_tty(&self) -> Result<(), ()> {
unsafe {
use libc::{tcsetattr, TCSANOW};
if self.saved_termios.is_none() {
Err(())
} else {
tcsetattr(0, TCSANOW, &self.saved_termios.unwrap());
Ok(())
}
}
}
pub fn insert_at_cursor(&mut self, txt: String) { pub fn insert_at_cursor(&mut self, txt: String) {
self.line.insert_str(self.cursor, txt.as_str()); self.line.insert_str(self.cursor, txt.as_str());
self.cursor += txt.len(); self.cursor += txt.len();
@ -187,6 +202,7 @@ impl ReaderState {
NewLine => { NewLine => {
let line = self.line.clone(); let line = self.line.clone();
self.submit_line(line.clone()); self.submit_line(line.clone());
println!("{}", line);
return Ok(line) return Ok(line)
}, },
CursorBack => { CursorBack => {

Loading…
Cancel
Save