From c155247f1d48981119bcb1d539644c6c3e2445f0 Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Wed, 14 Aug 2024 07:49:06 -0700 Subject: [PATCH] [Teton] Terminal now owns the command str. --- rust/sys/teton/src/console.rs | 43 +++++------------- rust/sys/teton/src/main.rs | 4 +- rust/sys/teton/src/terminal.rs | 80 +++++++++++++++++++++++++++++++++- 3 files changed, 89 insertions(+), 38 deletions(-) diff --git a/rust/sys/teton/src/console.rs b/rust/sys/teton/src/console.rs index e90e841..2e282dc 100644 --- a/rust/sys/teton/src/console.rs +++ b/rust/sys/teton/src/console.rs @@ -4,56 +4,33 @@ use crate::psf::Psf; pub struct Console { framebuffer: Framebuffer, psf: Psf, - row: u32, - col: u32, } impl Console { pub fn new(framebuffer: Framebuffer, psf: Psf) -> Self { - Self { - framebuffer, - psf, - row: 0, - col: 0, - } + Self { framebuffer, psf } } - fn incr_cursor(&mut self) { - self.col += 1; - if self.col >= self.cols() { - self.col = 0; - self.row += 1; + pub fn write_char(&mut self, chr: char, row: u32, col: u32) { + if row >= self.rows() { + panic!("Write at row {}, max is {}", row, self.rows()) } - - if self.row >= self.rows() { - panic!("Scroll unimplemented") - } - } - - pub fn write_char(&mut self, chr: char) { - if chr == '\x08' { - // Backspace. - if self.col > 1 { - self.col -= 1; - self.write_char(' '); - self.col -= 1; - } - return; + if col >= self.cols() { + panic!("Write at col {}, max is {}", col, self.cols()) } let glyph = self.psf.glyph(chr as u32); self.framebuffer.draw_glyph( glyph, - self.row * (self.psf.height() + 1), - self.col * (self.psf.width() + 1), + row * (self.psf.height() + 1), + col * (self.psf.width() + 1), ); - self.incr_cursor() } - fn cols(&self) -> u32 { + pub fn cols(&self) -> u32 { self.framebuffer.width() / (self.psf.width() + 1) } - fn rows(&self) -> u32 { + pub fn rows(&self) -> u32 { self.framebuffer.height() / (self.psf.height() + 1) } } diff --git a/rust/sys/teton/src/main.rs b/rust/sys/teton/src/main.rs index 73765a5..b1866d2 100644 --- a/rust/sys/teton/src/main.rs +++ b/rust/sys/teton/src/main.rs @@ -38,9 +38,7 @@ extern "C" fn main() -> z_err_t { .expect("Failed to create framebuffer"); let psf = psf::Psf::new("/default8x16.psfu").expect("Failed to open font file."); - let mut console = console::Console::new(framebuffer, psf); - console.write_char('>'); - + let console = console::Console::new(framebuffer, psf); let terminal = Rc::new(RefCell::new(terminal::Terminal::new(console))); let kb_listener = KeyboardListener::new(terminal).expect("Failed to create keyboard listener"); diff --git a/rust/sys/teton/src/terminal.rs b/rust/sys/teton/src/terminal.rs index 436fd48..1823de7 100644 --- a/rust/sys/teton/src/terminal.rs +++ b/rust/sys/teton/src/terminal.rs @@ -1,18 +1,94 @@ +use core::str::Split; + use crate::console::Console; +use alloc::{ + format, + string::{String, ToString}, +}; use voyageurs::listener::KeyboardHandler; pub struct Terminal { console: Console, + curr_cmd: String, + cwd: String, + row: u32, } impl KeyboardHandler for Terminal { fn handle_char(&mut self, c: char) { - self.console.write_char(c) + let mut should_execute = false; + match c { + '\x08' => { + let mut chars = self.curr_cmd.chars(); + chars.next_back(); // Pop last char. + self.curr_cmd = chars.collect(); + } + '\n' => should_execute = true, + _ => self.curr_cmd.push(c), + } + self.rewrite_command(); + if should_execute { + self.execute_command(); + self.rewrite_command(); + } } } impl Terminal { pub fn new(console: Console) -> Self { - Self { console } + let mut term = Self { + console, + curr_cmd: String::new(), + cwd: "/".to_string(), + row: 0, + }; + term.rewrite_command(); + term + } + + fn rewrite_command(&mut self) { + self.console.write_char('>', self.row, 0); + + let mut col = 1; + for c in self.curr_cmd.chars() { + self.console.write_char(c, self.row, col); + col += 1; + } + + // Hacky way to properly backspace. + // FIXME: This won't work once we have line wrapping. + self.console.write_char(' ', self.row, col) + } + + fn write_line(&mut self, line: &str) { + let mut col = 0; + for c in line.chars() { + self.console.write_char(c, self.row, col); + col += 1; + } + + self.row += 1 + } + + fn execute_command(&mut self) { + self.row += 1; + + let curr_cmd = self.curr_cmd.clone(); + let mut tokens = curr_cmd.split(' '); + + match tokens.next() { + None => {} + Some(command) => self.execute_command_parsed(command, tokens), + } + + self.curr_cmd.clear() + } + + fn execute_command_parsed(&mut self, cmd: &str, _args: Split<'_, char>) { + match cmd { + "help" => self.write_line("Available commands are 'pwd', 'ls', 'cd', and 'exec'"), + "pwd" => self.write_line(&self.cwd.clone()), + _ => self.write_line(&format!("Unrecognized command: {}", cmd)), + } } }