use alloc::{string::String, vec::Vec, boxed::Box}; use core::any::Any; use crate::std::{application::{Application, Error}, render::Window}; use async_trait::async_trait; use vga::writers::PrimitiveDrawing; use crate::apps::calc::Calculator; use crate::apps::editor::Editor; use crate::apps::grapher::Grapher; use crate::apps::tasks::Tasks; use crate::games::gameoflife::GameOfLife; use crate::games::paper_rs::GameBoard; use crate::{games, println, utils}; use crate::std::io::{Display, Serial}; use crate::std::render::{ColouredChar, Frame, RenderError}; use crate::std::time::timer; use crate::user::lib::libgui::cg_core::CgComponent; use crate::utils::crystalfetch::CrystalFetch; use crate::utils::gigachad_detector::GigachadDetector; use crate::utils::rickroll::Rickroll; pub struct ZxqSH { history: Vec, history_idx: usize, row_pos: usize, col_pos: usize, window: Window, buffer: Vec>, buffer_width: usize, } #[async_trait] impl Application for ZxqSH { fn new() -> Self { todo!() } async fn run(&mut self, window: Option, _args: Vec) -> Result<(), Error> { loop { if let Ok(exit) = self.next().await { if exit { return Ok(()) } } } } } impl ZxqSH { async fn next(&mut self) -> Result { // update cycle for the shell // TODO: prompt let command = String::new(); // TODO: exit if necessary // TODO: execute command self.execute(command, Vec::new()).await; // return Ok(false) } async fn write_char(&mut self, ch: char) { self.buffer[self.row_pos][self.col_pos] = ColouredChar::new(ch); } async fn execute(&self, cmd: String, args: Vec) -> Result<(), Error> { let window = Window::new(); match cmd.as_str() { "calculate" | "calc" | "solve" => Calculator::new().run(Some(window), args).await?, "games/connect4" => crate::user::bin::games::connect4::Game::new().run(Some(window), args).await?, "rickroll" => Rickroll::new().run(Some(window), args).await?, "crystalfetch" => CrystalFetch::new().run(Some(window), args).await?, "tasks" => Tasks::new().run(Some(window), args).await?, "VGA" => { use vga::colors::Color16; use vga::writers::{GraphicsWriter, Graphics640x480x16}; let mode = Graphics640x480x16::new(); mode.set_mode(); mode.clear_screen(Color16::Black); mode.draw_line((80, 60), (120, 420), Color16::Cyan); }, "graph" => Grapher::new().run(Some(window), args).await?, "games/snake" => games::snake::Game::new().run(Some(window), args).await?, "games/asteroids" => games::asteroids::Game::new().run(Some(window), args).await?, "games/pong" => games::pong::Game::new().run(Some(window), args).await?, "games/paper.rs" => games::paper_rs::GameBoard::new().run(Some(window), args).await?, "serial" => println!("{}", Serial::reply_char('e')), "games/gameoflife" => GameOfLife::new().run(Some(window), Vec::new()).await?, "games/tetris" => { // games::tetris::TetrisEngine::new().run(Vec::new()).await?; } "gigachad?" => utils::gigachad_detector::GigachadDetector::new().run(Some(window), args).await?, "editor" => Editor::new().run(Some(window), args).await?, // direct OS functions (not applications) "echo" => { println!( "Crystal: '{}'", args.into_iter() .map(|mut s| { s.push_str(" "); s }) .collect::() ) } "clear" => Display::clear(), "time" => timer(), _ => return Err(Error::UnknownCommand(cmd)) }; Ok(()) } } impl CgComponent for ZxqSH { fn render(&self) -> Result { let mut frame = Frame::from_window(&self.window); let term_height = self.window.dimensions().y; let term_width = self.window.dimensions().x; let buffer_width = self.buffer_width; let buffer_height = self.buffer.len(); self.window.move_cursor(self.col_pos as i32, term_height as i32)?; // render the contents of the terminal to a frame for (i, row) in self.buffer[buffer_height - term_height..buffer_height].iter().enumerate() { for (j, col) in row.iter().enumerate().take(term_width) { frame[i][j] = *col; } } Ok(frame) } fn as_any(&self) -> &dyn Any { self as &dyn Any } }