use std::io::{self, Read, Write}; use std::sync::{Arc, Mutex}; // STDIN is file descriptor (fd) 0 on Linux and other UN*X-likes pub const STDIN: i32 = 0; /// Retrieve a single byte of input /// /// Requires some setup beforehand (see beginning of repl()) fn getchar() -> u8 { let mut b = [0; 1]; io::stdout().lock().flush().unwrap(); io::stdin().read_exact(&mut b).unwrap(); b[0] } /// Handle user input at the repl prompt /// /// This is required instead of io::stdin().read_line(), because certain /// keys like `` and `` have special functions (cycle through /// autocomplete options, and history, respectively). It leverages /// [getchar] to read each character as the user inputs it. This also /// means special cases for handling backspace, newlines, etc. Assumes /// that (ICANON and ECHO) are off. See the beginning of [crate::repl] /// for more details. pub fn getline(buffer: &mut Arc>>) -> usize { // Keep track of position for backspaces let mut pos: usize = 0; // Loop over characters until there is a newline loop { let c = getchar(); match c { // enter/return b'\n' => break, // tab b'\t' => { pos += 1; print!(" "); buffer.lock().unwrap().push(b' '); } // ctrl-d 4 => return 0, // backspace 127 => { if pos == 0 { continue; } pos -= 1; buffer.lock().unwrap().pop(); print!("\u{8} \u{8}"); } // everything else _ => { pos += 1; print!("{}", c as char); buffer.lock().unwrap().push(c); } } } println!(); buffer.lock().unwrap().push(b'\n'); buffer.lock().unwrap().len() }