Complete chapter 4
This commit is contained in:
parent
fd9f504266
commit
0c81912cac
@ -6,7 +6,7 @@ use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::io::BufReader;
|
||||
use std::string::ToString;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use self::EditorKey::*;
|
||||
|
||||
@ -30,7 +30,7 @@ impl EditorRow {
|
||||
|
||||
/// Main structure for the editor
|
||||
/// `EditorConfig` struct in C version
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug)]
|
||||
pub struct Editor {
|
||||
cursor_x: usize,
|
||||
cursor_y: usize,
|
||||
@ -41,6 +41,8 @@ pub struct Editor {
|
||||
screen_rows: usize,
|
||||
rows: Vec<EditorRow>,
|
||||
filename: String,
|
||||
status_message: String,
|
||||
status_message_time: Instant,
|
||||
output_buffer: String,
|
||||
}
|
||||
|
||||
@ -72,6 +74,25 @@ impl EditorKey<char> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Editor {
|
||||
fn default() -> Self {
|
||||
Editor {
|
||||
cursor_x: 0,
|
||||
cursor_y: 0,
|
||||
render_x: 0,
|
||||
col_offset: 0,
|
||||
row_offset: 0,
|
||||
screen_cols: 0,
|
||||
screen_rows: 0,
|
||||
rows: vec![],
|
||||
filename: String::new(),
|
||||
status_message: String::new(),
|
||||
status_message_time: Instant::now(),
|
||||
output_buffer: String::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Editor {
|
||||
// ------------------------------------------------------------------------
|
||||
// Init
|
||||
@ -79,12 +100,11 @@ impl Editor {
|
||||
|
||||
pub fn new() -> Self {
|
||||
let mut instance = Self::default();
|
||||
|
||||
let size = instance.get_window_size();
|
||||
instance.rows = vec![];
|
||||
instance.cursor_x = 0;
|
||||
instance.cursor_y = 0;
|
||||
|
||||
instance.screen_cols = size.cols as usize;
|
||||
instance.screen_rows = (size.rows - 1) as usize;
|
||||
instance.screen_rows = (size.rows - 2) as usize;
|
||||
|
||||
instance
|
||||
}
|
||||
@ -414,7 +434,6 @@ impl Editor {
|
||||
let mut len = left_message.len();
|
||||
let mut rlen = right_message.len();
|
||||
if len > self.screen_cols {
|
||||
|
||||
len = self.screen_cols;
|
||||
left_message.truncate(len);
|
||||
}
|
||||
@ -428,6 +447,22 @@ impl Editor {
|
||||
self.append_out(" ");
|
||||
}
|
||||
self.append_out("\x1b[m");
|
||||
self.append_out("\r\n");
|
||||
}
|
||||
|
||||
fn draw_message_bar(&mut self) {
|
||||
self.append_out("\x1b[K");
|
||||
|
||||
let mut message = self.status_message.clone();
|
||||
let message_len = message.len();
|
||||
if message_len > self.screen_cols {
|
||||
message.truncate(self.screen_cols);
|
||||
}
|
||||
|
||||
let five_seconds = Duration::from_secs(5);
|
||||
if message_len > 0 && self.status_message_time.elapsed() < five_seconds {
|
||||
self.append_out(&message);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn refresh_screen(&mut self) -> io::Result<()> {
|
||||
@ -440,11 +475,12 @@ impl Editor {
|
||||
|
||||
self.draw_rows();
|
||||
self.draw_status_bar();
|
||||
self.draw_message_bar();
|
||||
|
||||
// Move cursor to state position
|
||||
let y = (self.cursor_y - self.row_offset) + 1;
|
||||
let x = (self.render_x - self.col_offset) + 1;
|
||||
let cursor_code = format!("\x1b[{y};{x}H", y=y, x=x);
|
||||
let cursor_code = format!("\x1b[{y};{x}H", y = y, x = x);
|
||||
self.append_out(&cursor_code);
|
||||
|
||||
// Show cursor
|
||||
@ -455,6 +491,25 @@ impl Editor {
|
||||
handle.write_all(&self.output_buffer.as_bytes())
|
||||
}
|
||||
|
||||
/// Set the status bar message
|
||||
///
|
||||
/// To avoid creating a macro that would just forward to
|
||||
/// the `format!` macro, this method only accepts a pre-formatted
|
||||
/// string.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no-run
|
||||
/// # use rs-kilo::editor::Editor;
|
||||
/// # let editor = Editor::new();
|
||||
/// let message = format!("{} is {}", key, status);
|
||||
/// editor.set_status_message(&message);
|
||||
/// ```
|
||||
pub fn set_status_message(&mut self, message: &str) {
|
||||
self.status_message = message.to_owned();
|
||||
self.status_message_time = Instant::now();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Row Operations
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -25,6 +25,8 @@ fn main() -> Result<(), Error> {
|
||||
editor.open(&args[1])?;
|
||||
}
|
||||
|
||||
editor.set_status_message("HELP: Ctrl-Q = quit");
|
||||
|
||||
// Main input loop. Editor::process_keypress uses an Option Enum as a sentinel.
|
||||
// `None` is returned on a quit action, in other cases, `Some(())` is returned,
|
||||
// continuing the loop
|
||||
|
Loading…
Reference in New Issue
Block a user