Improve editor (#77)

* Show write status in editor

* Add 'help edit' command

* Show pathname in status bar

* Update status bar colors

* Avoid clearing before printing by overwriting whole lines
This commit is contained in:
Vincent Ollivier 2020-07-14 11:34:38 +02:00 committed by GitHub
parent 1f86f6ba7f
commit b0266744c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 12 deletions

View File

@ -1,4 +1,6 @@
use crate::{kernel, print, user};
use crate::kernel::console::Style;
use alloc::format;
use alloc::string::String;
use alloc::vec::Vec;
use core::cmp;
@ -56,26 +58,43 @@ impl Editor {
if let Some(file) = &mut self.file {
file.write(&contents.as_bytes()).unwrap();
let status = format!("Wrote {}L to '{}'", n, self.pathname);
self.print_status(&status, "Yellow");
user::shell::ExitCode::CommandSuccessful
} else {
print!("Could not write to '{}'\n", self.pathname);
let status = format!("Could not write to '{}'", self.pathname);
self.print_status(&status, "LightRed");
user::shell::ExitCode::CommandError
}
}
fn print_status(&mut self, status: &str, background: &str) {
let csi_color = Style::color("Black").with_background(background);
let csi_reset = Style::reset();
let (x, y) = kernel::vga::cursor_position();
kernel::vga::set_writer_position(0, self.height());
print!("{}{:width$}{}", csi_color, status, csi_reset, width = self.width());
kernel::vga::set_writer_position(x, y);
kernel::vga::set_cursor_position(x, y);
}
fn print_screen(&mut self) {
let mut lines: Vec<String> = Vec::new();
let from = self.offset;
let to = cmp::min(self.lines.len(), self.offset + self.height());
for i in from..to {
let n = cmp::min(self.lines[i].len(), 80);
lines.push(self.lines[i][0..n].into()) // TODO: Use `offset_x .. offset_x + n`
let n = self.width();
let line = format!("{:width$}", self.lines[i], width = n);
lines.push(line[0..n].into()); // TODO: Use `offset_x .. offset_x + n`
}
kernel::vga::clear_screen();
kernel::vga::set_writer_position(0, 0);
print!("{}", lines.join("\n"));
let status = format!("Editing '{}'", self.pathname);
self.print_status(&status, "LightGray");
}
pub fn run(&mut self) -> user::shell::ExitCode {
kernel::vga::clear_screen();
self.print_screen();
kernel::vga::set_cursor_position(0, 0);
kernel::vga::set_writer_position(0, 0);
@ -87,10 +106,6 @@ impl Editor {
'\0' => {
continue;
}
'\x03' => { // Ctrl C
kernel::vga::clear_screen();
break;
}
'\x11' => { // Ctrl Q
// TODO: Warn if modifications have not been saved
kernel::vga::clear_screen();
@ -100,8 +115,9 @@ impl Editor {
self.save();
},
'\x18' => { // Ctrl X
let res = self.save();
kernel::vga::clear_screen();
return self.save();
return res;
},
'\n' => { // Newline
let new_line = self.lines[self.offset + y].split_off(x);
@ -234,7 +250,7 @@ impl Editor {
}
fn height(&self) -> usize {
kernel::vga::screen_height()
kernel::vga::screen_height() - 1 // Leave out one line for status line
}
fn width(&self) -> usize {

View File

@ -1,7 +1,27 @@
use crate::{print, user};
use crate::kernel::console::Style;
pub fn main(_args: &[&str]) -> user::shell::ExitCode {
pub fn main(args: &[&str]) -> user::shell::ExitCode {
if args.len() > 1 {
help_command(args[1])
} else {
help_summary()
}
}
fn help_command(cmd: &str) -> user::shell::ExitCode {
match cmd {
"edit" => help_edit(),
_ => help_unknown(cmd),
}
}
fn help_unknown(cmd: &str) -> user::shell::ExitCode {
print!("Help not found for command '{}'\n", cmd);
user::shell::ExitCode::CommandError
}
fn help_summary() -> user::shell::ExitCode {
let csi_color = Style::color("Yellow");
let csi_reset = Style::reset();
print!("{}Commands:{}\n", csi_color, csi_reset);
@ -12,7 +32,7 @@ pub fn main(_args: &[&str]) -> user::shell::ExitCode {
("d", "elete <file>", "Delete file or empty directory\n"),
("e", "dit <file>", "Edit existing or new file\n"),
("g", "oto <dir>", "Go to directory\n"),
("h", "elp", "Display this text\n"),
("h", "elp <command>", "Display help about a command\n"),
("l", "ist <dir>", "List entries in directory\n"),
("m", "ove <file> <file>", "Move file from source to destination\n"),
("p", "rint <string>", "Print string to screen\n"),
@ -33,3 +53,29 @@ pub fn main(_args: &[&str]) -> user::shell::ExitCode {
print!("Made with <3 in 2019-2020 by Vincent Ollivier <v@vinc.cc>\n");
user::shell::ExitCode::CommandSuccessful
}
fn help_edit() -> user::shell::ExitCode {
let csi_color = Style::color("Yellow");
let csi_reset = Style::reset();
print!("MOROS text editor is somewhat inspired by nano, but with an even smaller range\n");
print!("of features.\n");
print!("\n");
print!("{}Shortcuts:{}\n", csi_color, csi_reset);
print!("\n");
let shortcuts = [
("^Q", "Quit editor"),
("^W", "Write to file"),
("^X", "Write to file and quit"),
("^T", "Go to top of file"),
("^B", "Go to bottom of file"),
("^A", "Go to beginning of line"),
("^E", "Go to end of line"),
];
for (shortcut, usage) in &shortcuts {
let csi_color = Style::color("LightGreen");
let csi_reset = Style::reset();
print!(" {}{}{} {}\n", csi_color, shortcut, csi_reset, usage);
}
user::shell::ExitCode::CommandSuccessful
}