rs-kilo/src/editor.rs

168 lines
4.4 KiB
Rust
Raw Normal View History

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
///
/// impl blocks are split similarly to the original C implementation
2019-08-23 16:46:04 -04:00
#[derive(Debug, Default)]
pub struct Editor {
2019-08-26 10:04:12 -04:00
screen_cols: usize,
screen_rows: usize,
output_buffer: String,
2019-08-23 16:46:04 -04:00
}
2019-08-22 14:25:18 -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();
2019-08-26 10:04:12 -04:00
instance.screen_cols = size.cols as usize;
instance.screen_rows = size.rows as usize;
2019-08-23 16:46:04 -04:00
instance
2019-08-22 16:44:47 -04:00
}
}
2019-08-22 16:44:47 -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();
let stdin = stdin.lock();
2019-08-22 16:44:47 -04:00
let mut in_str = String::new();
let mut input = BufReader::with_capacity(3, stdin);
2019-08-22 16:44:47 -04:00
input.read_to_string(&mut in_str).unwrap();
let mut output: Vec<char> = vec![];
for char in in_str.chars() {
output.push(char);
}
if output.len() == 0 {
return None;
2019-08-22 16:44:47 -04:00
}
return Some(output);
}
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-22 16:44:47 -04:00
// Input
impl Editor {
2019-08-23 16:46:04 -04:00
/// 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];
2019-08-22 16:44:47 -04:00
if first == ctrl_key('q') {
2019-08-23 16:46:04 -04:00
clear_and_reset();
// Break out of the input loop
return None;
}
print!("{:?}\r\n", chars);
// Continue the main input loop
Some(())
}
}
2019-08-22 14:25:18 -04:00
}
}
// Output
impl Editor {
2019-08-26 10:04:12 -04:00
/// Equivalent of the abAppend function
/// in the original tutorial, just appends
/// to the `output_buffer` String in the
/// editor struct.
fn append_out(&mut self, str: &str) {
self.output_buffer.push_str(str);
}
2019-08-23 16:46:04 -04:00
fn draw_rows(&mut self) {
2019-08-26 10:04:12 -04:00
for y in 0..self.screen_rows {
if y == (self.screen_rows / 3) {
let mut welcome = format!("Kilo editor -- version {}", env!("CARGO_PKG_VERSION"));
if welcome.len() > self.screen_cols {
welcome.truncate(self.screen_cols)
}
// Center welcome message
let mut padding = (self.screen_cols - welcome.len()) / 2;
if padding > 0 {
self.append_out("~");
padding -= 1;
}
while padding > 0 {
self.append_out(" ");
padding -=1;
}
self.append_out(&welcome);
} else {
self.append_out("~");
}
2019-08-26 10:04:12 -04:00
self.append_out("\x1b[K");
if y < (self.screen_rows as usize - 1) {
self.append_out("\r\n");
}
2019-08-23 16:46:04 -04:00
}
}
pub fn refresh_screen(&mut self) {
2019-08-26 10:04:12 -04:00
self.output_buffer.clear();
2019-08-23 16:46:04 -04:00
2019-08-26 10:04:12 -04:00
// Hide cursor, reposition cursor
self.append_out("\x1b[?25l");
self.append_out("\x1b[H");
2019-08-23 16:46:04 -04:00
self.draw_rows();
2019-08-26 10:04:12 -04:00
self.append_out("\x1b[H");
self.append_out("\x1b[?25h");
let stdout = io::stdout();
let mut handle = stdout.lock();
handle.write_all(&self.output_buffer.as_bytes()).unwrap();
}
}