//! Editor functionality use crate::helpers::*; use std::io; use std::io::prelude::*; use std::io::BufReader; /// Main structure for the editor /// /// impl blocks are split similarly to the original C implementation #[derive(Debug, Default)] pub struct Editor { screen_cols: u16, screen_rows: u16, } // init impl Editor { pub fn new() -> Self { let mut instance = Self::default(); let size = instance.get_window_size(); instance.screen_cols = size.cols; instance.screen_rows = size.rows; instance } } // Terminal impl Editor { fn read_key(&mut self) -> Option> { let stdin = io::stdin(); let stdin = stdin.lock(); let mut in_str = String::new(); let mut input = BufReader::with_capacity(3, stdin); input.read_to_string(&mut in_str).unwrap(); let mut output: Vec = vec![]; for char in in_str.chars() { output.push(char); } if output.len() == 0 { return None; } return Some(output); } fn get_cursor_position(&mut self) -> TermSize { let stdout = io::stdout(); let mut handle = stdout.lock(); let buffer = String::from("\x1b[6n").into_bytes(); handle.write(&buffer).unwrap(); let stdin = io::stdin(); let stdin = stdin.lock(); let mut in_buf = String::new().into_bytes(); let mut input = BufReader::with_capacity(32, stdin); input.read_until('R' as u8, &mut in_buf).unwrap(); // @TODO Find a solution to retrieve the cursor coordinates unimplemented!(); } fn get_window_size(&mut self) -> TermSize { match get_term_size() { Some(size) => size, None => { let stdout = io::stdout(); let mut handle = stdout.lock(); let buffer = String::from("\x1b[999C\x1b[999B").into_bytes(); handle.write(&buffer).unwrap(); self.get_cursor_position() } } } } // Input impl Editor { /// Route user input to the appropriate handler method pub fn process_keypress(&mut self) -> Option<()> { match self.read_key() { // Just continue the input loop on an "empty" keypress None => Some(()), Some(chars) => { let first = chars[0]; if first == ctrl_key('q') { clear_and_reset(); // Break out of the input loop return None; } print!("{:?}\r\n", chars); // Continue the main input loop Some(()) } } } } // Output impl Editor { fn draw_rows(&mut self) { let stdout = io::stdout(); let mut handle = stdout.lock(); let buffer = String::from("~\r\n").into_bytes(); for _ in 0..self.screen_rows as usize { handle.write(&buffer).unwrap(); } } pub fn refresh_screen(&mut self) { let stdout = io::stdout(); let mut handle = stdout.lock(); // Clear screen let mut buffer = String::from("\x1b[2J").into_bytes(); handle.write_all(&mut buffer).unwrap(); // Reposition cursor let mut buffer = String::from("\x1b[H").into_bytes(); handle.write_all(&mut buffer).unwrap(); self.draw_rows(); handle.write_all(&mut buffer).unwrap(); } }