2019-08-22 14:25:18 -04:00
|
|
|
//! Editor functionality
|
2019-08-22 16:44:47 -04:00
|
|
|
use crate::helpers::*;
|
2019-08-22 14:25:18 -04:00
|
|
|
|
2019-08-22 16:44:47 -04:00
|
|
|
use std::io;
|
|
|
|
use std::io::prelude::*;
|
2019-08-23 16:46:04 -04:00
|
|
|
use std::io::BufReader;
|
2019-08-22 16:44:47 -04:00
|
|
|
|
|
|
|
/// Main structure for the editor
|
2019-08-23 14:57:26 -04:00
|
|
|
///
|
|
|
|
/// impl blocks are split similarly to the original C implementation
|
2019-08-23 16:46:04 -04:00
|
|
|
#[derive(Debug, Default)]
|
|
|
|
pub struct Editor {
|
|
|
|
screen_cols: u16,
|
|
|
|
screen_rows: u16,
|
|
|
|
}
|
2019-08-22 14:25:18 -04:00
|
|
|
|
2019-08-23 13:34:00 -04:00
|
|
|
// init
|
2019-08-22 14:25:18 -04:00
|
|
|
impl Editor {
|
|
|
|
pub fn new() -> Self {
|
2019-08-23 16:46:04 -04:00
|
|
|
let mut instance = Self::default();
|
|
|
|
let size = instance.get_window_size();
|
|
|
|
instance.screen_cols = size.cols;
|
|
|
|
instance.screen_rows = size.rows;
|
|
|
|
|
|
|
|
instance
|
2019-08-22 16:44:47 -04:00
|
|
|
}
|
2019-08-23 13:34:00 -04:00
|
|
|
}
|
2019-08-22 16:44:47 -04:00
|
|
|
|
2019-08-23 13:34:00 -04:00
|
|
|
// Terminal
|
|
|
|
impl Editor {
|
|
|
|
fn read_key(&mut self) -> Option<Vec<char>> {
|
2019-08-22 16:44:47 -04:00
|
|
|
let stdin = io::stdin();
|
2019-08-23 14:57:26 -04:00
|
|
|
let stdin = stdin.lock();
|
2019-08-22 16:44:47 -04:00
|
|
|
let mut in_str = String::new();
|
2019-08-23 14:57:26 -04:00
|
|
|
let mut input = BufReader::with_capacity(3, stdin);
|
2019-08-22 16:44:47 -04:00
|
|
|
input.read_to_string(&mut in_str).unwrap();
|
|
|
|
|
2019-08-23 13:34:00 -04:00
|
|
|
let mut output: Vec<char> = vec![];
|
|
|
|
|
|
|
|
for char in in_str.chars() {
|
|
|
|
output.push(char);
|
|
|
|
}
|
|
|
|
|
|
|
|
if output.len() == 0 {
|
2019-08-23 14:57:26 -04:00
|
|
|
return None;
|
2019-08-22 16:44:47 -04:00
|
|
|
}
|
|
|
|
|
2019-08-23 14:57:26 -04:00
|
|
|
return Some(output);
|
2019-08-23 13:34:00 -04:00
|
|
|
}
|
2019-08-23 16:46:04 -04:00
|
|
|
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-23 13:34:00 -04:00
|
|
|
}
|
2019-08-22 16:44:47 -04:00
|
|
|
|
2019-08-23 13:34:00 -04:00
|
|
|
// Input
|
|
|
|
impl Editor {
|
2019-08-23 16:46:04 -04:00
|
|
|
/// Route user input to the appropriate handler method
|
2019-08-23 13:34:00 -04:00
|
|
|
pub fn process_keypress(&mut self) -> Option<()> {
|
2019-08-23 14:57:26 -04:00
|
|
|
match self.read_key() {
|
|
|
|
// Just continue the input loop on an "empty" keypress
|
|
|
|
None => Some(()),
|
|
|
|
Some(chars) => {
|
|
|
|
let first = chars[0];
|
2019-08-22 16:44:47 -04:00
|
|
|
|
2019-08-23 14:57:26 -04:00
|
|
|
if first == ctrl_key('q') {
|
2019-08-23 16:46:04 -04:00
|
|
|
clear_and_reset();
|
|
|
|
|
2019-08-23 14:57:26 -04:00
|
|
|
// Break out of the input loop
|
|
|
|
return None;
|
|
|
|
}
|
2019-08-23 13:34:00 -04:00
|
|
|
|
2019-08-23 14:57:26 -04:00
|
|
|
print!("{:?}\r\n", chars);
|
2019-08-23 13:34:00 -04:00
|
|
|
|
2019-08-23 14:57:26 -04:00
|
|
|
// Continue the main input loop
|
|
|
|
Some(())
|
2019-08-23 13:34:00 -04:00
|
|
|
}
|
|
|
|
}
|
2019-08-22 14:25:18 -04:00
|
|
|
}
|
2019-08-23 13:34:00 -04:00
|
|
|
}
|
|
|
|
|
2019-08-23 14:57:26 -04:00
|
|
|
// Output
|
|
|
|
impl Editor {
|
2019-08-23 16:46:04 -04:00
|
|
|
fn draw_rows(&mut self) {
|
2019-08-23 14:57:26 -04:00
|
|
|
let stdout = io::stdout();
|
|
|
|
let mut handle = stdout.lock();
|
2019-08-23 16:46:04 -04:00
|
|
|
let buffer = String::from("~\r\n").into_bytes();
|
2019-08-23 14:57:26 -04:00
|
|
|
|
2019-08-23 16:46:04 -04:00
|
|
|
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
|
2019-08-23 14:57:26 -04:00
|
|
|
let mut buffer = String::from("\x1b[2J").into_bytes();
|
2019-08-23 16:46:04 -04:00
|
|
|
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();
|
2019-08-23 13:34:00 -04:00
|
|
|
|
2019-08-23 14:57:26 -04:00
|
|
|
handle.write_all(&mut buffer).unwrap();
|
|
|
|
}
|
2019-08-23 13:34:00 -04:00
|
|
|
}
|