Compare commits
12 Commits
65b0367487
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 1b278475cb | |||
| 1e7d513f26 | |||
| 1ace354158 | |||
| 41a6b6740b | |||
| c3c4633cf1 | |||
| ee0963fafd | |||
| a8b8d61112 | |||
| 2e66cf646c | |||
| e036e550ce | |||
| ebab50f2c1 | |||
| 12cf115288 | |||
| 77528c76b3 |
@@ -1,24 +0,0 @@
|
|||||||
name: Rust
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "main" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "main" ]
|
|
||||||
|
|
||||||
env:
|
|
||||||
CARGO_TERM_COLOR: always
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Build Docker Image
|
|
||||||
run: docker build -t crystal-os .
|
|
||||||
|
|
||||||
- name: Run Build in Docker Container
|
|
||||||
run: docker run --rm crystal-os
|
|
||||||
Generated
-1
@@ -2,6 +2,5 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="" vcs="Git" />
|
<mapping directory="" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/CrystalPy" vcs="Git" />
|
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# CrystalOS
|
# ZXQ5.OS
|
||||||
|
|
||||||
the initial aim of this project was to follow a blog series on how to write an operating system in Rust (see links below)
|
the initial aim of this project was to follow a blog series on how to write an operating system in Rust (see links below)
|
||||||
|
|
||||||
@@ -12,6 +12,25 @@ while I'm waiting for the third edition to release, I guess I'm gonna just have
|
|||||||
|
|
||||||
- for more details on this project read the wiki ^^^
|
- for more details on this project read the wiki ^^^
|
||||||
|
|
||||||
|
# Building
|
||||||
|
- this project unfortunately does not build on the latest rust versions and requires an older nightly build.
|
||||||
|
the version below (rust v1.68.0-nightly) works:
|
||||||
|
> rustup override set nightly-2023-01-01
|
||||||
|
(you may need to install this first)
|
||||||
|
> rustup install nightly-2023-01-01
|
||||||
|
- you will need the bare metal x86 target installed:
|
||||||
|
> rustup target add x86_64-unknown-none
|
||||||
|
- you will also need several extra rustup components to build the project
|
||||||
|
> rustup component add llvm-tools-preview
|
||||||
|
> rustup component add rust-src
|
||||||
|
(ensure that you are installing the components for the correct nightly build)
|
||||||
|
- you will also need the bootimage crate which can be installed with the below command:
|
||||||
|
> cargo install bootimage
|
||||||
|
- the final requirement is having QEMU desktop installed for your system. on linux this comes in the default repositories of most major distributions.
|
||||||
|
- finally:
|
||||||
|
> cargo run
|
||||||
|
|
||||||
|
|
||||||
# Features as of Nov 2023
|
# Features as of Nov 2023
|
||||||
|
|
||||||
### barebones standard library with the following general features
|
### barebones standard library with the following general features
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
never gonna give you up
|
||||||
|
|
||||||
|
|
||||||
|
// "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
@@ -1 +0,0 @@
|
|||||||
never gonna give you up
|
|
||||||
+15
-2
@@ -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, 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;
|
||||||
|
|
||||||
@@ -16,6 +21,7 @@ use CrystalOS::user::bin::shell;
|
|||||||
fn panic(_info: &PanicInfo) -> ! {
|
fn panic(_info: &PanicInfo) -> ! {
|
||||||
syscall::terminal_mode_force();
|
syscall::terminal_mode_force();
|
||||||
printerr!("{}", _info);
|
printerr!("{}", _info);
|
||||||
|
serial_println!("{}", _info);
|
||||||
CrystalOS::hlt();
|
CrystalOS::hlt();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,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();
|
||||||
|
}
|
||||||
+21
-10
@@ -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)]
|
||||||
@@ -52,6 +54,7 @@ pub enum RenderError {
|
|||||||
InvalidCharacter,
|
InvalidCharacter,
|
||||||
InvalidColour,
|
InvalidColour,
|
||||||
InvalidRenderMode,
|
InvalidRenderMode,
|
||||||
|
Other(&'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScreenChar {
|
impl ScreenChar {
|
||||||
@@ -61,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;
|
||||||
@@ -111,19 +122,18 @@ 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, 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
|
||||||
let mut processed_frame: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT] = [[ScreenChar::null(); BUFFER_WIDTH]; BUFFER_HEIGHT];
|
|
||||||
|
|
||||||
for (i, row) in frame.iter().enumerate() {
|
for (i, row) in frame.iter_mut().enumerate() {
|
||||||
for (j, col) in row.iter().enumerate() {
|
for (j, col) in row.iter_mut().enumerate() {
|
||||||
processed_frame[i][j] = match special_char(col.character as char) {
|
if col.character == 0u8 { continue; }
|
||||||
Some(c) => ScreenChar::new(c as u8, col.colour),
|
if let Some(c) = special_char(col.character as char) {
|
||||||
None => *col,
|
col.character = c as u8;
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.app_buffer = processed_frame;
|
self.app_buffer[i][j] = *col;
|
||||||
|
}
|
||||||
|
}
|
||||||
self.internal_render();
|
self.internal_render();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,6 +306,7 @@ impl Renderer {
|
|||||||
if self.application_mode {
|
if self.application_mode {
|
||||||
for (i, row) in self.app_buffer.iter().enumerate() {
|
for (i, row) in self.app_buffer.iter().enumerate() {
|
||||||
for (j, col) in row.iter().enumerate() {
|
for (j, col) in row.iter().enumerate() {
|
||||||
|
if col.character == 0u8 { continue; }
|
||||||
self.screen_ref.chars[i][j].write(*col);
|
self.screen_ref.chars[i][j].write(*col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -206,7 +206,10 @@ impl KeyboardHandler {
|
|||||||
pub(crate) fn add_scancode(scancode: u8) {
|
pub(crate) fn add_scancode(scancode: u8) {
|
||||||
if let Ok(queue) = SCANCODE_QUEUE.try_get() {
|
if let Ok(queue) = SCANCODE_QUEUE.try_get() {
|
||||||
if let Err(_) = queue.push(scancode) {
|
if let Err(_) = queue.push(scancode) {
|
||||||
println!("WARNING: queue is full - ignoring input");
|
let _ = queue.pop();
|
||||||
|
if let Err(_) = queue.push(scancode) {
|
||||||
|
println!("WARNING: scancode queue is full");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
WAKER.wake();
|
WAKER.wake();
|
||||||
}
|
}
|
||||||
@@ -221,7 +224,7 @@ pub struct ScanCodeStream {
|
|||||||
|
|
||||||
impl ScanCodeStream {
|
impl ScanCodeStream {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
SCANCODE_QUEUE.try_init_once(|| ArrayQueue::new(100))
|
SCANCODE_QUEUE.try_init_once(|| ArrayQueue::new(3))
|
||||||
.expect("ScanCodeStream::new has already been called once");
|
.expect("ScanCodeStream::new has already been called once");
|
||||||
ScanCodeStream { _private: () }
|
ScanCodeStream { _private: () }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use alloc::{string::String, vec::Vec, boxed::Box};
|
use alloc::{string::String, vec::Vec, boxed::Box};
|
||||||
|
|
||||||
|
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, _: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,6 +18,7 @@ pub enum Error {
|
|||||||
CommandFailed(String),
|
CommandFailed(String),
|
||||||
ApplicationError(String),
|
ApplicationError(String),
|
||||||
EmptyCommand,
|
EmptyCommand,
|
||||||
|
NoWindow,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Exit {
|
pub enum Exit {
|
||||||
|
|||||||
+5
-37
@@ -48,46 +48,10 @@ impl Serial {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// enum with a terminal and application mode
|
|
||||||
pub enum Screen {
|
|
||||||
Terminal,
|
|
||||||
Application,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// DEPRECATED - STOP USING THIS SOON
|
|
||||||
impl Screen {
|
|
||||||
/// mode can be set for the kernel using this method
|
|
||||||
// pub fn set_mode(&self) -> Result<(), RenderError> {
|
|
||||||
// Ok(match self {
|
|
||||||
// Screen::Terminal => RENDERER.lock().terminal_mode(),
|
|
||||||
// Screen::Application => RENDERER.lock().application_mode(),
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// returns the current display mode
|
|
||||||
pub fn get_mode() -> Screen {
|
|
||||||
match RENDERER.lock().mode_is_app() {
|
|
||||||
true => Screen::Application,
|
|
||||||
false => Screen::Terminal,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// switches between modes
|
|
||||||
pub fn switch(&self) {
|
|
||||||
if RENDERER.lock().mode_is_app() == true {
|
|
||||||
RENDERER.lock().terminal_mode();
|
|
||||||
} else {
|
|
||||||
RENDERER.lock().application_mode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn clear() {
|
|
||||||
RENDERER.lock().clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An interface that tells the kernel what rendering mode to use
|
/// An interface that tells the kernel what rendering mode to use
|
||||||
/// Creating an instance of this struct will enable application rendering mode
|
/// Creating an instance of this struct will enable application rendering mode
|
||||||
/// Dropping the instance will return the display to focus on the terminal.
|
/// Dropping the instance will return the display to focus on the terminal.
|
||||||
|
/// this will be deprecated in the near future !!
|
||||||
pub struct Display;
|
pub struct Display;
|
||||||
|
|
||||||
impl Display {
|
impl Display {
|
||||||
@@ -99,6 +63,10 @@ impl Display {
|
|||||||
pub fn mv_cursor(&self, x: u8, y: u8) -> Result<(), RenderError> {
|
pub fn mv_cursor(&self, x: u8, y: u8) -> Result<(), RenderError> {
|
||||||
RENDERER.lock().cursor_position(x, y)
|
RENDERER.lock().cursor_position(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear() {
|
||||||
|
RENDERER.lock().clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Display {
|
impl Drop for Display {
|
||||||
|
|||||||
@@ -4,13 +4,15 @@ use alloc::{string::String};
|
|||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref OS: Mutex<SysInfo> = Mutex::new(SysInfo {
|
pub static ref OS: Mutex<SysInfo> = Mutex::new(SysInfo {
|
||||||
os: String::from("CrystalOS Alpha"),
|
os: String::from("Zxq5-OS"),
|
||||||
version: String::from("0.2.2"),
|
version: String::from("0.2.2"),
|
||||||
|
url: String::from("https://git.zxq5.dev/OsDev/Zxq5-OS")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SysInfo {
|
pub struct SysInfo {
|
||||||
pub os: String,
|
pub os: String,
|
||||||
pub version: String,
|
pub version: String,
|
||||||
|
pub url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+213
-6
@@ -4,7 +4,7 @@ use alloc::vec::Vec;
|
|||||||
use crate::system::kernel::render::{RENDERER, ScreenChar};
|
use crate::system::kernel::render::{RENDERER, ScreenChar};
|
||||||
use crate::std::io::Color;
|
use crate::std::io::Color;
|
||||||
use num_traits::{Num, ToPrimitive};
|
use num_traits::{Num, ToPrimitive};
|
||||||
|
use crate::serial_println;
|
||||||
/// TODO: get a working implementation for CLI apps
|
/// TODO: get a working implementation for CLI apps
|
||||||
/// elements can be created using their from_str() method
|
/// elements can be created using their from_str() method
|
||||||
/// you can then render the element to the current frame using the render() method
|
/// you can then render the element to the current frame using the render() method
|
||||||
@@ -21,6 +21,185 @@ pub use crate::system::kernel::render::{
|
|||||||
BUFFER_HEIGHT
|
BUFFER_HEIGHT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub struct Window {
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
x: usize,
|
||||||
|
y: usize,
|
||||||
|
bordered: bool,
|
||||||
|
open: bool,
|
||||||
|
title: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Window {
|
||||||
|
pub fn new() -> Window {
|
||||||
|
Window {
|
||||||
|
width: BUFFER_WIDTH,
|
||||||
|
height: BUFFER_HEIGHT,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
bordered: true,
|
||||||
|
open: false,
|
||||||
|
title: String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open(&mut self) -> Result<(), RenderError> {
|
||||||
|
RENDERER.lock().application_mode();
|
||||||
|
|
||||||
|
if self.open { return Err(RenderError::InvalidRenderMode); }
|
||||||
|
|
||||||
|
self.open = true;
|
||||||
|
self.render(&Frame::from_window(self))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_open(&self) -> bool {
|
||||||
|
self.open
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dimensions(&self) -> Dimensions<usize> {
|
||||||
|
Dimensions::new(self.width, self.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_dimensions(&mut self, width: usize, height: usize) {
|
||||||
|
self.width = width;
|
||||||
|
self.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn position(&self) -> Position<usize> {
|
||||||
|
Position::new(self.x, self.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_position(&mut self, x: usize, y: usize) {
|
||||||
|
self.x = x;
|
||||||
|
self.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_title(&mut self, title: &str) {
|
||||||
|
self.title = String::from(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(&self, f: &Frame) -> Result<(), RenderError> {
|
||||||
|
let mut frame: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT] = [[ScreenChar::null(); BUFFER_WIDTH]; BUFFER_HEIGHT];
|
||||||
|
|
||||||
|
for (i, row) in f.frame.iter().enumerate() {
|
||||||
|
for (j, col) in row.iter().enumerate() {
|
||||||
|
frame[i + f.position.y][j + f.position.x] = col.as_screen_char();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.bordered {
|
||||||
|
self.outline(&mut frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
RENDERER.lock().render_frame(frame);
|
||||||
|
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> {
|
||||||
|
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]) {
|
||||||
|
// draws the sides of the container
|
||||||
|
// Calculate the dimensions
|
||||||
|
let dimensions = self.dimensions();
|
||||||
|
|
||||||
|
// Extract coordinates for readability
|
||||||
|
let top_y = self.y as isize - 1;
|
||||||
|
let bottom_y = self.y as isize + dimensions.y as isize;
|
||||||
|
let left_x = self.x as isize - 1;
|
||||||
|
let right_x = self.x as isize + dimensions.x as isize;
|
||||||
|
let x_start = self.x as isize;
|
||||||
|
let x_end = self.x as isize + dimensions.x as isize;
|
||||||
|
let y_start = self.y as isize;
|
||||||
|
let y_end = self.y as isize + dimensions.y as isize;
|
||||||
|
|
||||||
|
// Define ranges
|
||||||
|
let (top, bottom, left, right) = (
|
||||||
|
(top_y, x_start..x_end),
|
||||||
|
(bottom_y, x_start..x_end),
|
||||||
|
(left_x, y_start..y_end),
|
||||||
|
(right_x, y_start..y_end),
|
||||||
|
);
|
||||||
|
|
||||||
|
let title = self.title.clone();
|
||||||
|
let title_width = title.len();
|
||||||
|
let mut title_x = left_x + (dimensions.x as isize - title_width as isize) / 2;
|
||||||
|
if title_x < left_x {
|
||||||
|
title_x = left_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (y, range) in [top, bottom] {
|
||||||
|
for x in range {
|
||||||
|
if x >= 0 && x < 80 && y >= 0 && y < 25 {
|
||||||
|
frame[y as usize][x as usize] = ColouredChar::new('─').as_screen_char();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (x, range) in [left, right] {
|
||||||
|
for y in range {
|
||||||
|
if x >= 0 && x < 80 && y >= 0 && y < 25 {
|
||||||
|
frame[y as usize][x as usize] = ColouredChar::new('│').as_screen_char();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, c) in title.chars().enumerate() {
|
||||||
|
let i = i as isize;
|
||||||
|
if title_x + i >= 0 && title_x + i < 80 && top_y >= 0 && top_y < 25 {
|
||||||
|
frame[top_y as usize][(title_x + i as isize) as usize] = ColouredChar::new(c).as_screen_char();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw the corners of the container
|
||||||
|
let corners = [
|
||||||
|
(top_y, left_x, '┌'),
|
||||||
|
(top_y, right_x, '┐'),
|
||||||
|
(bottom_y, left_x, '└'),
|
||||||
|
(bottom_y, right_x, '┘'),
|
||||||
|
];
|
||||||
|
for &(y, x, c) in &corners {
|
||||||
|
if x >= 0 && x < 80 && y >= 0 && y < 25 {
|
||||||
|
frame[y as usize][x as usize] = ColouredChar::new(c).as_screen_char();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.open {
|
||||||
|
self.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct ColouredChar {
|
pub struct ColouredChar {
|
||||||
@@ -38,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),
|
||||||
@@ -56,11 +242,9 @@ impl ColouredChar {
|
|||||||
colour: self.colour,
|
colour: self.colour,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct Position<T: Num> {
|
pub struct Position<T: Num> {
|
||||||
pub x: T,
|
pub x: T,
|
||||||
@@ -113,10 +297,18 @@ 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],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_window(window: &Window) -> Frame {
|
||||||
|
Frame {
|
||||||
|
dimensions: Dimensions::new(window.width as usize, window.height as usize),
|
||||||
|
position: Position::new(window.x as usize, window.y as usize),
|
||||||
|
frame: vec![vec![ColouredChar::blank(); window.width as usize]; window.height as usize],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_str(elemstr: String) -> Self {
|
pub fn from_str(elemstr: String) -> Self {
|
||||||
let mut element = Frame { frame: Vec::<Vec<ColouredChar>>::new(), dimensions: Dimensions::new(0, 0), position: Position::new(0, 0) };
|
let mut element = Frame { frame: Vec::<Vec<ColouredChar>>::new(), dimensions: Dimensions::new(0, 0), position: Position::new(0, 0) };
|
||||||
|
|
||||||
@@ -141,6 +333,7 @@ impl Frame {
|
|||||||
self.frame.clone()
|
self.frame.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// DEPRECATED. Use Window::render(&Frame) instead !!
|
||||||
pub fn write_to_screen(&self) -> Result<(), RenderError> {
|
pub fn write_to_screen(&self) -> Result<(), RenderError> {
|
||||||
let mut frame: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT] = [[ScreenChar::null(); BUFFER_WIDTH]; BUFFER_HEIGHT];
|
let mut frame: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT] = [[ScreenChar::null(); BUFFER_WIDTH]; BUFFER_HEIGHT];
|
||||||
for (i, row) in self.frame.iter().enumerate() {
|
for (i, row) in self.frame.iter().enumerate() {
|
||||||
@@ -151,6 +344,7 @@ impl Frame {
|
|||||||
RENDERER.lock().render_frame(frame);
|
RENDERER.lock().render_frame(frame);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_position(&self) -> Position<usize> {
|
pub fn get_position(&self) -> Position<usize> {
|
||||||
self.position
|
self.position
|
||||||
}
|
}
|
||||||
@@ -210,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 {
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ use core::fmt;
|
|||||||
use alloc::{boxed::Box, format, string::String, vec::Vec};
|
use alloc::{boxed::Box, format, string::String, vec::Vec};
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
use alloc::borrow::ToOwned;
|
use alloc::borrow::ToOwned;
|
||||||
use crate::{println, print, mknode, std, serial_println};
|
use crate::std::render::Window;
|
||||||
|
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
|
||||||
@@ -357,8 +359,8 @@ 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, args: Vec<String>) -> Result<(), ShellError> {
|
async fn run(&mut self, args: Vec<String>) -> Result<(), ShellError> {
|
||||||
@@ -420,8 +422,6 @@ impl Calculator {
|
|||||||
e
|
e
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
serial_println!("{:?}", tokens);
|
|
||||||
|
|
||||||
let mut parser = Parser::new(tokens).unwrap();
|
let mut parser = Parser::new(tokens).unwrap();
|
||||||
parser.parse().map_err(|e| format!("{:?}", e))
|
parser.parse().map_err(|e| format!("{:?}", e))
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-64
@@ -1,7 +1,7 @@
|
|||||||
use crate::{serial_println, std};
|
use crate::{serial_println, std};
|
||||||
use crate::std::application::{self, Application};
|
use crate::std::application::{self, Application};
|
||||||
use crate::std::io::{Color, ColorCode, Display, KeyStroke};
|
use crate::std::io::{Color, ColorCode, Display, KeyStroke};
|
||||||
use crate::std::render::{ColouredChar, Frame, Position, RenderError};
|
use crate::std::render::{ColouredChar, Frame, Position, RenderError, Window};
|
||||||
use crate::user::lib::libgui::cg_core::CgComponent;
|
use crate::user::lib::libgui::cg_core::CgComponent;
|
||||||
|
|
||||||
|
|
||||||
@@ -20,8 +20,8 @@ pub struct Editor {
|
|||||||
command: String,
|
command: String,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
unsaved: bool,
|
unsaved: bool,
|
||||||
display: Display,
|
|
||||||
lineno_width: i32,
|
lineno_width: i32,
|
||||||
|
window: Window,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Mode {
|
enum Mode {
|
||||||
@@ -36,7 +36,7 @@ impl core::fmt::Display for Mode {
|
|||||||
match self {
|
match self {
|
||||||
Mode::Normal => write!(f, "Normal"),
|
Mode::Normal => write!(f, "Normal"),
|
||||||
Mode::Insert => write!(f, "Insert"),
|
Mode::Insert => write!(f, "Insert"),
|
||||||
Mode::Command => write!(f, "Commnd"),
|
Mode::Command => write!(f, "Cmmd "),
|
||||||
Mode::Diff => write!(f, "Diff "),
|
Mode::Diff => write!(f, "Diff "),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,38 +67,25 @@ impl Editor {
|
|||||||
self.cursor_pos.x += dx;
|
self.cursor_pos.x += dx;
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_println!("cursor: {} {} offset: {} {} ", self.cursor_pos.x, self.cursor_pos.y, self.offset_pos.x, self.offset_pos.y);
|
while self.cursor_pos.x + 2 + (self.lineno_width + 2) > self.window.dimensions().x as i32 + self.offset_pos.x {
|
||||||
|
|
||||||
while self.cursor_pos.x + 3 + (self.lineno_width + 2) > 80 + self.offset_pos.x {
|
|
||||||
self.offset_pos.x += 1;
|
self.offset_pos.x += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while self.cursor_pos.x - 3 < self.offset_pos.x && self.offset_pos.x - 3 >= 0 {
|
while self.cursor_pos.x - 3 < self.offset_pos.x && self.offset_pos.x - 1 >= 0 {
|
||||||
self.offset_pos.x -= 1;
|
self.offset_pos.x -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while self.cursor_pos.y + 3 > self.offset_pos.y + 25 {
|
while self.cursor_pos.y + 3 > self.offset_pos.y + self.window.dimensions().y as i32 {
|
||||||
self.offset_pos.y += 1;
|
self.offset_pos.y += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while self.cursor_pos.y - 3 < self.offset_pos.y && self.offset_pos.y - 3 >= 0 {
|
while self.cursor_pos.y - 1 < self.offset_pos.y && self.offset_pos.y - 1 >= 0 {
|
||||||
self.offset_pos.y -= 1;
|
self.offset_pos.y -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_println!(
|
self.window.move_cursor(
|
||||||
"moving cursor to {}, {}",
|
self.cursor_pos.x - self.offset_pos.x + self.lineno_width + 2,
|
||||||
(self.cursor_pos.x - self.offset_pos.x + self.lineno_width + 2) as u8,
|
self.cursor_pos.y - self.offset_pos.y
|
||||||
(self.cursor_pos.y - self.offset_pos.y) as u8
|
|
||||||
);
|
|
||||||
|
|
||||||
// print all the values below
|
|
||||||
serial_println!("offset: {}, {}", self.offset_pos.x, self.offset_pos.y);
|
|
||||||
serial_println!("cursor: {}, {}", self.cursor_pos.x, self.cursor_pos.y);
|
|
||||||
serial_println!("line width: {}", self.lineno_width + 2);
|
|
||||||
|
|
||||||
self.display.mv_cursor(
|
|
||||||
(self.cursor_pos.x - self.offset_pos.x + self.lineno_width + 2) as u8,
|
|
||||||
(self.cursor_pos.y - self.offset_pos.y) as u8
|
|
||||||
).unwrap();
|
).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,43 +143,39 @@ 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(),
|
||||||
command: String::new(),
|
command: String::new(),
|
||||||
mode: Mode::Normal,
|
mode: Mode::Normal,
|
||||||
unsaved: false,
|
unsaved: false,
|
||||||
display: Display::borrow(),
|
lineno_width: 0,
|
||||||
lineno_width: 0
|
window,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&mut self, _args: Vec<String>) -> Result<(), application::Error> {
|
async fn run(&mut self, args: Vec<String>) -> Result<(), application::Error> {
|
||||||
|
|
||||||
// if let Some(s) = args.get(0) {
|
|
||||||
// self.buffer = s.lines().map(|l| l.chars().collect()).collect::<Vec<Vec<char>>>()
|
|
||||||
// }
|
|
||||||
|
|
||||||
self.buffer = String::from("
|
|
||||||
/$$ /$$$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$$ /$$ /$$ /$$
|
|
||||||
/$$/|_____ $$ | $$ / $$ /$$__ $$| $$____/ /$$/| $$| $$
|
|
||||||
/$$/ /$$/ | $$/ $$/| $$ \\ $$| $$ /$$/ \\ $$\\ $$
|
|
||||||
/$$/ /$$/ \\ $$$$/ | $$ | $$| $$$$$$$ /$$/ \\ $$\\ $$
|
|
||||||
| $$ /$$/ >$$ $$ | $$ | $$|_____ $$ /$$/ /$$/ /$$/
|
|
||||||
\\ $$ /$$/ /$$/\\ $$| $$/$$ $$ /$$ \\ $$ /$$/ /$$/ /$$/
|
|
||||||
\\ $$ /$$$$$$$$| $$ \\ $$| $$$$$$/| $$$$$$//$$/ /$$/ /$$/
|
|
||||||
\\__/|________/|__/ |__/ \\____ $$$ \\______/|__/ |__/ |__/
|
|
||||||
\\__/
|
|
||||||
").lines().map(|l| l.chars().collect()).collect::<Vec<Vec<char>>>();
|
|
||||||
|
|
||||||
|
self.window.set_dimensions(60, 15);
|
||||||
|
self.window.set_position(10, 3);
|
||||||
|
self.window.set_title("Editor");
|
||||||
|
self.window.open();
|
||||||
|
|
||||||
|
if let Some(s) = args.get(0) {
|
||||||
|
self.buffer = s.lines().map(|l| l.chars().collect()).collect::<Vec<Vec<char>>>()
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// start by rendering the screen
|
// start by rendering the screen
|
||||||
self.lineno_width = self.buffer.len().to_string().len() as i32;
|
self.lineno_width = self.buffer.len().to_string().len() as i32;
|
||||||
self.render().unwrap().write_to_screen().unwrap();
|
|
||||||
|
if let Ok(frame) = self.render() {
|
||||||
|
self.window.render(&frame).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
// wait for a keyboard input
|
// wait for a keyboard input
|
||||||
let keystroke = std::io::Stdin::keystroke().await;
|
let keystroke = std::io::Stdin::keystroke().await;
|
||||||
@@ -203,19 +186,12 @@ impl Application for Editor {
|
|||||||
KeyStroke::Char('i') => self.mode = Mode::Insert,
|
KeyStroke::Char('i') => self.mode = Mode::Insert,
|
||||||
KeyStroke::Char(':') => self.mode = Mode::Command,
|
KeyStroke::Char(':') => self.mode = Mode::Command,
|
||||||
KeyStroke::Char('d') => self.mode = Mode::Diff,
|
KeyStroke::Char('d') => self.mode = Mode::Diff,
|
||||||
KeyStroke::Char('`') => {
|
KeyStroke::Char('`') => return Ok(()),
|
||||||
// TODO: End terminal session
|
|
||||||
// ncurses::endwin();
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Mode::Insert => {
|
Mode::Insert => {
|
||||||
match keystroke {
|
match keystroke {
|
||||||
KeyStroke::Enter => {
|
|
||||||
// TODO: newline function
|
|
||||||
},
|
|
||||||
KeyStroke::Char(c) => {
|
KeyStroke::Char(c) => {
|
||||||
match c {
|
match c {
|
||||||
// escape
|
// escape
|
||||||
@@ -247,12 +223,8 @@ impl Application for Editor {
|
|||||||
KeyStroke::Down => {
|
KeyStroke::Down => {
|
||||||
self.move_cursor(0, 1);
|
self.move_cursor(0, 1);
|
||||||
},
|
},
|
||||||
KeyStroke::None => {
|
KeyStroke::None => {},
|
||||||
serial_println!("none");
|
_ => {}
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
serial_println!("other");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Mode::Command => {
|
Mode::Command => {
|
||||||
@@ -280,11 +252,11 @@ impl Application for Editor {
|
|||||||
|
|
||||||
impl CgComponent for Editor {
|
impl CgComponent for Editor {
|
||||||
fn render(&self) -> Result<Frame, RenderError> {
|
fn render(&self) -> Result<Frame, RenderError> {
|
||||||
let mut frame = Frame::new(Position::zero(), Position::new(80, 25))?;
|
let mut frame = Frame::new(self.window.position(), self.window.dimensions())?;
|
||||||
let width = self.lineno_width as usize;
|
let width = self.lineno_width as usize;
|
||||||
let linecolour = ColorCode::new(Color::Cyan, Color::Black);
|
let linecolour = ColorCode::new(Color::Cyan, Color::Black);
|
||||||
|
|
||||||
for (i, line) in (self.offset_pos.y..self.offset_pos.y + 24).enumerate() {
|
for (i, line) in (self.offset_pos.y..self.offset_pos.y + self.window.dimensions().y as i32 - 1).enumerate() {
|
||||||
if line >= self.buffer.len() as i32 {
|
if line >= self.buffer.len() as i32 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -297,7 +269,7 @@ impl CgComponent for Editor {
|
|||||||
|
|
||||||
let line = self.buffer[line as usize].iter().collect::<String>();
|
let line = self.buffer[line as usize].iter().collect::<String>();
|
||||||
|
|
||||||
for (j, c) in line.chars().skip(self.offset_pos.x as usize).take(80 - (width + 2)).enumerate() {
|
for (j, c) in line.chars().skip(self.offset_pos.x as usize).take(self.window.dimensions().x - (width + 2)).enumerate() {
|
||||||
frame.write(Position::new(j + width + 2, i), ColouredChar::new(c))?;
|
frame.write(Position::new(j + width + 2, i), ColouredChar::new(c))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -317,7 +289,7 @@ impl CgComponent for Editor {
|
|||||||
let toolbar = line_and_col + " " + &mode + " " + &unsaved;
|
let toolbar = line_and_col + " " + &mode + " " + &unsaved;
|
||||||
|
|
||||||
for (i, c) in toolbar.chars().enumerate() {
|
for (i, c) in toolbar.chars().enumerate() {
|
||||||
frame.write(Position::new(i, 24), ColouredChar::new(c))?;
|
frame.write(Position::new(i, self.window.dimensions().y - 1), ColouredChar::new(c))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(frame)
|
Ok(frame)
|
||||||
@@ -328,3 +300,14 @@ impl CgComponent for Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// self.buffer = String::from("
|
||||||
|
// /$$ /$$$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$$ /$$ /$$ /$$
|
||||||
|
// /$$/|_____ $$ | $$ / $$ /$$__ $$| $$____/ /$$/| $$| $$
|
||||||
|
// /$$/ /$$/ | $$/ $$/| $$ \\ $$| $$ /$$/ \\ $$\\ $$
|
||||||
|
// /$$/ /$$/ \\ $$$$/ | $$ | $$| $$$$$$$ /$$/ \\ $$\\ $$
|
||||||
|
// | $$ /$$/ >$$ $$ | $$ | $$|_____ $$ /$$/ /$$/ /$$/
|
||||||
|
// \\ $$ /$$/ /$$/\\ $$| $$/$$ $$ /$$ \\ $$ /$$/ /$$/ /$$/
|
||||||
|
// \\ $$ /$$$$$$$$| $$ \\ $$| $$$$$$/| $$$$$$//$$/ /$$/ /$$/
|
||||||
|
// \\__/|________/|__/ |__/ \\____ $$$ \\______/|__/ |__/ |__/
|
||||||
|
// \\__/
|
||||||
|
// ").lines().map(|l| l.chars().collect()).collect::<Vec<Vec<char>>>();
|
||||||
@@ -5,7 +5,7 @@ use alloc::boxed::Box;
|
|||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use crate::std::application::{Application, Error};
|
use crate::std::application::{Application, Error};
|
||||||
use crate::std::render::{Frame, Position, Dimensions, ColouredChar, RenderError};
|
use crate::std::render::{ColouredChar, Dimensions, Frame, Position, RenderError, Window};
|
||||||
use crate::std::io::{Display, KeyStroke, Stdin};
|
use crate::std::io::{Display, KeyStroke, Stdin};
|
||||||
|
|
||||||
use crate::user::lib::libgui::{
|
use crate::user::lib::libgui::{
|
||||||
@@ -43,12 +43,13 @@ 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, args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, args: Vec<String>) -> Result<(), Error> {
|
||||||
let _d = Display::borrow();
|
let _d = Display::borrow();
|
||||||
|
|
||||||
@@ -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),
|
||||||
@@ -136,13 +138,6 @@ impl Application for Grapher {
|
|||||||
entry_widget.update(entry);
|
entry_widget.update(entry);
|
||||||
|
|
||||||
if let Ok(frame) = container.render() {
|
if let Ok(frame) = container.render() {
|
||||||
|
|
||||||
let self_widget = container.elements.get("grapher").unwrap();
|
|
||||||
let _self_clone = self_widget.fetch::<Grapher>().unwrap();
|
|
||||||
|
|
||||||
let entry = container.elements.get("entry_box").unwrap();
|
|
||||||
let _entry_clone = entry.fetch::<CgLineEdit>().unwrap();
|
|
||||||
|
|
||||||
frame.write_to_screen().map_err(|_| Error::ApplicationError(String::from("failed to write to screen")))?;
|
frame.write_to_screen().map_err(|_| Error::ApplicationError(String::from("failed to write to screen")))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,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),
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ pub mod calc;
|
|||||||
pub mod editor;
|
pub mod editor;
|
||||||
pub mod grapher;
|
pub mod grapher;
|
||||||
pub mod tasks;
|
pub mod tasks;
|
||||||
|
pub mod zxqsh;
|
||||||
@@ -4,6 +4,7 @@ use crate::std::application::{
|
|||||||
Error
|
Error
|
||||||
};
|
};
|
||||||
use crate::println;
|
use crate::println;
|
||||||
|
use crate::std::render::Window;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
@@ -25,7 +26,9 @@ 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, args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, args: Vec<String>) -> Result<(), Error> {
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,263 @@
|
|||||||
|
use alloc::{string::String, vec::Vec, boxed::Box, format};
|
||||||
|
use alloc::string::ToString;
|
||||||
|
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, serial_println, utils};
|
||||||
|
use crate::std::application::Error::ApplicationError;
|
||||||
|
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::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<String>,
|
||||||
|
history_idx: usize,
|
||||||
|
|
||||||
|
window: Window,
|
||||||
|
|
||||||
|
// 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]
|
||||||
|
impl Application for ZxqSH {
|
||||||
|
fn new(window: Option<Window>) -> Result<ZxqSH, Error> {
|
||||||
|
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, _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 {
|
||||||
|
match self.next().await {
|
||||||
|
Err(e) => {
|
||||||
|
self.write(format!("Error: {:?}", e), Color::Yellow);
|
||||||
|
return Err(e);
|
||||||
|
},
|
||||||
|
Ok(exit) => {
|
||||||
|
if exit { return Ok(()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ZxqSH {
|
||||||
|
async fn next(&mut self) -> Result<bool, Error> {
|
||||||
|
|
||||||
|
// update cycle for the shell
|
||||||
|
|
||||||
|
// TODO: prompt
|
||||||
|
let mut command = self.input().await;
|
||||||
|
// TODO: exit if necessary
|
||||||
|
|
||||||
|
// TODO: execute command
|
||||||
|
if let Err(e) = self.execute(command, Vec::new()).await {
|
||||||
|
match e {
|
||||||
|
Error::UnknownCommand(e) => {
|
||||||
|
self.write("Unknown command\n".to_string(), Color::Yellow);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.write(format!("Error: {:?}\n", e), Color::Yellow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, string: String, color: Color) {
|
||||||
|
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> {
|
||||||
|
|
||||||
|
let window = Window::new();
|
||||||
|
|
||||||
|
match cmd.as_str() {
|
||||||
|
"calculate" | "calc" | "solve" => Calculator::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
|
"games/connect4" => crate::user::bin::games::connect4::Game::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
|
"rickroll" => Rickroll::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
|
"crystalfetch" => CrystalFetch::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
|
"tasks" => Tasks::new(Some(window)).expect("couldn't open window").run(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(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
|
"games/snake" => games::snake::Game::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
|
"games/asteroids" => games::asteroids::Game::new(Some(window)).expect("couldn't open window").run(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(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
|
"serial" => println!("{}", Serial::reply_char('e')),
|
||||||
|
"games/gameoflife" => GameOfLife::new(Some(window)).expect("couldn't open window").run(Vec::new()).await?,
|
||||||
|
"games/tetris" => {
|
||||||
|
// games::tetris::TetrisEngine::new().expect("couldn't open window").run(Vec::new()).await?;
|
||||||
|
}
|
||||||
|
"gigachad?" => utils::gigachad_detector::GigachadDetector::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
|
"editor" => Editor::new(Some(window)).expect("couldn't open window").run(args).await?,
|
||||||
|
// direct OS functions (not applications)
|
||||||
|
"echo" => {
|
||||||
|
println!(
|
||||||
|
"Crystal: '{}'",
|
||||||
|
args.into_iter()
|
||||||
|
.map(|mut s| {
|
||||||
|
s.push_str(" ");
|
||||||
|
s
|
||||||
|
})
|
||||||
|
.collect::<String>()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
"clear" => Display::clear(),
|
||||||
|
"time" => timer(),
|
||||||
|
_ => return Err(Error::UnknownCommand(cmd))
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Ok(frame) = self.render() {
|
||||||
|
self.window.render(&frame).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CgComponent for ZxqSH {
|
||||||
|
fn render(&self) -> Result<Frame, RenderError> {
|
||||||
|
let mut frame = Frame::from_window(&self.window);
|
||||||
|
|
||||||
|
let term_height = self.window.dimensions().y;
|
||||||
|
let term_width = self.window.dimensions().x;
|
||||||
|
|
||||||
|
self.window.move_cursor(self.get_col() as i32, term_height as i32 - 1)?;
|
||||||
|
|
||||||
|
// render the contents of the terminal to a frame
|
||||||
|
|
||||||
|
let mut line = term_height - 1;
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
self as &dyn Any
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::std::application::Error;
|
use crate::std::application::Error;
|
||||||
use crate::std::application::Error::ApplicationError;
|
use crate::std::application::Error::ApplicationError;
|
||||||
use crate::std::render::{ColouredChar, Dimensions, Frame, Position, RenderError};
|
use crate::std::render::{ColouredChar, Dimensions, Frame, Position, RenderError, Window};
|
||||||
use crate::std::io::{Color, ColorCode, Display, KeyStroke, Stdin};
|
use crate::std::io::{Color, ColorCode, Display, KeyStroke, Stdin};
|
||||||
use crate::std::random::Random;
|
use crate::std::random::Random;
|
||||||
use crate::system::std::application::Application;
|
use crate::system::std::application::Application;
|
||||||
@@ -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,7 +50,7 @@ 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, _args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
|
||||||
let _d = Display::borrow();
|
let _d = Display::borrow();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use alloc::{string::String, vec::Vec, boxed::Box};
|
use alloc::{string::String, vec::Vec, boxed::Box};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{std::{application::{Application, Error}, io::{Color, Display, KeyStroke, Stdin}, random::Random, render::{ColorCode, ColouredChar, Dimensions, Frame, Position, RenderError}, time}, user::lib::libgui::cg_core::CgComponent};
|
use crate::{std::{application::{Application, Error}, io::{Color, Display, KeyStroke, Stdin}, random::Random, render::{ColorCode, ColouredChar, Dimensions, Frame, Position, RenderError, Window}, time}, user::lib::libgui::cg_core::CgComponent};
|
||||||
|
|
||||||
pub struct Game {
|
pub struct Game {
|
||||||
pub board: [[Cell; 7]; 6],
|
pub board: [[Cell; 7]; 6],
|
||||||
@@ -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, _: 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,10 +1,11 @@
|
|||||||
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 crate::std::render::{ColouredChar, Frame, Position, Dimensions, RenderError};
|
use futures_util::future::err;
|
||||||
|
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,9 +17,15 @@ 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, _args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
|
||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use crate::{
|
|||||||
self,
|
self,
|
||||||
application::{Application, Error},
|
application::{Application, Error},
|
||||||
io::{Color, ColorCode, Display, KeyStroke, Stdin},
|
io::{Color, ColorCode, Display, KeyStroke, Stdin},
|
||||||
render::{ColouredChar, Dimensions, Frame, Position, RenderError},
|
render::{ColouredChar, Dimensions, Frame, Position, RenderError, Window},
|
||||||
time
|
time
|
||||||
},
|
},
|
||||||
user::lib::libgui::cg_core::CgComponent
|
user::lib::libgui::cg_core::CgComponent
|
||||||
@@ -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,7 +46,7 @@ impl Application for GameBoard {
|
|||||||
],
|
],
|
||||||
max_territory: 0,
|
max_territory: 0,
|
||||||
current_territory: 0,
|
current_territory: 0,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use alloc::vec::Vec;
|
|||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use crate::std::application::{Application, Error};
|
use crate::std::application::{Application, Error};
|
||||||
use crate::std::render::{BUFFER_HEIGHT, BUFFER_WIDTH, ColorCode, ColouredChar, Dimensions, Frame, Position, RenderError};
|
use crate::std::render::{ColorCode, ColouredChar, Dimensions, Frame, Position, RenderError, Window, BUFFER_HEIGHT, BUFFER_WIDTH};
|
||||||
use crate::std::io::{Color, Display, KeyStroke, Stdin};
|
use crate::std::io::{Color, Display, KeyStroke, Stdin};
|
||||||
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;
|
||||||
@@ -17,12 +17,12 @@ 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, _: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _: Vec<String>) -> Result<(), Error> {
|
||||||
|
|||||||
+22
-12
@@ -1,10 +1,10 @@
|
|||||||
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};
|
||||||
use crate::std::time;
|
use crate::std::time;
|
||||||
use crate::std::application::{Application, Error};
|
use crate::std::application::{Application, Error};
|
||||||
use crate::std::render::{ColouredChar, Dimensions, Frame, RenderError, ColorCode};
|
use crate::std::render::{ColorCode, ColouredChar, Dimensions, Frame, RenderError, Window};
|
||||||
use crate::std::random::Random;
|
use crate::std::random::Random;
|
||||||
use crate::system::std::render;
|
use crate::system::std::render;
|
||||||
use super::super::super::lib::geometry::{Position, Direction};
|
use super::super::super::lib::geometry::{Position, Direction};
|
||||||
@@ -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, 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;
|
|
||||||
+41
-32
@@ -18,15 +18,9 @@ use crate::{
|
|||||||
printerr,
|
printerr,
|
||||||
println,
|
println,
|
||||||
std::{
|
std::{
|
||||||
application::{Application, Error, Exit},
|
application::{Application, Error, Exit}, io::{write, Color, Display, KeyStroke, Serial, Stdin}, render::Window, time::timer
|
||||||
time::{timer},
|
|
||||||
io::{Color, write, Screen, Stdin, Serial, KeyStroke, Display},
|
|
||||||
},
|
},
|
||||||
user::{
|
user::{
|
||||||
lib::libgui::{
|
|
||||||
cg_core::{CgComponent, CgKeyboardCapture},
|
|
||||||
cg_widgets::CgDialog,
|
|
||||||
},
|
|
||||||
bin::{
|
bin::{
|
||||||
apps::{
|
apps::{
|
||||||
calc::Calculator,
|
calc::Calculator,
|
||||||
@@ -48,9 +42,13 @@ use crate::{
|
|||||||
gigachad_detector::GigachadDetector,
|
gigachad_detector::GigachadDetector,
|
||||||
rickroll::Rickroll,
|
rickroll::Rickroll,
|
||||||
},
|
},
|
||||||
},
|
}, lib::libgui::{
|
||||||
|
cg_core::{CgComponent, CgKeyboardCapture},
|
||||||
|
cg_widgets::CgDialog,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
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());
|
||||||
@@ -67,7 +65,9 @@ pub async fn command_handler() {
|
|||||||
pub async fn eventloop() {
|
pub async fn eventloop() {
|
||||||
println!("running!");
|
println!("running!");
|
||||||
|
|
||||||
let mut fetch = CrystalFetch::new();
|
let window = Window::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);
|
||||||
@@ -104,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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,28 +125,30 @@ async fn exec() -> Result<(), Error> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let window = Window::new();
|
||||||
|
|
||||||
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(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(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(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(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(args).await?;
|
cmd.run(args).await?;
|
||||||
}
|
}
|
||||||
"VGA" => {
|
"VGA" => {
|
||||||
@@ -156,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(args).await?;
|
Grapher::new(Some(window)).expect("couldn't open window").run(args).await?;
|
||||||
}
|
}
|
||||||
"games/snake" => {
|
"games/snake" => {
|
||||||
SnakeGame::new().run(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(args).await?;
|
cmd.run(args).await?;
|
||||||
}
|
}
|
||||||
"games/pong" => {
|
"games/pong" => {
|
||||||
PongGame::new().run(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(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(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(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(args).await?;
|
cmd.run(args).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// direct OS functions (not applications)
|
// direct OS functions (not applications)
|
||||||
"echo" => {
|
"echo" => {
|
||||||
println!(
|
println!(
|
||||||
@@ -208,7 +217,7 @@ async fn exec() -> Result<(), Error> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
"clear" => {
|
"clear" => {
|
||||||
Screen::clear();
|
Display::clear();
|
||||||
// not sure why this code was here but leaving it in case weird bugs happen so i remember to add it back if so
|
// not sure why this code was here but leaving it in case weird bugs happen so i remember to add it back if so
|
||||||
//interrupts::without_interrupts(|| {});
|
//interrupts::without_interrupts(|| {});
|
||||||
}
|
}
|
||||||
@@ -272,7 +281,7 @@ impl CommandHandler {
|
|||||||
// TODO: coloured prompt
|
// TODO: coloured prompt
|
||||||
|
|
||||||
pub fn prompt(&self) {
|
pub fn prompt(&self) {
|
||||||
write(format_args!("\n Crystal> "), (Color::Cyan, Color::Black));
|
write(format_args!("\n <Zxq5/> "), (Color::Cyan, Color::Black));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
@@ -2,9 +2,7 @@ use async_trait::async_trait;
|
|||||||
use alloc::{boxed::Box, format, string::String, vec::Vec};
|
use alloc::{boxed::Box, format, string::String, vec::Vec};
|
||||||
|
|
||||||
use crate::std::{
|
use crate::std::{
|
||||||
os::OS,
|
application::{Application, Error}, io::{write, Color, Display}, os::OS, render::Window
|
||||||
io::{Color, write, Screen},
|
|
||||||
application::{Application, Error},
|
|
||||||
};
|
};
|
||||||
use crate::println;
|
use crate::println;
|
||||||
|
|
||||||
@@ -51,24 +49,28 @@ 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, _args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
|
||||||
|
|
||||||
|
// let ds = Display::borrow();
|
||||||
|
|
||||||
let os = OS.lock().os.clone();
|
let os = OS.lock().os.clone();
|
||||||
let version = OS.lock().version.clone();
|
let version = OS.lock().version.clone();
|
||||||
|
let git_url = OS.lock().url.clone();
|
||||||
|
|
||||||
Screen::clear();
|
// clear screen
|
||||||
|
Display::clear();
|
||||||
|
|
||||||
let logo_string = ZXQ5_LOGO;
|
let logo_string = ZXQ5_LOGO;
|
||||||
let info_string = format!(
|
let info_string = format!(
|
||||||
" [ OS » {}
|
" [ OS » {}
|
||||||
[ BUILD » {}
|
[ BUILD » {}
|
||||||
[ Shell » CrySH
|
[ Shell » ZxqSH
|
||||||
[ Github » https://github.com/FantasyPvP/CrystalOS
|
[ Git » {}
|
||||||
[ Author » ZXQ5", os, version);
|
[ Author » ZXQ5", os, version, git_url);
|
||||||
|
|
||||||
// write to output
|
// write to output
|
||||||
let spacer = "\n".repeat(25 - logo_string.lines().count() - 4 - info_string.lines().count());
|
let spacer = "\n".repeat(25 - logo_string.lines().count() - 4 - info_string.lines().count());
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ use alloc::{boxed::Box, string::String, vec::Vec};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
println,
|
println,
|
||||||
std::application::{
|
std::{application::{
|
||||||
Application,
|
Application,
|
||||||
Error,
|
Error,
|
||||||
},
|
}, render::Window},
|
||||||
};
|
};
|
||||||
|
|
||||||
const GIGACHAD: [&'static str; 3] = ["fantasypvp", "zxq5", "ZXQ5"];
|
const GIGACHAD: [&'static str; 3] = ["fantasypvp", "zxq5", "ZXQ5"];
|
||||||
@@ -15,8 +15,8 @@ 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, args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, args: Vec<String>) -> Result<(), Error> {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ const RICKROLL2: &str = "
|
|||||||
`--'";
|
`--'";
|
||||||
|
|
||||||
use crate::println;
|
use crate::println;
|
||||||
|
use crate::std::render::Window;
|
||||||
use alloc::{string::String, boxed::Box, vec::Vec};
|
use alloc::{string::String, boxed::Box, vec::Vec};
|
||||||
|
|
||||||
|
|
||||||
@@ -51,8 +52,8 @@ 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, _args: Vec<String>) -> Result<(), Error> {
|
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
// pub mod libgui_old_archive;
|
// pub mod libgui_old_archive;
|
||||||
pub mod geometry;
|
pub mod geometry;
|
||||||
pub mod libgui;
|
pub mod libgui;
|
||||||
|
pub mod termui;
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub async fn idk() {}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
pub mod components;
|
||||||
Reference in New Issue
Block a user