updating apps to work with new API, working on new terminal app. a lot of stuff is broken rn :/
This commit is contained in:
+13
-1
@@ -4,10 +4,15 @@
|
|||||||
#![test_runner(CrystalOS::test_runner)]
|
#![test_runner(CrystalOS::test_runner)]
|
||||||
#![reexport_test_harness_main = "test_main"]
|
#![reexport_test_harness_main = "test_main"]
|
||||||
|
|
||||||
|
use alloc::vec::Vec;
|
||||||
use bootloader::{entry_point, BootInfo};
|
use bootloader::{entry_point, BootInfo};
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
use CrystalOS::std::tasks::{Executor, Task};
|
use CrystalOS::std::tasks::{Executor, Task};
|
||||||
use CrystalOS::{printerr, serial_println, std::syscall};
|
use CrystalOS::{printerr, serial_println, std::syscall};
|
||||||
|
use CrystalOS::apps::zxqsh::ZxqSH;
|
||||||
|
use CrystalOS::std::application::Application;
|
||||||
|
use CrystalOS::std::render::Window;
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use CrystalOS::user::bin::shell;
|
use CrystalOS::user::bin::shell;
|
||||||
|
|
||||||
@@ -37,9 +42,16 @@ fn main(boot_info: &'static BootInfo) -> ! {
|
|||||||
|
|
||||||
// runs the 'mainloop' of the OS;
|
// runs the 'mainloop' of the OS;
|
||||||
let mut executor = Executor::new();
|
let mut executor = Executor::new();
|
||||||
executor.spawn(Task::new(shell::command_handler()));
|
// executor.spawn(Task::new(shell::command_handler()));
|
||||||
|
executor.spawn(Task::new(start_shell()));
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
executor.try_run();
|
executor.try_run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn start_shell() {
|
||||||
|
let window = Window::new();
|
||||||
|
let mut shell = ZxqSH::new(Some(window)).unwrap();
|
||||||
|
shell.run(Vec::new()).await.unwrap();
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use alloc::string::String;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
@@ -5,6 +6,7 @@ use volatile::Volatile;
|
|||||||
|
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
use crate::serial_println;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
@@ -62,6 +64,14 @@ impl ScreenChar {
|
|||||||
colour: ColorCode::new(Color::White, Color::Black),
|
colour: ColorCode::new(Color::White, Color::Black),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn blank() -> ScreenChar {
|
||||||
|
ScreenChar {
|
||||||
|
character: ' ' as u8,
|
||||||
|
colour: ColorCode::new(Color::White, Color::Black),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn white(mut character: u8) -> ScreenChar {
|
pub fn white(mut character: u8) -> ScreenChar {
|
||||||
if let Some(c) = special_char(character as char) {
|
if let Some(c) = special_char(character as char) {
|
||||||
character = c;
|
character = c;
|
||||||
@@ -113,15 +123,17 @@ lazy_static! {
|
|||||||
impl Renderer {
|
impl Renderer {
|
||||||
// EXTERNAL API : for use by standard library and other parts of the kernel
|
// EXTERNAL API : for use by standard library and other parts of the kernel
|
||||||
pub fn render_frame(&mut self, mut frame: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT]) { // renders the given frame to the app buffer
|
pub fn render_frame(&mut self, mut frame: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT]) { // renders the given frame to the app buffer
|
||||||
|
|
||||||
for (i, row) in frame.iter_mut().enumerate() {
|
for (i, row) in frame.iter_mut().enumerate() {
|
||||||
for (j, col) in row.iter_mut().enumerate() {
|
for (j, col) in row.iter_mut().enumerate() {
|
||||||
|
if col.character == 0u8 { continue; }
|
||||||
if let Some(c) = special_char(col.character as char) {
|
if let Some(c) = special_char(col.character as char) {
|
||||||
col.character = c as u8;
|
col.character = c as u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.app_buffer[i][j] = *col;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.app_buffer = frame;
|
|
||||||
self.internal_render();
|
self.internal_render();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,4 +373,4 @@ pub fn write(args: fmt::Arguments, cols: (Color, Color)) {
|
|||||||
writer.write_fmt(args).unwrap();
|
writer.write_fmt(args).unwrap();
|
||||||
writer.reset_colour();
|
writer.reset_colour();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ use super::render::Window;
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Application {
|
pub trait Application {
|
||||||
fn new() -> Self;
|
fn new(window: Option<Window>) -> Result<Self, Error> where Self: Sized;
|
||||||
|
|
||||||
async fn run(&mut self, _window: Option<Window>, _args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,7 @@ pub enum Error {
|
|||||||
CommandFailed(String),
|
CommandFailed(String),
|
||||||
ApplicationError(String),
|
ApplicationError(String),
|
||||||
EmptyCommand,
|
EmptyCommand,
|
||||||
|
NoWindow,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Exit {
|
pub enum Exit {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ impl Window {
|
|||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
bordered: true,
|
bordered: true,
|
||||||
open: true,
|
open: false,
|
||||||
title: String::new(),
|
title: String::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,6 +54,10 @@ impl Window {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_open(&self) -> bool {
|
||||||
|
self.open
|
||||||
|
}
|
||||||
|
|
||||||
pub fn dimensions(&self) -> Dimensions<usize> {
|
pub fn dimensions(&self) -> Dimensions<usize> {
|
||||||
Dimensions::new(self.width, self.height)
|
Dimensions::new(self.width, self.height)
|
||||||
}
|
}
|
||||||
@@ -86,18 +90,23 @@ impl Window {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.bordered {
|
if self.bordered {
|
||||||
self.outline(&mut frame)?;
|
self.outline(&mut frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
RENDERER.lock().render_frame(frame);
|
RENDERER.lock().render_frame(frame);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clear(&self) {
|
||||||
|
let mut frame = Frame::from_window(self);
|
||||||
|
self.render(&frame).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn move_cursor(&self, x: i32, y: i32) -> Result<(), RenderError> {
|
pub fn move_cursor(&self, x: i32, y: i32) -> Result<(), RenderError> {
|
||||||
RENDERER.lock().cursor_position((x + self.x as i32) as u8, (y + self.y as i32) as u8)
|
RENDERER.lock().cursor_position((x + self.x as i32) as u8, (y + self.y as i32) as u8)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn outline(&self, frame: &mut [[ScreenChar; 80]; 25]) -> Result<(), RenderError> {
|
fn outline(&self, frame: &mut [[ScreenChar; 80]; 25]) {
|
||||||
// draws the sides of the container
|
// draws the sides of the container
|
||||||
// Calculate the dimensions
|
// Calculate the dimensions
|
||||||
let dimensions = self.dimensions();
|
let dimensions = self.dimensions();
|
||||||
@@ -162,13 +171,33 @@ impl Window {
|
|||||||
frame[y as usize][x as usize] = ColouredChar::new(c).as_screen_char();
|
frame[y as usize][x as usize] = ColouredChar::new(c).as_screen_char();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
}
|
||||||
|
|
||||||
|
pub fn close(&mut self) {
|
||||||
|
self.open = false;
|
||||||
|
|
||||||
|
let mut frame = Frame::from_window(self);
|
||||||
|
frame.position.x = (frame.position.x as isize - 1).max(0).min(BUFFER_WIDTH as isize - 1) as usize;
|
||||||
|
frame.position.y = (frame.position.y as isize - 1).max(0).min(BUFFER_HEIGHT as isize - 1) as usize;
|
||||||
|
frame.dimensions.x = (frame.dimensions.x as isize + 2).max(2).min(BUFFER_WIDTH as isize + frame.position.x as isize) as usize;
|
||||||
|
frame.dimensions.y = (frame.dimensions.y as isize + 2).max(2).min(BUFFER_HEIGHT as isize + frame.position.y as isize) as usize;
|
||||||
|
frame.frame = vec![vec![ColouredChar::blank(); frame.dimensions.x]; frame.dimensions.y];
|
||||||
|
let mut newf: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT] = [[ScreenChar::null(); BUFFER_WIDTH]; BUFFER_HEIGHT];
|
||||||
|
|
||||||
|
for (i, row) in frame.frame.iter().enumerate() {
|
||||||
|
for (j, col) in row.iter().enumerate() {
|
||||||
|
newf[i + frame.position.y][j + frame.position.x] = col.as_screen_char();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
RENDERER.lock().render_frame(newf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Window {
|
impl Drop for Window {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
RENDERER.lock().terminal_mode();
|
if self.open {
|
||||||
|
self.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +217,14 @@ impl ColouredChar {
|
|||||||
colour: ColorCode::new(Color::White, Color::Black),
|
colour: ColorCode::new(Color::White, Color::Black),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn null() -> ColouredChar {
|
|
||||||
|
pub fn null () -> ColouredChar {
|
||||||
|
ColouredChar {
|
||||||
|
character: 0u8 as char,
|
||||||
|
colour: ColorCode::new(Color::Black, Color::Black),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn blank() -> ColouredChar {
|
||||||
ColouredChar {
|
ColouredChar {
|
||||||
character: ' ',
|
character: ' ',
|
||||||
colour: ColorCode::new(Color::White, Color::Black),
|
colour: ColorCode::new(Color::White, Color::Black),
|
||||||
@@ -206,6 +242,7 @@ impl ColouredChar {
|
|||||||
colour: self.colour,
|
colour: self.colour,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
@@ -260,7 +297,7 @@ impl Frame {
|
|||||||
Ok(Frame {
|
Ok(Frame {
|
||||||
position,
|
position,
|
||||||
dimensions,
|
dimensions,
|
||||||
frame: vec![vec![ColouredChar::null(); dimensions.x]; dimensions.y],
|
frame: vec![vec![ColouredChar::blank(); dimensions.x]; dimensions.y],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +305,7 @@ impl Frame {
|
|||||||
Frame {
|
Frame {
|
||||||
dimensions: Dimensions::new(window.width as usize, window.height as usize),
|
dimensions: Dimensions::new(window.width as usize, window.height as usize),
|
||||||
position: Position::new(window.x as usize, window.y as usize),
|
position: Position::new(window.x as usize, window.y as usize),
|
||||||
frame: vec![vec![ColouredChar::null(); window.width as usize]; window.height as usize],
|
frame: vec![vec![ColouredChar::blank(); window.width as usize]; window.height as usize],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,6 +404,19 @@ impl Frame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Display for Frame {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
for row in &self.frame {
|
||||||
|
for col in row {
|
||||||
|
if col.character as u8 == 0u8 { write!(f, "~")?; continue; }
|
||||||
|
if col.character == ' ' { write!(f, "@")?; continue; }
|
||||||
|
write!(f, "{}", col.character)?;
|
||||||
|
}
|
||||||
|
writeln!(f)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
impl core::ops::Index<usize> for Frame {
|
impl core::ops::Index<usize> for Frame {
|
||||||
type Output = Vec<ColouredChar>;
|
type Output = Vec<ColouredChar>;
|
||||||
fn index(&self, index: usize) -> &Self::Output {
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::std::render::Window;
|
|||||||
use crate::{println, print, mknode, std};
|
use crate::{println, print, mknode, std};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use crate::std::application;
|
||||||
use crate::std::application::{
|
use crate::std::application::{
|
||||||
Application,
|
Application,
|
||||||
Error as ShellError
|
Error as ShellError
|
||||||
@@ -358,11 +359,11 @@ pub struct Calculator {}
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Application for Calculator {
|
impl Application for Calculator {
|
||||||
fn new() -> Self {
|
fn new(window: Option<Window>) -> Result<Calculator, application::Error> {
|
||||||
Self {}
|
Ok(Calculator {})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&mut self, window: Option<Window>, args: Vec<String>) -> Result<(), ShellError> {
|
async fn run(&mut self, args: Vec<String>) -> Result<(), ShellError> {
|
||||||
if args.len() == 0 {
|
if args.len() == 0 {
|
||||||
loop {
|
loop {
|
||||||
print!("enter equation > ");
|
print!("enter equation > ");
|
||||||
|
|||||||
@@ -143,8 +143,10 @@ impl ToString for Editor {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Application for Editor {
|
impl Application for Editor {
|
||||||
fn new() -> Editor {
|
fn new(window: Option<Window>) -> Result<Editor, application::Error> {
|
||||||
Editor {
|
let window = if let Some(window) = window { window } else { return Err(application::Error::NoWindow) };
|
||||||
|
|
||||||
|
Ok(Editor {
|
||||||
buffer: Vec::new(),
|
buffer: Vec::new(),
|
||||||
cursor_pos: Position::zero(),
|
cursor_pos: Position::zero(),
|
||||||
offset_pos: Position::zero(),
|
offset_pos: Position::zero(),
|
||||||
@@ -152,18 +154,14 @@ impl Application for Editor {
|
|||||||
mode: Mode::Normal,
|
mode: Mode::Normal,
|
||||||
unsaved: false,
|
unsaved: false,
|
||||||
lineno_width: 0,
|
lineno_width: 0,
|
||||||
window: Window::new(),
|
window,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&mut self, window: Option<Window>, args: Vec<String>) -> Result<(), application::Error> {
|
async fn run(&mut self, args: Vec<String>) -> Result<(), application::Error> {
|
||||||
|
|
||||||
if let Some(w) = window {
|
self.window.set_dimensions(60, 15);
|
||||||
self.window = w;
|
self.window.set_position(10, 3);
|
||||||
}
|
|
||||||
|
|
||||||
self.window.set_dimensions(60, 23);
|
|
||||||
self.window.set_position(10, 1);
|
|
||||||
self.window.set_title("Editor");
|
self.window.set_title("Editor");
|
||||||
self.window.open();
|
self.window.open();
|
||||||
|
|
||||||
|
|||||||
@@ -43,13 +43,14 @@ struct PointI64 {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Application for Grapher {
|
impl Application for Grapher {
|
||||||
fn new() -> Self {
|
fn new(window: Option<Window>) -> Result<Self, Error> {
|
||||||
Self {
|
Ok(Self {
|
||||||
points: Vec::new(),
|
points: Vec::new(),
|
||||||
frame: Frame::new(Position::new(1, 1), Dimensions::new(78, 22)).unwrap()
|
frame: Frame::new(Position::new(1, 1), Dimensions::new(78, 22)).unwrap()
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
async fn run(&mut self, window: Option<Window>, args: Vec<String>) -> Result<(), Error> {
|
|
||||||
|
async fn run(&mut self, args: Vec<String>) -> Result<(), Error> {
|
||||||
let _d = Display::borrow();
|
let _d = Display::borrow();
|
||||||
|
|
||||||
self.frame.frame = vec![vec![ColouredChar::new(' '); self.frame.dimensions.x]; self.frame.dimensions.y];
|
self.frame.frame = vec![vec![ColouredChar::new(' '); self.frame.dimensions.x]; self.frame.dimensions.y];
|
||||||
@@ -71,6 +72,7 @@ impl Application for Grapher {
|
|||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
let mut container = CgContainer::new(
|
let mut container = CgContainer::new(
|
||||||
Position::new(0, 0),
|
Position::new(0, 0),
|
||||||
@@ -149,7 +151,7 @@ impl Grapher {
|
|||||||
|
|
||||||
fn graph_equation(&mut self, equation: String, offsets: (i64, i64)) {
|
fn graph_equation(&mut self, equation: String, offsets: (i64, i64)) {
|
||||||
|
|
||||||
let cal = calc::Calculator::new();
|
let cal = calc::Calculator::new(None).unwrap();
|
||||||
let ast = cal.get_expr(equation.chars().map(|c| {
|
let ast = cal.get_expr(equation.chars().map(|c| {
|
||||||
match c {
|
match c {
|
||||||
'e' => format!("({})", E),
|
'e' => format!("({})", E),
|
||||||
|
|||||||
@@ -26,9 +26,11 @@ pub struct Tasks;
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Application for Tasks {
|
impl Application for Tasks {
|
||||||
fn new() -> Self { Self {} }
|
fn new(window: Option<Window>) -> Result<Tasks, Error> {
|
||||||
|
Ok(Tasks)
|
||||||
|
}
|
||||||
|
|
||||||
async fn run(&mut self, window: Option<Window>, args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, args: Vec<String>) -> Result<(), Error> {
|
||||||
|
|
||||||
if args[0].clone() == String::from("add") {
|
if args[0].clone() == String::from("add") {
|
||||||
|
|
||||||
|
|||||||
+158
-41
@@ -1,4 +1,5 @@
|
|||||||
use alloc::{string::String, vec::Vec, boxed::Box};
|
use alloc::{string::String, vec::Vec, boxed::Box, format};
|
||||||
|
use alloc::string::ToString;
|
||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
use crate::std::{application::{Application, Error}, render::Window};
|
use crate::std::{application::{Application, Error}, render::Window};
|
||||||
|
|
||||||
@@ -10,9 +11,10 @@ use crate::apps::grapher::Grapher;
|
|||||||
use crate::apps::tasks::Tasks;
|
use crate::apps::tasks::Tasks;
|
||||||
use crate::games::gameoflife::GameOfLife;
|
use crate::games::gameoflife::GameOfLife;
|
||||||
use crate::games::paper_rs::GameBoard;
|
use crate::games::paper_rs::GameBoard;
|
||||||
use crate::{games, println, utils};
|
use crate::{games, println, serial_println, utils};
|
||||||
use crate::std::io::{Display, Serial};
|
use crate::std::application::Error::ApplicationError;
|
||||||
use crate::std::render::{ColouredChar, Frame, RenderError};
|
use crate::std::io::{Color, ColorCode, Display, KeyStroke, Serial, Stdin};
|
||||||
|
use crate::std::render::{ColouredChar, Frame, Position, RenderError};
|
||||||
use crate::std::time::timer;
|
use crate::std::time::timer;
|
||||||
use crate::user::lib::libgui::cg_core::CgComponent;
|
use crate::user::lib::libgui::cg_core::CgComponent;
|
||||||
use crate::utils::crystalfetch::CrystalFetch;
|
use crate::utils::crystalfetch::CrystalFetch;
|
||||||
@@ -23,24 +25,44 @@ pub struct ZxqSH {
|
|||||||
history: Vec<String>,
|
history: Vec<String>,
|
||||||
history_idx: usize,
|
history_idx: usize,
|
||||||
|
|
||||||
row_pos: usize,
|
|
||||||
col_pos: usize,
|
|
||||||
|
|
||||||
window: Window,
|
window: Window,
|
||||||
buffer: Vec<Vec<ColouredChar>>,
|
|
||||||
buffer_width: usize,
|
// the buffer is a vec of coloured characters
|
||||||
|
// we use a 1d vec so that the terminal can be resized.
|
||||||
|
buffer: Vec<ColouredChar>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Application for ZxqSH {
|
impl Application for ZxqSH {
|
||||||
fn new() -> Self {
|
fn new(window: Option<Window>) -> Result<ZxqSH, Error> {
|
||||||
todo!()
|
match window {
|
||||||
|
Some(window) => {
|
||||||
|
Ok(ZxqSH {
|
||||||
|
history: Vec::new(),
|
||||||
|
history_idx: 0,
|
||||||
|
window,
|
||||||
|
buffer: Vec::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
None => Err(Error::NoWindow),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&mut self, window: Option<Window>, _args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
|
||||||
|
self.window.set_dimensions(78, 23);
|
||||||
|
self.window.set_position(1, 1);
|
||||||
|
self.window.set_title("Terminal");
|
||||||
|
self.window.open();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if let Ok(exit) = self.next().await {
|
match self.next().await {
|
||||||
if exit { return Ok(()) }
|
Err(e) => {
|
||||||
|
self.write(format!("Error: {:?}", e), Color::Yellow);
|
||||||
|
return Err(e);
|
||||||
|
},
|
||||||
|
Ok(exit) => {
|
||||||
|
if exit { return Ok(()) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,20 +74,95 @@ impl ZxqSH {
|
|||||||
// update cycle for the shell
|
// update cycle for the shell
|
||||||
|
|
||||||
// TODO: prompt
|
// TODO: prompt
|
||||||
let command = String::new();
|
let mut command = self.input().await;
|
||||||
|
|
||||||
// TODO: exit if necessary
|
// TODO: exit if necessary
|
||||||
|
|
||||||
// TODO: execute command
|
// TODO: execute command
|
||||||
self.execute(command, Vec::new()).await;
|
if let Err(e) = self.execute(command, Vec::new()).await {
|
||||||
// return
|
match e {
|
||||||
|
Error::UnknownCommand(e) => {
|
||||||
|
self.write("Unknown command\n".to_string(), Color::Yellow);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.write(format!("Error: {:?}\n", e), Color::Yellow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn write_char(&mut self, ch: char) {
|
fn write(&mut self, string: String, color: Color) {
|
||||||
self.buffer[self.row_pos][self.col_pos] = ColouredChar::new(ch);
|
for ch in string.chars() {
|
||||||
|
self.write_char(ch, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_char(&mut self, ch: char, color: Color) {
|
||||||
|
self.buffer.push(ColouredChar::coloured(ch, ColorCode::new(color, Color::Black)));
|
||||||
|
while self.buffer.len() > 100000 {
|
||||||
|
self.buffer.remove(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(frame) = self.render() {
|
||||||
|
self.window.render(&frame).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn backspace(&mut self) {
|
||||||
|
let _ = self.buffer.pop();
|
||||||
|
if let Ok(frame) = self.render() {
|
||||||
|
self.window.render(&frame).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn input(&mut self) -> String {
|
||||||
|
let mut string = String::new();
|
||||||
|
self.write("ZxqS> ".to_string(), Color::Cyan);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let ch = Stdin::keystroke().await;
|
||||||
|
match ch {
|
||||||
|
KeyStroke::Char(c) => {
|
||||||
|
match c {
|
||||||
|
'\x08' => {
|
||||||
|
if string.len() == 0 { continue; }
|
||||||
|
string.pop();
|
||||||
|
self.backspace()
|
||||||
|
},
|
||||||
|
'\n' => {
|
||||||
|
self.write_char(c, Color::White);
|
||||||
|
break
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
self.write_char(c, Color::White);
|
||||||
|
string.push(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_col(&self) -> usize {
|
||||||
|
let term_width = self.window.dimensions().x as isize;
|
||||||
|
let mut col = self.buffer.iter().rev().take_while(|c| c.character != '\n').count() as isize;
|
||||||
|
|
||||||
|
while col - term_width >= 0 {
|
||||||
|
col -= term_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
col as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lines(&self) -> Vec<Vec<ColouredChar>> {
|
||||||
|
self.buffer
|
||||||
|
.split(|c| c.character == '\n')
|
||||||
|
.map(|line| line.to_vec())
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn execute(&self, cmd: String, args: Vec<String>) -> Result<(), Error> {
|
async fn execute(&self, cmd: String, args: Vec<String>) -> Result<(), Error> {
|
||||||
@@ -73,11 +170,11 @@ impl ZxqSH {
|
|||||||
let window = Window::new();
|
let window = Window::new();
|
||||||
|
|
||||||
match cmd.as_str() {
|
match cmd.as_str() {
|
||||||
"calculate" | "calc" | "solve" => Calculator::new().run(Some(window), args).await?,
|
"calculate" | "calc" | "solve" => Calculator::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
"games/connect4" => crate::user::bin::games::connect4::Game::new().run(Some(window), args).await?,
|
"games/connect4" => crate::user::bin::games::connect4::Game::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
"rickroll" => Rickroll::new().run(Some(window), args).await?,
|
"rickroll" => Rickroll::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
"crystalfetch" => CrystalFetch::new().run(Some(window), args).await?,
|
"crystalfetch" => CrystalFetch::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
"tasks" => Tasks::new().run(Some(window), args).await?,
|
"tasks" => Tasks::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
"VGA" => {
|
"VGA" => {
|
||||||
use vga::colors::Color16;
|
use vga::colors::Color16;
|
||||||
use vga::writers::{GraphicsWriter, Graphics640x480x16};
|
use vga::writers::{GraphicsWriter, Graphics640x480x16};
|
||||||
@@ -86,19 +183,18 @@ impl ZxqSH {
|
|||||||
mode.clear_screen(Color16::Black);
|
mode.clear_screen(Color16::Black);
|
||||||
mode.draw_line((80, 60), (120, 420), Color16::Cyan);
|
mode.draw_line((80, 60), (120, 420), Color16::Cyan);
|
||||||
},
|
},
|
||||||
"graph" => Grapher::new().run(Some(window), args).await?,
|
"graph" => Grapher::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
"games/snake" => games::snake::Game::new().run(Some(window), args).await?,
|
"games/snake" => games::snake::Game::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
"games/asteroids" => games::asteroids::Game::new().run(Some(window), args).await?,
|
"games/asteroids" => games::asteroids::Game::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
"games/pong" => games::pong::Game::new().run(Some(window), args).await?,
|
"games/pong" => games::pong::Game::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
"games/paper.rs" => games::paper_rs::GameBoard::new().run(Some(window), args).await?,
|
"games/paper.rs" => games::paper_rs::GameBoard::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
"serial" => println!("{}", Serial::reply_char('e')),
|
"serial" => println!("{}", Serial::reply_char('e')),
|
||||||
"games/gameoflife" => GameOfLife::new().run(Some(window), Vec::new()).await?,
|
"games/gameoflife" => GameOfLife::new(Some(window)).expect("couldn't open window").run(Vec::new()).await?,
|
||||||
"games/tetris" => {
|
"games/tetris" => {
|
||||||
// games::tetris::TetrisEngine::new().run(Vec::new()).await?;
|
// games::tetris::TetrisEngine::new().expect("couldn't open window").run(Vec::new()).await?;
|
||||||
}
|
}
|
||||||
"gigachad?" => utils::gigachad_detector::GigachadDetector::new().run(Some(window), args).await?,
|
"gigachad?" => utils::gigachad_detector::GigachadDetector::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
"editor" => Editor::new().run(Some(window), args).await?,
|
"editor" => Editor::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
|
|
||||||
// direct OS functions (not applications)
|
// direct OS functions (not applications)
|
||||||
"echo" => {
|
"echo" => {
|
||||||
println!(
|
println!(
|
||||||
@@ -116,6 +212,10 @@ impl ZxqSH {
|
|||||||
_ => return Err(Error::UnknownCommand(cmd))
|
_ => return Err(Error::UnknownCommand(cmd))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let Ok(frame) = self.render() {
|
||||||
|
self.window.render(&frame).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,17 +226,34 @@ impl CgComponent for ZxqSH {
|
|||||||
|
|
||||||
let term_height = self.window.dimensions().y;
|
let term_height = self.window.dimensions().y;
|
||||||
let term_width = self.window.dimensions().x;
|
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)?;
|
self.window.move_cursor(self.get_col() as i32, term_height as i32 - 1)?;
|
||||||
|
|
||||||
// render the contents of the terminal to a frame
|
// 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) {
|
let mut line = term_height - 1;
|
||||||
frame[i][j] = *col;
|
let mut col = self.get_col();
|
||||||
|
let buff = self.lines();
|
||||||
|
let mut lines = buff.iter();
|
||||||
|
|
||||||
|
for line_chars in lines.rev() {
|
||||||
|
col = line_chars.len() % term_width;
|
||||||
|
|
||||||
|
for c in line_chars.iter().rev() {
|
||||||
|
if c.character == '\n' { continue; }
|
||||||
|
frame.write(Position::new(col, line), c.clone())?;
|
||||||
|
|
||||||
|
if col <= 0 {
|
||||||
|
line -= 1;
|
||||||
|
col = term_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
col -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
line -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(frame)
|
Ok(frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ pub struct Game {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Application for Game {
|
impl Application for Game {
|
||||||
fn new() -> Self {
|
fn new(window: Option<Window>) -> Result<Self, Error> {
|
||||||
Self {
|
Ok(Self {
|
||||||
player: Player::new(),
|
player: Player::new(),
|
||||||
enemies: Vec::new(),
|
enemies: Vec::new(),
|
||||||
score: 0,
|
score: 0,
|
||||||
@@ -50,9 +50,9 @@ impl Application for Game {
|
|||||||
difficulty_idx: 1,
|
difficulty_idx: 1,
|
||||||
gamespeed: 1.0,
|
gamespeed: 1.0,
|
||||||
timer: GameTimer::new(),
|
timer: GameTimer::new(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
async fn run(&mut self, window: Option<Window>, _args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
|
||||||
let _d = Display::borrow();
|
let _d = Display::borrow();
|
||||||
|
|
||||||
let mut container_data =
|
let mut container_data =
|
||||||
|
|||||||
@@ -21,19 +21,18 @@ pub enum Cell {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Application for Game {
|
impl Application for Game {
|
||||||
fn new() -> Self {
|
fn new(window: Option<Window>) -> Result<Self, Error> {
|
||||||
Game {
|
Ok(Game {
|
||||||
board: [[Cell::Empty; 7]; 6],
|
board: [[Cell::Empty; 7]; 6],
|
||||||
turn: 1,
|
turn: 1,
|
||||||
vs_ai: false,
|
vs_ai: false,
|
||||||
game_over: false,
|
game_over: false,
|
||||||
winner: None,
|
winner: None,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&mut self, window: Option<Window>, _: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _: Vec<String>) -> Result<(), Error> {
|
||||||
let _display = Display::borrow();
|
let _display = Display::borrow();
|
||||||
|
|
||||||
self.get_next_mode().await;
|
self.get_next_mode().await;
|
||||||
|
|
||||||
// Main game loop
|
// Main game loop
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use alloc::vec;
|
use alloc::{format, vec};
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use crate::std::application::{Application, Error};
|
use crate::std::application::{Application, Error};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use futures_util::future::err;
|
||||||
use crate::std::render::{ColouredChar, Dimensions, Frame, Position, RenderError, Window};
|
use crate::std::render::{ColouredChar, Dimensions, Frame, Position, RenderError, Window};
|
||||||
use crate::std::io::{KeyStroke, Stdin, Color, ColorCode, Display};
|
use crate::std::io::{KeyStroke, Stdin, Color, ColorCode, Display};
|
||||||
use crate::std::time::wait;
|
use crate::std::time::wait;
|
||||||
@@ -16,12 +17,18 @@ const LOOP_SPEED: f64 = 0.1;
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Application for GameOfLife {
|
impl Application for GameOfLife {
|
||||||
fn new() -> Self {
|
fn new(window: Option<Window>) -> Result<Self, Error> {
|
||||||
Self {
|
let mut frame: Frame;
|
||||||
frame: Frame::new(Position::new(0, 0), Dimensions::new(80, 25)).unwrap()
|
if let Some(window) = window {
|
||||||
|
frame = Frame::new(Position::new(0, 0), Dimensions::new(80, 25)).unwrap();
|
||||||
|
frame.dimensions = window.dimensions();
|
||||||
|
frame.position = window.position();
|
||||||
|
Ok(Self { frame })
|
||||||
|
} else {
|
||||||
|
return Err(Error::NoWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async fn run(&mut self, window: Option<Window>, _args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
|
||||||
// setup:
|
// setup:
|
||||||
let _d = Display::borrow();
|
let _d = Display::borrow();
|
||||||
|
|
||||||
@@ -100,12 +107,12 @@ impl GameOfLife {
|
|||||||
if self.frame[y as usize][x as usize] == ColouredChar::coloured('#', ColorCode::new(Color::Green, Color::Black)) {
|
if self.frame[y as usize][x as usize] == ColouredChar::coloured('#', ColorCode::new(Color::Green, Color::Black)) {
|
||||||
return ColouredChar::coloured('#', ColorCode::new(Color::Green, Color::Black));
|
return ColouredChar::coloured('#', ColorCode::new(Color::Green, Color::Black));
|
||||||
} else {
|
} else {
|
||||||
return ColouredChar::null();
|
return ColouredChar::blank();
|
||||||
}
|
}
|
||||||
} else if alive == 3 {
|
} else if alive == 3 {
|
||||||
ColouredChar::coloured('#', ColorCode::new(Color::Green, Color::Black))
|
ColouredChar::coloured('#', ColorCode::new(Color::Green, Color::Black))
|
||||||
} else {
|
} else {
|
||||||
ColouredChar::null()
|
ColouredChar::blank()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ pub struct GameBoard {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Application for GameBoard {
|
impl Application for GameBoard {
|
||||||
fn new() -> GameBoard {
|
fn new(window: Option<Window>) -> Result<Self, Error> {
|
||||||
GameBoard {
|
Ok(GameBoard {
|
||||||
board: [[Cell::Empty; 80]; 25],
|
board: [[Cell::Empty; 80]; 25],
|
||||||
players: [
|
players: [
|
||||||
Player::new(0, (10, 10), false),
|
Player::new(0, (10, 10), false),
|
||||||
@@ -46,10 +46,10 @@ impl Application for GameBoard {
|
|||||||
],
|
],
|
||||||
max_territory: 0,
|
max_territory: 0,
|
||||||
current_territory: 0,
|
current_territory: 0,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&mut self, window: Option<Window>, _args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
|
||||||
let _display = Display::borrow();
|
let _display = Display::borrow();
|
||||||
|
|
||||||
'outer: loop {
|
'outer: loop {
|
||||||
|
|||||||
@@ -17,15 +17,15 @@ pub(crate) struct Game {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Application for Game {
|
impl Application for Game {
|
||||||
fn new() -> Self {
|
fn new(window: Option<Window>) -> Result<Self, Error> {
|
||||||
Game {
|
Ok(Game {
|
||||||
ball: Ball::new(),
|
ball: Ball::new(),
|
||||||
player1: Player::new(1),
|
player1: Player::new(1),
|
||||||
player2: Player::new(78),
|
player2: Player::new(78),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&mut self, window: Option<Window>, _: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _: Vec<String>) -> Result<(), Error> {
|
||||||
let _d = Display::borrow();
|
let _d = Display::borrow();
|
||||||
|
|
||||||
let mut update_time = Timer::new(0.1);
|
let mut update_time = Timer::new(0.1);
|
||||||
|
|||||||
+23
-13
@@ -1,4 +1,4 @@
|
|||||||
use alloc::string::String;
|
use alloc::string::{String, ToString};
|
||||||
use alloc::{format, vec, vec::Vec, boxed::Box};
|
use alloc::{format, vec, vec::Vec, boxed::Box};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use crate::std::io::{Color, Display, KeyStroke, Stdin};
|
use crate::std::io::{Color, Display, KeyStroke, Stdin};
|
||||||
@@ -30,22 +30,34 @@ pub struct Game {
|
|||||||
pois: Vec<Position>,
|
pois: Vec<Position>,
|
||||||
score: u8,
|
score: u8,
|
||||||
gamemode: Gamemode,
|
gamemode: Gamemode,
|
||||||
|
window: Window,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Application for Game {
|
impl Application for Game {
|
||||||
fn new() -> Self {
|
fn new(window: Option<Window>) -> Result<Self, Error> {
|
||||||
Self {
|
let window = match window {
|
||||||
|
Some(w) => w,
|
||||||
|
None => return Err(Error::NoWindow),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
snakes: Vec::new(),
|
snakes: Vec::new(),
|
||||||
pois: Vec::new(),
|
pois: Vec::new(),
|
||||||
score: 0,
|
score: 0,
|
||||||
gamemode: Gamemode::Uninitialised,
|
gamemode: Gamemode::Uninitialised,
|
||||||
}
|
window,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&mut self, window: Option<Window>, args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, args: Vec<String>) -> Result<(), Error> {
|
||||||
|
self.window.set_title("snake game");
|
||||||
|
self.window.set_dimensions(78, 23);
|
||||||
|
self.window.set_position(1, 1);
|
||||||
|
self.window.open();
|
||||||
|
|
||||||
|
|
||||||
let _settings = [0, 0, 0]; // ai_count, snake_len, poi_count
|
let _settings = [0, 0, 0]; // ai_count, snake_len, poi_count
|
||||||
|
|
||||||
@@ -75,7 +87,6 @@ impl Application for Game {
|
|||||||
self.prepare();
|
self.prepare();
|
||||||
|
|
||||||
// switch OS to application mode
|
// switch OS to application mode
|
||||||
let _d = Display::borrow();
|
|
||||||
// render the initial state of the screen.
|
// render the initial state of the screen.
|
||||||
self.render().map_err(|_| Error::ApplicationError(String::from("failed to render game screen")))?;
|
self.render().map_err(|_| Error::ApplicationError(String::from("failed to render game screen")))?;
|
||||||
// run the game
|
// run the game
|
||||||
@@ -154,7 +165,7 @@ impl Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn new_poi(&mut self) {
|
fn new_poi(&mut self) {
|
||||||
self.pois.push(Position { x: Random::int(3, 76) as i64, y: Random::int(3, 21) as i64 });
|
self.pois.push(Position { x: Random::int(3, self.window.dimensions().x - 4) as i64, y: Random::int(3, self.window.dimensions().y - 4) as i64 });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replace_poi(&mut self, poi: &Position) {
|
fn replace_poi(&mut self, poi: &Position) {
|
||||||
@@ -164,7 +175,7 @@ impl Game {
|
|||||||
|
|
||||||
fn render(&mut self) -> Result<(), RenderError> {
|
fn render(&mut self) -> Result<(), RenderError> {
|
||||||
|
|
||||||
let mut frame = Frame::new(render::Position::new(0, 0), Dimensions::new(80, 25))?;
|
let mut frame = Frame::new(render::Position::new(0, 0), self.window.dimensions())?;
|
||||||
let mut curr_colour = ColorCode::new(Color::LightBlue, Color::Black);
|
let mut curr_colour = ColorCode::new(Color::LightBlue, Color::Black);
|
||||||
|
|
||||||
for s in self.snakes.clone() {
|
for s in self.snakes.clone() {
|
||||||
@@ -182,15 +193,14 @@ impl Game {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let literal = format!("snake go brr score: {}", self.score);
|
let literal = format!("snake go brr score: {}", self.score);
|
||||||
let msg = Game::centre_text(80, literal);
|
let msg = Game::centre_text(self.window.dimensions().x, literal);
|
||||||
msg.chars().enumerate().for_each(|(i, c)| {
|
msg.chars().enumerate().for_each(|(i, c)| {
|
||||||
if c != ' ' {
|
if c != ' ' {
|
||||||
frame[1][i] = ColouredChar::coloured(c, ColorCode::new(Color::LightGreen, Color::Black))
|
frame[1][i] = ColouredChar::coloured(c, ColorCode::new(Color::LightGreen, Color::Black))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
frame.write_to_screen()?;
|
self.window.render(&frame)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,7 +221,7 @@ impl Game {
|
|||||||
frame[12] = Game::centre_text(80, String::from(format!("ur score was {}", self.score))).chars().map(|c| ColouredChar::coloured(c, ColorCode::new(Color::LightGreen, Color::Black))).collect();
|
frame[12] = Game::centre_text(80, String::from(format!("ur score was {}", self.score))).chars().map(|c| ColouredChar::coloured(c, ColorCode::new(Color::LightGreen, Color::Black))).collect();
|
||||||
frame[14] = Game::centre_text(80, String::from("L bozo")).chars().map(|c| ColouredChar::coloured(c, ColorCode::new(Color::Red, Color::Black))).collect();
|
frame[14] = Game::centre_text(80, String::from("L bozo")).chars().map(|c| ColouredChar::coloured(c, ColorCode::new(Color::Red, Color::Black))).collect();
|
||||||
|
|
||||||
frame.write_to_screen()?;
|
self.window.render(&frame)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,4 +2,3 @@ pub mod apps;
|
|||||||
pub mod games;
|
pub mod games;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
pub mod shell;
|
pub mod shell;
|
||||||
pub mod shellrewrite;
|
|
||||||
+36
-28
@@ -48,6 +48,7 @@ use crate::{
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use crate::apps::zxqsh::ZxqSH;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref CMD: Mutex<CommandHandler> = Mutex::new(CommandHandler::new());
|
pub static ref CMD: Mutex<CommandHandler> = Mutex::new(CommandHandler::new());
|
||||||
@@ -66,11 +67,11 @@ pub async fn eventloop() {
|
|||||||
|
|
||||||
let window = Window::new();
|
let window = Window::new();
|
||||||
|
|
||||||
let mut fetch = CrystalFetch::new();
|
let mut fetch = CrystalFetch::new(Some(window)).unwrap();
|
||||||
let string = String::from(" ");
|
let string = String::from(" ");
|
||||||
let mut vec: Vec<String> = Vec::new();
|
let mut vec: Vec<String> = Vec::new();
|
||||||
vec.push(string);
|
vec.push(string);
|
||||||
fetch.run(Some(window), vec).await.unwrap();
|
fetch.run(vec).await.unwrap();
|
||||||
|
|
||||||
CMD.lock().prompt();
|
CMD.lock().prompt();
|
||||||
|
|
||||||
@@ -103,6 +104,9 @@ fn handle_error(e: Error) {
|
|||||||
Error::CommandFailed(e) => {
|
Error::CommandFailed(e) => {
|
||||||
printerr!("command failed:\n{}", e);
|
printerr!("command failed:\n{}", e);
|
||||||
},
|
},
|
||||||
|
Error::NoWindow => {
|
||||||
|
printerr!("no window");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,27 +129,27 @@ async fn exec() -> Result<(), Error> {
|
|||||||
|
|
||||||
match cmd.as_str() {
|
match cmd.as_str() {
|
||||||
"calculate" | "calc" | "solve" => {
|
"calculate" | "calc" | "solve" => {
|
||||||
let mut cmd = Calculator::new();
|
let mut cmd = Calculator::new(Some(window)).expect("couldn't open window");
|
||||||
cmd.run(Some(window), args).await?;
|
cmd.run(args).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"games/connect4" => {
|
"games/connect4" => {
|
||||||
let mut cmd = Connect4Game::new();
|
let mut cmd = Connect4Game::new(Some(window)).expect("couldn't open window");
|
||||||
cmd.run(Some(window), args).await?;
|
cmd.run(args).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"rickroll" => {
|
"rickroll" => {
|
||||||
let mut cmd = Rickroll::new();
|
let mut cmd = Rickroll::new(Some(window)).expect("couldn't open window");
|
||||||
cmd.run(Some(window), args).await?;
|
cmd.run(args).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"crystalfetch" => {
|
"crystalfetch" => {
|
||||||
let mut cmd = CrystalFetch::new();
|
let mut cmd = CrystalFetch::new(Some(window)).expect("couldn't open window");
|
||||||
cmd.run(Some(window), args).await?;
|
cmd.run(args).await?;
|
||||||
}
|
}
|
||||||
"tasks" => {
|
"tasks" => {
|
||||||
let mut cmd = Tasks::new();
|
let mut cmd = Tasks::new(Some(window)).expect("couldn't open window");
|
||||||
cmd.run(Some(window), args).await?;
|
cmd.run(args).await?;
|
||||||
}
|
}
|
||||||
"VGA" => {
|
"VGA" => {
|
||||||
use vga::colors::Color16;
|
use vga::colors::Color16;
|
||||||
@@ -157,45 +161,49 @@ async fn exec() -> Result<(), Error> {
|
|||||||
mode.draw_line((80, 60), (120, 420), Color16::Cyan);
|
mode.draw_line((80, 60), (120, 420), Color16::Cyan);
|
||||||
}
|
}
|
||||||
"graph" => {
|
"graph" => {
|
||||||
Grapher::new().run(Some(window), args).await?;
|
Grapher::new(Some(window)).expect("couldn't open window").run(args).await?;
|
||||||
}
|
}
|
||||||
"games/snake" => {
|
"games/snake" => {
|
||||||
SnakeGame::new().run(Some(window), args).await?;
|
SnakeGame::new(Some(window)).expect("couldn't open window").run(args).await?;
|
||||||
}
|
}
|
||||||
"games/asteroids" => {
|
"games/asteroids" => {
|
||||||
let mut asteroid_game = AsteroidsGame::new();
|
let mut cmd = AsteroidsGame::new(Some(window)).expect("couldn't open window");
|
||||||
asteroid_game.run(Some(window), args).await?;
|
cmd.run(args).await?;
|
||||||
}
|
}
|
||||||
"games/pong" => {
|
"games/pong" => {
|
||||||
PongGame::new().run(Some(window), args).await?;
|
let mut cmd = PongGame::new(Some(window)).expect("couldn't open window");
|
||||||
|
cmd.run(args).await?;
|
||||||
}
|
}
|
||||||
"games/paper.rs" => {
|
"games/paper.rs" => {
|
||||||
let mut game = GameBoard::new();
|
let mut cmd = GameBoard::new(Some(window)).expect("couldn't open window");
|
||||||
game.run(Some(window), args).await?;
|
cmd.run(args).await?;
|
||||||
}
|
}
|
||||||
"serial" => {
|
"serial" => {
|
||||||
let c = Serial::reply_char('e');
|
let c = Serial::reply_char('e');
|
||||||
println!("{}", c);
|
println!("{}", c);
|
||||||
}
|
}
|
||||||
"games/gameoflife" => {
|
"games/gameoflife" => {
|
||||||
let mut game = GameOfLife::new();
|
let mut cmd = GameOfLife::new(Some(window)).expect("couldn't open window");
|
||||||
game.run(Some(window), Vec::new()).await?;
|
cmd.run(Vec::new()).await?;
|
||||||
}
|
}
|
||||||
"games/tetris" => {
|
"games/tetris" => {
|
||||||
// let mut game = TetrisEngine::new();
|
// let mut cmd = TetrisEngine::new(Some(window)).expect("couldn't open window");
|
||||||
// game.run(Vec::new()).await?;
|
// cmd.run(Vec::new()).await?;
|
||||||
|
},
|
||||||
|
"shell" => {
|
||||||
|
let mut cmd = ZxqSH::new(Some(window)).expect("couldn't open window");
|
||||||
|
cmd.run(args).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"gigachad?" => {
|
"gigachad?" => {
|
||||||
let mut detector = GigachadDetector::new();
|
let mut cmd = GigachadDetector::new(Some(window)).expect("couldn't open window");
|
||||||
detector.run(Some(window), args).await?;
|
cmd.run(args).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"editor" => {
|
"editor" => {
|
||||||
let mut editor = Editor::new();
|
let mut cmd = Editor::new(Some(window)).expect("couldn't open window");
|
||||||
editor.run(Some(window), args).await?;
|
cmd.run(args).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// direct OS functions (not applications)
|
// direct OS functions (not applications)
|
||||||
"echo" => {
|
"echo" => {
|
||||||
println!(
|
println!(
|
||||||
|
|||||||
@@ -1,158 +0,0 @@
|
|||||||
// // importing libraries
|
|
||||||
// use async_trait::async_trait;
|
|
||||||
// use lazy_static::lazy_static;
|
|
||||||
// use spin::Mutex;
|
|
||||||
// use x86_64::instructions::interrupts;
|
|
||||||
|
|
||||||
// use alloc::{boxed::Box, string::{String, ToString}, vec, vec::Vec};
|
|
||||||
|
|
||||||
// use crate::{
|
|
||||||
// kernel::tasks::{executor::Executor, Task},
|
|
||||||
// std::application::{Application, Error},
|
|
||||||
// std::io::{print, println, Stdin, Screen},
|
|
||||||
// user::bin::*,
|
|
||||||
// };
|
|
||||||
// use crate::std::io::{Color, write};
|
|
||||||
// use crate::user::bin::gigachad_detector::GigachadDetector;
|
|
||||||
|
|
||||||
// use super::*;
|
|
||||||
|
|
||||||
// // [ CRYSTAL SHELL ]
|
|
||||||
// // the purpose of this module is to provide a basic unix shell like experience for the user
|
|
||||||
// // to interact with the OS
|
|
||||||
// // this is a rewrite of my original shell.
|
|
||||||
// // this shell should support:
|
|
||||||
// // - browsing the virtual filesystem
|
|
||||||
// // - executing programs
|
|
||||||
// // - basic arithmetic
|
|
||||||
// // - chained execution ( multiple commands linked together) eg: '5 + 5 | echo' which calculates
|
|
||||||
// // the result of 5 + 5 and then sends the result to an echo command which prints it to console
|
|
||||||
|
|
||||||
|
|
||||||
// /// starts the shell
|
|
||||||
// /// this function should be directly called by main.rs or by an init system
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fn run_task(task_name: String, args: Vec<String>) -> Result<(), String> {
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub async fn userspace() -> Result<(), String> {
|
|
||||||
// let mut executor = Executor::new();
|
|
||||||
|
|
||||||
// let mut shell = Shell::new();
|
|
||||||
// shell.run(vec![]).await.unwrap();
|
|
||||||
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
|
|
||||||
// struct Shell {
|
|
||||||
// history: Vec<String>,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[async_trait]
|
|
||||||
// impl Application for Shell {
|
|
||||||
// fn new() -> Shell {
|
|
||||||
// Shell {
|
|
||||||
// history: Vec::new(),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// async fn run(&mut self, _: Vec<String>) -> Result<(), Error> {
|
|
||||||
// loop {
|
|
||||||
// self.prompt();
|
|
||||||
// let input = Stdin::readline().await;
|
|
||||||
// let (cmd, args) = self.parse_args(input).unwrap();
|
|
||||||
// self.run_cmd(cmd, args).await.unwrap();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl Shell {
|
|
||||||
// fn prompt(&mut self) {
|
|
||||||
// write(format_args!("\n Crystal> "), (Color::Cyan, Color::Black));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // fn exec<R, T: Fn() -> R>(command: T) -> Result<R, Error> { // this command runs when a shell command is executed
|
|
||||||
// // Ok(command())
|
|
||||||
// // }
|
|
||||||
// async fn run_cmd(&mut self, cmd: String, args: Vec<String>) -> Result<(), Error> {
|
|
||||||
// match cmd.as_str() {
|
|
||||||
// "calculate" | "calc" | "solve" => {
|
|
||||||
// let mut cmd = calc::Calculator::new();
|
|
||||||
// cmd.run(args).await?;
|
|
||||||
// }
|
|
||||||
// "rickroll" => {
|
|
||||||
// let mut cmd = rickroll::Rickroll::new();
|
|
||||||
// cmd.run(args).await?;
|
|
||||||
// }
|
|
||||||
// "crystalfetch" => {
|
|
||||||
// let mut cmd = crystalfetch::CrystalFetch::new();
|
|
||||||
// cmd.run(args).await?;
|
|
||||||
// }
|
|
||||||
// "tasks" => {
|
|
||||||
// let mut cmd = tasks::Tasks::new();
|
|
||||||
// cmd.run(args).await?;
|
|
||||||
// }
|
|
||||||
// "play" => {
|
|
||||||
// let mut gameloop = crystal_rpg::init::GameLoop::new();
|
|
||||||
// gameloop.run(args).await?;
|
|
||||||
// }
|
|
||||||
// "echo" => {
|
|
||||||
// println!(
|
|
||||||
// "Crystal: '{}'",
|
|
||||||
// " ".join(args)
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// "clear" => {
|
|
||||||
// Screen::clear();
|
|
||||||
// }
|
|
||||||
// "print" => {
|
|
||||||
// use crate::std::os::OS;
|
|
||||||
// let x: String = OS.lock().version.clone();
|
|
||||||
// println!("{}", x);
|
|
||||||
// }
|
|
||||||
// "snake" => {
|
|
||||||
// let mut game = snake::Game::new();
|
|
||||||
// game.run(Vec::new()).await?;
|
|
||||||
// }
|
|
||||||
// "gigachad?" => {
|
|
||||||
// let mut gigachad_detector = GigachadDetector::new();
|
|
||||||
// gigachad_detector.run(args).await?;
|
|
||||||
// }
|
|
||||||
// "test_features" => {
|
|
||||||
// use crate::std::random::Random;
|
|
||||||
// println!("{}", Random::int(0, 10));
|
|
||||||
// }
|
|
||||||
// _ => {
|
|
||||||
// return Err(Error::UnknownCommand(
|
|
||||||
// "command not yet implemented".to_string(),
|
|
||||||
// ))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
// fn parse_args(&self, command: String) -> Result<(String, Vec<String>), String> {
|
|
||||||
// let mut args: Vec<String> = Vec::new();
|
|
||||||
|
|
||||||
// for arg in command.split(" ").collect::<Vec<&str>>() {
|
|
||||||
// match arg {
|
|
||||||
// "" => {}
|
|
||||||
// x => args.push(x.to_string()),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let cmd: String;
|
|
||||||
// if args.len() > 0 {
|
|
||||||
// cmd = args[0].clone();
|
|
||||||
// args.remove(0);
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// return Err("command was empty.".to_string());
|
|
||||||
// };
|
|
||||||
|
|
||||||
// Ok((cmd, args))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
@@ -49,11 +49,11 @@ pub struct CrystalFetch {}
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Application for CrystalFetch {
|
impl Application for CrystalFetch {
|
||||||
fn new() -> Self {
|
fn new(window: Option<Window>) -> Result<Self, Error> {
|
||||||
Self {}
|
Ok(Self {})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&mut self, window: Option<Window>, _args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
|
||||||
|
|
||||||
// let ds = Display::borrow();
|
// let ds = Display::borrow();
|
||||||
|
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ pub struct GigachadDetector {}
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Application for GigachadDetector {
|
impl Application for GigachadDetector {
|
||||||
fn new() -> Self {
|
fn new(window: Option<Window>) -> Result<Self, Error> {
|
||||||
Self {}
|
Ok(Self {})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&mut self, window: Option<Window>, args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, args: Vec<String>) -> Result<(), Error> {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
self.detect_gigachad_by_username(&arg)
|
self.detect_gigachad_by_username(&arg)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,11 +52,11 @@ pub struct Rickroll {}
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Application for Rickroll {
|
impl Application for Rickroll {
|
||||||
fn new() -> Self {
|
fn new(window: Option<Window>) -> Result<Self, Error> {
|
||||||
Self {}
|
Ok(Self {})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&mut self, window: Option<Window>, _args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
|
||||||
println!("{}", RICKROLL2);
|
println!("{}", RICKROLL2);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user