ok
This commit is contained in:
FantasyPvP
2023-03-10 00:25:08 +00:00
commit e491435dea
60 changed files with 4542 additions and 0 deletions
+582
View File
@@ -0,0 +1,582 @@
use core::fmt;
use alloc::{boxed::Box, string::String, vec::Vec};
use alloc::string::ToString;
use alloc::borrow::ToOwned;
use crate::{println, print, mknode, std};
use async_trait::async_trait;
use crate::std::application::{
Application,
Error as ShellError
};
struct Parser {
tokens: Vec<Token>,
idx: i32,
current: Token
}
struct Interpreter {}
impl Interpreter {
fn new() -> Result<Self, Error>{
return Ok(Self {})
}
fn visit(&mut self, node: Node) -> Result<Value, Error> {
match node {
Node::BinaryOperation(_) => return self.visit_binary_operation(node),
Node::UnaryOperation(_) => return self.visit_unary_operation(node),
Node::Number(_) => return self.visit_number(node),
Node::Operator(_) => return self.visit_operator(node),
}
}
fn visit_number(&mut self, node: Node) -> Result<Value, Error> {
if let Node::Number(x) = node {
Ok(Value::Number(x))
} else {
Err(Error::Other(String::from("value accessed was not an number")))
}
}
fn visit_operator(&mut self, node: Node) -> Result<Value, Error> {
if let Node::Operator(x) = node {
Ok(Value::Operator(x))
} else {
Err(Error::Other(String::from("value is not an operator")))
}
}
fn visit_binary_operation(&mut self, node: Node) -> Result<Value, Error> {
let left = match self.visit(self.get_node(node.clone(), "left")?.expect("returned none").to_owned())? {
Value::Number(x) => x,
_ => return Err(Error::Other(String::from("value is not a number"))),
};
let right = match self.visit(self.get_node(node.clone(), "right")?.expect("returned none").to_owned())? {
Value::Number(x) => x,
_ => return Err(Error::Other(String::from("value is not a number"))),
};
let operator = match self.visit(self.get_node(node.clone(), "operator")?.expect("returned none").to_owned())? {
Value::Operator(x) => x,
_ => return Err(Error::Other(String::from("value is not a binary operator"))),
};
match operator {
Operator::Add => {
return Ok(Value::Number(left + right))
},
Operator::Sub => {
return Ok(Value::Number(left - right))
},
Operator::Div => {
if right != 0.0 {
return Ok(Value::Number(left / right))
} else {
return Err(Error::LogicalError(String::from("division by 0")))
}
},
Operator::Mod => {
return Ok(Value::Number(left % right))
},
Operator::Qot => {
if right != 0.0 {
return Ok(Value::Number(
((left / right) as i64) as f64
))
} else {
return Err(Error::LogicalError(String::from("division by 0")))
}
},
Operator::Mul => {
return Ok(Value::Number(left * right))
},
Operator::Exp => {
return Ok(Value::Number({
let mut val = 1.0;
for _ in 0..(right as i64) {
val *= left
};
val
}))
}
}
}
fn visit_unary_operation(&mut self, node: Node) -> Result<Value, Error> {
let other: f64 = match self.visit(self.get_node(node.clone(), "other")?.expect("returned none").to_owned())? {
Value::Number(x) => x,
_ => return Err(Error::LogicalError("value is not a number".to_string()))
};
if let Node::UnaryOperation(x) = node {
match x.operator {
Node::Operator(Operator::Sub) => {
return Ok(Value::Number(other * -1f64));
},
_ => return Err(Error::LogicalError("value is not an operator".to_string()))
}
} else {
return Err(Error::LogicalError("node is not a binary operator".to_string()))
}
}
fn get_node(&self, node: Node, position: &str) -> Result<Option<Node>, Error> {
let result = match position {
"left" => {
if let Node::BinaryOperation(x) = node {
Some(x.left)
} else {
None
}
}
"right" => {
if let Node::BinaryOperation(x) = node {
Some(x.right)
} else {
None
}
}
"other" => {
if let Node::UnaryOperation(x) = node {
Some(x.other)
} else {
None
}
}
"operator" => {
if let Node::BinaryOperation(x) = node {
Some(x.operator)
} else {
None
}
},
_ => return Err(Error::Other(String::from("invalid param for get_Node")))
};
Ok(result)
}
}
impl Parser {
fn new(tokens: Vec<Token>) -> Result<Self, Error> {
let mut parser = Self { tokens, idx: -1, current: Token::Null };
parser.advance()?;
Ok(parser)
}
fn parse(&mut self) -> Result<Node, Error> {
let result = self.expr();
result
}
fn advance(&mut self) -> Result<Option<Token>, Error> {
self.idx += 1;
if self.idx < self.tokens.len() as i32 {
self.current = self.tokens[self.idx as usize].clone();
Ok(Some(self.current.clone()))
} else if self.idx == self.tokens.len() as i32 {
Ok(None)
} else {
Err(Error::Eof)
}
}
fn atom(&mut self) -> Result<Node, Error> {
let token = self.current.clone();
match token {
Token::Number(x) => {
self.advance()?;
return Ok(Node::Number(x))
},
Token::Bracket('(') => {
self.advance()?;
let expr = self.expr()?;
if let Token::Bracket(')') = self.current {
self.advance()?;
return Ok(expr)
} else {
return Err(Error::InvalidSyntax(0))
}
},
_ => return Err(Error::InvalidSyntax(0))
}
}
fn power(&mut self) -> Result<Node, Error> {
let mut left = self.atom()?;
while let Token::Operator(Operator::Exp) = self.current {
let current = self.current.clone();
self.advance()?;
let operator = mknode!(current).expect("mknode function returned None");
let right = self.factor()?;
left = Node::BinaryOperation(Box::new(BinaryOperation { left: left.clone(), operator, right }));
}
Ok(left)
}
fn factor(&mut self) -> Result<Node, Error> {
let token = self.current.clone();
match token {
Token::Operator(Operator::Add) | Token::Operator(Operator::Sub) => {
self.advance()?;
let operator = mknode!(token).expect("mknode returned none");
let other = self.factor().expect("holup");
return Ok(Node::UnaryOperation(Box::new(UnaryOperation { operator, other})))
},
_ => {
return Ok(self.power()?)
}
}
}
fn term(&mut self) -> Result<Node, Error> {
let mut left = self.factor()?;
while let Token::Operator(Operator::Div)
| Token::Operator(Operator::Mul)
| Token::Operator(Operator::Mod)
| Token::Operator(Operator::Qot) = self.current {
let current = self.current.clone();
self.advance()?;
let operator = mknode!(current).expect("mknode function returned None");
let right = self.factor()?;
left = Node::BinaryOperation(Box::new(BinaryOperation { left: left.clone(), operator, right }));
}
Ok(left)
}
fn expr(&mut self) -> Result<Node, Error> {
let mut left = self.term()?;
while let Token::Operator(Operator::Sub) | Token::Operator(Operator::Add) = self.current {
let current = self.current.clone();
self.advance()?;
let operator = mknode!(current).expect("mknode returned None");
let right = self.term()?;
left = Node::BinaryOperation(Box::new(BinaryOperation { left: left.clone(), operator, right }));
}
Ok(left)
}
}
#[macro_export]
macro_rules! mknode {
($token:expr) => {
match $token {
Token::Operator(x) => Some(Node::Operator(x)),
Token::Number(x) => Some(Node::Number(x)),
_ => None
}
};
}
pub struct Calculator {}
#[async_trait]
impl Application for Calculator {
fn new() -> Self {
Self {}
}
async fn run(&mut self, args: Vec<String>) -> Result<(), ShellError> {
if args.len() == 0 {
loop {
print!("enter equation > ");
let inp = std::io::stdin().await;
println!("{}", inp);
if inp == String::from("exit\n") {
return Ok(());
}
match calculate_inner(inp) {
Ok(_) => (),
Err(_) => { println!("your input must be a valid mathematical expression contaning only numbers (including floats) and the operators: [ +, -, *, **, /, //, % ]"); return Err(ShellError::CommandFailed(String::from("failed"))) },
};
}
} else {
match calculate_inner(args.into_iter().collect()) {
Ok(x) => x,
Err(_) => { println!("your input must be a valid mathematical expression contaning only numbers (including floats) and the operators: [ +, -, *, **, /, //, % ]"); return Err(ShellError::CommandFailed(String::from("failed"))) },
};
Ok(())
}
}
}
fn calculate_inner(mut equation: String) -> Result<f64, Error> {
equation.push('\n');
let mut neweq = equation.clone();
neweq.pop();
let tokens = tokenise(&equation)?;
let mut parser = Parser::new(tokens)?;
let ast = parser.parse()?;
let mut interpreter = Interpreter::new()?;
let result = interpreter.visit(ast)?;
let return_res = {
if let Value::Number(x) = result {
x
} else {
panic!("did not return a float!");
}
};
println!("\n\n
_____ _ _
/ ____| | | | |
| | _ __ _ _ ___| |_ __ _| |
| | | '__| | | / __| __/ _` | |
| |____| | | |_| \\__ \\ || (_| | |
\\_____|_| \\__, |___/\\__\\__,_|_|
_____ __/ |
/ ____||___/ |
| | __ _| | ___
| | / _` | |/ __|
| |___| (_| | | (__
\\_____\\__,_|_|\\___|
┌────────────────────────────────────────────┐
│ │
│ Expression -> [ {} ]
│ │
│ Calculated Solution -> [ {} ]
│ │
└────────────────────────────────────────────┘
", neweq, return_res);
Ok(return_res)
}
fn tokenise(equation: &str) -> Result<Vec<Token>, Error> {
let mut tokens = Vec::new();
let mut current_num = "".to_string();
let current_string: String = "".to_string();
'mainloop: for (x, character) in equation.chars().enumerate() {
match character {
'0'..='9' => current_num.push(character),
'.' => current_num.push(character),
_ => {
if current_num.len() != 0 {
tokens.push(Token::Number(current_num.parse::<f64>().unwrap()));
current_num = "".to_string();
} else if current_string.len() != 0 {
} match character {
'+' => tokens.push(Token::Operator(Operator::Add)),
'-' => tokens.push(Token::Operator(Operator::Sub)),
'%' => tokens.push(Token::Operator(Operator::Mod)),
'*' => {
if &equation.chars().nth(x-1).unwrap() == &'*' {
tokens.push(Token::Operator(Operator::Exp));
} else if &equation.chars().nth(x+1).unwrap() == &'*' {
()
} else {
tokens.push(Token::Operator(Operator::Mul));
}
},
'/' => {
if &equation.chars().nth(x-1).unwrap() == &'/' {
tokens.push(Token::Operator(Operator::Qot));
} else if &equation.chars().nth(x+1).unwrap() == &'/' {
()
} else {
tokens.push(Token::Operator(Operator::Div));
}
},
'(' | ')' | '[' | ']' | '{' | '}' | '<' | '>' => tokens.push(Token::Bracket(character)),
'\n' => break 'mainloop,
' ' => (),
_ => {
return Err(Error::InvalidCharacter(x))
},
}
}
}
}
Ok(tokens)
}
#[derive(Debug)]
enum Value {
Number(f64),
Operator(Operator)
}
#[derive(Debug, Clone, PartialEq)]
enum Token {
Number(f64),
Operator(Operator),
Bracket(char),
Null,
}
#[derive(Copy, Debug, Clone, PartialEq)]
enum Operator {
Add,
Sub,
Mul,
Div,
Qot,
Mod,
Exp,
}
#[derive(Debug)]
enum Error {
InvalidSyntax(usize),
InvalidCharacter(usize),
LogicalError(String),
Eof,
Other(String),
}
#[derive(Debug, Clone, PartialEq)]
enum Node {
Number(f64),
Operator(Operator),
BinaryOperation(Box<BinaryOperation>),
UnaryOperation(Box<UnaryOperation>)
}
#[derive(Debug, Clone, PartialEq)]
struct BinaryOperation {
left: Node,
operator: Node,
right: Node,
}
#[derive(Debug, Clone, PartialEq)]
struct UnaryOperation {
operator: Node,
other: Node,
}
impl fmt::Display for BinaryOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f, "(\n{} \n{} \n{}\n)
", self.left, self.operator, self.right
)
}
}
impl fmt::Display for UnaryOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f, "(\n{} \n{} \n)
", self.operator, self.other,
)
}
}
impl fmt::Display for Node {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Node::Number(x) => write!(f, "{}", x),
Node::Operator(x) => write!(f, "{}", x),
Node::BinaryOperation(x) => {
let inner = *x.clone();
write!(f, "{}", inner)
}
Node::UnaryOperation(x) => {
let inner = *x.clone();
write!(f, "{}", inner)
}
}
}
}
impl fmt::Display for Operator {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Operator::Add => write!(f, "+"),
Operator::Sub => write!(f, "-"),
Operator::Mul => write!(f, "*"),
Operator::Div => write!(f, "/"),
Operator::Mod => write!(f, "%"),
Operator::Qot => write!(f, "//"),
Operator::Exp => write!(f, "**"),
}
}
}
+53
View File
@@ -0,0 +1,53 @@
use super::entity::Enemy;
use alloc::vec::Vec;
pub enum Event {
PlayerKilled,
EntityKilled(Enemy),
}
pub enum Choice<A, B> {
A(A),
B(B),
}
impl core::fmt::Display for Event {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Event::PlayerKilled => write!(f, "Player killed!"),
Event::EntityKilled(x) => write!(f, "Entity killed! {}", x),
}
}
}
impl<A, B> core::fmt::Display for Choice<A, B> where
A: core::fmt::Display,
B: core::fmt::Display
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Choice::A(a) => write!(f, "{}", a),
Choice::B(b) => write!(f, "{}", b),
}
}
}
pub fn eventcheck<A>(e: (A, Option<Vec<Event>>)) -> Choice<A, Event> {
match e.1 {
Some(events) => {
for event in events {
match event {
Event::PlayerKilled => {
return Choice::B(event)
}
Event::EntityKilled(entity) => {
return Choice::B(event)
}
}
}
},
None => (),
};
Choice::A(e.0)
}
+102
View File
@@ -0,0 +1,102 @@
use super::player::Player;
use super::engine::Event;
use alloc::{string::String, vec::Vec, vec};
use crate::std::random;
pub trait Entity {
fn attack_entity(&mut self, _: &mut EntityObject) -> (AttackResult, Option<Vec<Event>>) {
(AttackResult::Miss, None)
}
}
pub enum EntityObject<'a> {
Player(&'a mut Player),
Enemy(&'a mut Enemy),
}
#[derive(Debug, Clone, Copy)]
pub enum AttackResult {
Miss,
GlancingBlow(f64),
Hit(f64),
CriticalHit(f64),
FriendlyFire,
}
impl core::fmt::Display for AttackResult {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
AttackResult::Miss => write!(f, "Missed!"),
AttackResult::GlancingBlow(damage) => write!(f, "Glancing Blow: {}", damage),
AttackResult::Hit(damage) => write!(f, "Hit: {}", damage),
AttackResult::CriticalHit(damage) => write!(f, "Critical Hit: {}", damage),
AttackResult::FriendlyFire => write!(f, "Friendly Fire (no damage dealt)!"),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Enemy {
pub health_points: f64,
pub max_health_points: f64,
pub base_attack_damage: f64,
pub speed: f64,
}
impl Enemy {
pub fn new() -> Self {
Self {
health_points: 200.0,
max_health_points: 200.0,
base_attack_damage: 5.0,
speed: 100.0,
}
}
}
impl core::fmt::Display for Enemy {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Enemy: {}/{}", self.health_points, self.max_health_points)
}
}
impl Entity for Enemy {
fn attack_entity(&mut self, target: &mut EntityObject) -> (AttackResult, Option<Vec<Event>>) {
let mut entity = if let EntityObject::Player(player) = target {
player
} else {
return (AttackResult::FriendlyFire, None);
};
// combat implementation
let dmg: f64;
let r = random::Random::int(0, 125) as f64;
let rs = self.speed / entity.speed * 100 as f64;
let attack = if r < rs * 0.2 {
dmg = self.base_attack_damage * 1.5;
entity.health_points -= dmg;
AttackResult::CriticalHit(dmg)
} else if r < rs * 0.8 {
dmg = self.base_attack_damage;
entity.health_points -= dmg;
AttackResult::Hit(dmg)
} else if r < rs {
dmg = self.base_attack_damage * 0.5;
entity.health_points -= dmg;
AttackResult::GlancingBlow(dmg)
} else {
AttackResult::Miss
};
if entity.health_points <= 0.0 {
return (attack, Some(vec![Event::PlayerKilled]));
} else {
return (attack, None)
}
}
}
+129
View File
@@ -0,0 +1,129 @@
use async_trait::async_trait;
use rand::prelude::*;
use super::{
engine::{eventcheck, Choice, Event},
entity::{Entity, Enemy, EntityObject},
player::Player,
};
use alloc::{boxed::Box, string::{String, ToString}, vec::Vec, format, borrow::ToOwned};
use crate::{
std::application::{
Application,
Error,
},
std::{
io::{self, println, serial_println, FRAMEGEN, Element},
random,
},
};
pub struct GameLoop;
#[async_trait]
impl Application for GameLoop {
fn new() -> Self {
Self {}
}
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
let mut username: String = io::stdin().await;
username = username.trim().to_string();
let mut player = Player::new(username);
let mut enemy = Enemy::new();
for _ in 0..30 {
match (eventcheck(player.attack_entity(&mut EntityObject::Enemy(&mut enemy)))) {
Choice::A(result) => {
println!("{}", result);
},
Choice::B(event) => {
println!("{}", event);
match event {
Event::PlayerKilled => {
println!(" [!] {} was slain by Enemy\n\n[ You lost! ]", player.username);
break;
}
Event::EntityKilled(entity) => {
println!("\n [!] Enemy was slain by {}\n\n [ You won! ]", player.username);
break;
}
}
}
}
println!("{}", eventcheck(enemy.attack_entity(&mut EntityObject::Player(&mut player))));
println!("[{}\n[{}", player, enemy);
}
FRAMEGEN.lock().render_frame();
let string = String::from(format!(
"┌────────────────────────────┐
{}
{} / {}
└────────────────────────────┘"
, player.username, player.health_points, player.max_health_points));
let mut healthbar = Element::from_str(string);
healthbar.render((1, 1));
let new2 = String::from("[an element]");
let mut new = Element::from_str(new2);
new.render((10, 10));
new.render((10, 15));
new.render((5, 20));
new.render((34, 16));
FRAMEGEN.lock().render_frame();
let fr = FRAMEGEN.lock().get_frame().to_owned();
serial_println!("{}", {
let mut string = String::new();
for row in fr {
let mut r = String::new();
for col in row {
r.push(col);
}
string.push_str(&r);
string.push('\n')
};
string
});
loop {
println!("{}", io::stdchar().await)
}
Ok(())
}
}
fn random() -> u64 {
let mut r = random::Random::int(0, 125) as u64;
r
}
+19
View File
@@ -0,0 +1,19 @@
#[derive(Debug, Clone, Copy)]
pub struct Armour;
#[derive(Debug, Clone, Copy)]
pub struct Weapon;
#[derive(Debug, Clone, Copy)]
pub struct Charm;
#[derive(Debug, Clone, Copy)]
pub struct OtherItem;
#[derive(Debug, Clone, Copy)]
pub enum Item {
Armour(Armour),
Weapon(Weapon),
Charm(Charm),
Other(OtherItem),
}
+6
View File
@@ -0,0 +1,6 @@
pub mod player;
pub mod items;
pub mod entity;
pub mod engine;
pub mod renderer;
pub mod init;
+82
View File
@@ -0,0 +1,82 @@
use super::{
items::{Item, Armour},
entity::{Entity, EntityObject, AttackResult},
engine::Event,
};
use alloc::{string::String, vec::Vec, vec};
use crate::std::random;
pub struct Player {
pub username: String,
pub health_points: f64,
pub max_health_points: f64,
pub base_attack_damage: f64,
pub speed: f64,
pub inventory: [ Item ; 15 ],
pub equipped: [ Item ; 7 ], // helmet, chestplate, leggings, boots, mainhand, offhand, charm
}
impl Player {
pub fn new(username: String) -> Self {
Self {
username,
health_points: 100.0,
max_health_points: 100.0,
base_attack_damage: 10.0,
speed: 100.0,
inventory: [ Item::Armour(Armour {}); 15 ],
equipped: [ Item::Armour(Armour {}); 7 ],
}
}
}
impl core::fmt::Display for Player {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}: {}/{}", self.username, self.health_points, self.max_health_points)
}
}
impl Entity for Player {
fn attack_entity(&mut self, target: &mut EntityObject) -> (AttackResult, Option<Vec<Event>>) {
let mut entity = if let EntityObject::Enemy(enemy) = target {
enemy
} else {
return (AttackResult::FriendlyFire, None);
};
// combat implementation
let dmg: f64;
let r = random::Random::int(0, 125) as f64;
let rs = self.speed / entity.speed * 100 as f64;
let attack = if r < rs * 0.2 {
dmg = self.base_attack_damage * 1.5;
entity.health_points -= dmg;
AttackResult::CriticalHit(dmg)
} else if r < rs * 0.8 {
dmg = self.base_attack_damage;
entity.health_points -= dmg;
AttackResult::Hit(dmg)
} else if r < rs {
dmg = self.base_attack_damage * 0.5;
entity.health_points -= dmg;
AttackResult::GlancingBlow(dmg)
} else {
AttackResult::Miss
};
if entity.health_points <= 0.0 {
return (attack, Some(vec![Event::EntityKilled(entity.clone())]));
} else {
return (attack, None)
}
}
}
+60
View File
@@ -0,0 +1,60 @@
use async_trait::async_trait;
use alloc::{boxed::Box, string::String, vec::Vec};
use crate::{
std::os::OS,
std::io::{Color, write},
println,
std::application::{
Application,
Error,
},
};
pub struct CrystalFetch {}
#[async_trait]
impl Application for CrystalFetch {
fn new() -> Self {
Self {}
}
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
let os = OS.lock().os.clone();
let version = OS.lock().version.clone();
write(format_args!("
────────────────────────────────────────────────────────
_____ _ _ ____ _____
/ ____| | | | |/ __ \\ / ____|
| | _ __ _ _ ___| |_ __ _| | | | | (___
| | | '__| | | / __| __/ _` | | | | |\\___ \\
| |____| | | |_| \\__ \\ || (_| | | |__| |____) |
\\_____|_| \\__, |___/\\__\\__,_|_|\\____/|_____/
__/ |
|___/
"), (Color::Magenta, Color::Black));
println!("
╔═══════════════════════════════
║ OS » {}
║ BUILD » {}
║ RAM » idk
║ Shell » CrystalSH
║ API » CrystalAPI
║ Pkgs » 4
║ Fetch » CrystalFetch
╚═══════════════════════════════
────────────────────────────────────────────────────────
", os, version);
Ok(())
}
}
+6
View File
@@ -0,0 +1,6 @@
pub mod calc;
pub mod rickroll;
pub mod crystalfetch;
pub mod tasks;
pub mod crystal_rpg;
pub mod shell;
+41
View File
@@ -0,0 +1,41 @@
use async_trait::async_trait;
use crate::std::application::{
Application,
Error,
};
use crate::{println};
use alloc::{string::String, boxed::Box, vec::Vec};
pub struct Rickroll {}
#[async_trait]
impl Application for Rickroll {
fn new() -> Self {
Self {}
}
async fn run(&mut self, _args: Vec<String>) -> Result<(), Error> {
println!("
_ _ _____
| \\ | | / ____|
| \\| | _____ _____ _ __ | | __ ___ _ __ _ __ __ _
| . ` |/ _ \\ \\ / / _ \\ '__| | | |_ |/ _ \\| '_ \\| '_ \\ / _` |
| |\\ | __/\\ V / __/ | | |__| | (_) | | | | | | | (_| |
|_| \\_|\\___| \\_/ \\___|_| \\_____|\\___/|_| |_|_| |_|\\__,_|
_______ __ __ ___ ___
/ ____(_) \\ \\ / / | | | |
| | __ ___ _____ \\ \\_/ /__ _ _ | | | |_ __
| | |_ | \\ \\ / / _ \\ \\ / _ \\| | | | | | | | '_ \\
| |__| | |\\ V / __/ | | (_) | |_| | | |__| | |_) |
\\_____|_| \\_/ \\___| |_|\\___/ \\__,_| \\____/| .__/
| |
|_|
");
Ok(())
}
}
+197
View File
@@ -0,0 +1,197 @@
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,
};
use crate::{
print, println,
std::application::{Application, Error},
user::bin::*,
};
lazy_static! {
pub static ref CMD: Mutex<CommandHandler> = Mutex::new(CommandHandler::new());
}
/// boilerplate function
/// may provide other interfacing options later on idk.
pub async fn command_handler() {
eventloop().await;
}
/// this function starts the shell running, the function will loop repeatedly until the command to shutdown
/// TODO: implement shutdown command
pub async fn eventloop() {
println!("running!");
let mut fetch = crystalfetch::CrystalFetch::new();
let string = String::from(" ");
let mut vec: Vec<String> = Vec::new();
vec.push(string);
fetch.run(vec).await.unwrap();
CMD.lock().prompt();
loop {
let string = crate::std::io::stdin().await;
CMD.lock().current.push_str(&string);
match exec().await {
Ok(_) => {
();
}
Err(e) => {
handle_error(e);
}
};
CMD.lock().prompt();
}
}
fn handle_error(e: Error) {}
async fn exec() -> Result<(), Error> {
let mut current = CMD.lock().current.clone();
CMD.lock().history.history.push(current.clone());
current.pop();
CMD.lock().current = String::new();
let (cmd, args) = match CommandHandler::parse_args(current) {
Ok((cmd, args)) => (cmd, args),
Err(_) => {
return Err(Error::EmptyCommand);
}
};
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?;
}
// direct OS functions (not applications)
"echo" => {
println!(
"Crystal: '{}'",
args.into_iter()
.map(|mut s| {
s.push_str(" ");
s
})
.collect::<String>()
)
}
"clear" => {
interrupts::without_interrupts(|| {
crate::std::io::clear();
});
}
"print" => {
use crate::std::os::OS;
let x: String = OS.lock().version.clone();
println!("{}", x);
}
"switch" => {
crate::std::io::switch_mode();
}
"random" => {
use crate::std::random::Random;
let vec = Vec::from(["a", "b", "c", "d", "e", "f"]);
let sel = Random::selection(vec);
println!("{}", sel);
}
"filesystem" => {
use crate::std::io;
io::mkfs();
}
_ => {
return Err(Error::UnknownCommand(
"command not yet implemented".to_string(),
))
}
};
Ok(())
}
pub struct CommandHandler {
current: String,
history: CmdHistory,
}
impl CommandHandler {
pub fn new() -> Self {
let handler = Self {
current: String::new(),
history: CmdHistory {
history: Vec::new(),
},
};
handler
}
pub fn parse_args(command: String) -> Result<(String, Vec<String>), String> {
let temp = command.split(" ").collect::<Vec<&str>>();
let mut args: Vec<String> = Vec::new();
for arg in temp {
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))
}
// this function is activated every time the user presses a key on the keyboard
// it accesses the queue of keys (a static ref in src/tasks/keyboard.rs)
// displays a text prompt for the user to type into.
// this is a separate function so that it can be developed as necessary later on
// TODO: coloured prompt
pub fn prompt(&self) {
print!("\n [ Crystal ] >> ");
}
// this function is run every time the enter key is pressed in the command line mode.
// it detects the command that is being run and then executes it, passing the arguments to it.
}
struct CmdHistory {
history: Vec<String>,
}
+42
View File
@@ -0,0 +1,42 @@
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,
};
use crate::{
applications::*,
std::application::{Application, Error},
std::io::{print, println},
user::bin::*,
};
lazy_static! {
pub static ref CMD: Mutex<Cmd> = Mutex::new(Cmd::new());
}
struct Cmd {}
impl Cmd {
fn new() -> Self {
Self {}
}
}
// [ 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
pub fn init_sh() -> Result<(), String> {
Ok(())
}
+168
View File
@@ -0,0 +1,168 @@
use alloc::{string::String, vec::Vec, boxed::Box};
use crate::std::application::{
Application,
Error
};
use crate::{print, println};
use lazy_static::lazy_static;
use spin::Mutex;
use async_trait::async_trait;
use alloc::{
string::ToString,
borrow::ToOwned,
};
use crate::std::random;
lazy_static! {
static ref TASKS: Mutex<TaskList> = Mutex::new(TaskList::new());
}
pub struct Tasks;
#[async_trait]
impl Application for Tasks {
fn new() -> Self { Self {} }
async fn run(&mut self, args: Vec<String>) -> Result<(), Error> {
if args[0].clone() == String::from("add") {
let content = args[1..].to_owned().into_iter().map(|mut s| {s.push_str(" "); s} ).collect::<String>();
self.add_task(content);
}
if args[0].clone() == String::from("remove") {
let idx = match args[1].to_owned().parse::<usize>() {
Ok(x) => x,
Err(_) => { return Err(Error::CommandFailed(String::from("number must be an integer"))) },
};
self.remove_task(idx);
}
if args[0].clone() == String::from("select") {
let arg2 = args[1].clone();
if arg2 == String::from("random") {
let len = TASKS.lock().tasks.len();
self.select_task(random::Random::int(0, len -1) as i32);
} else if arg2.parse::<u64>().is_ok() {
()
}
}
if args[0].clone() == String::from("priority") {
let idx = TASKS.lock().current;
if idx < 0 {
println!(
"-------------------------------------
no task currently set as priority
-------------------------------------\n"
);
return Ok(())
}
let task = TASKS.lock().tasks[idx as usize].clone();
let content = task.content.clone();
println!(
"-------------------------------------
PRIORITY TASK: {} : {}
-------------------------------------\n",
idx, content
)
}
if args[0].as_str() == "list" {
println!(
"-------------------------------------
Your TODO List:
-------------------------------------\n");
for task in TASKS.lock().tasks.iter() {
let idx = task.taskid;
let content = task.content.clone();
println!(" | Task -> {} \n | {}\n", idx, content);
}
println!("\n-------------------------------------");
}
Ok(())
}
}
impl Tasks {
fn add_task(&mut self, content: String) {
TASKS.lock().add(content);
}
fn remove_task(&self, idx: usize) {
TASKS.lock().remove(idx);
}
fn select_task(&self, idx: i32) {
TASKS.lock().select(idx);
}
}
pub struct TaskList {
current: i32,
tasks: Vec<Task>,
next_idx: usize,
}
impl TaskList {
pub fn new() -> Self {
Self {
current: -1,
tasks: Vec::new(),
next_idx: 1
}
}
pub fn next(&mut self) -> usize {
self.next_idx += 1;
self.next_idx -1
}
pub fn add(&mut self, content: String) -> Result<(), Error> {
let task = Task::new(self.next(), content);
let id = task.taskid.clone();
self.tasks.push(task);
Ok(())
}
pub fn remove(&mut self, id: usize) -> Result<(), Error> {
for (i, task) in self.tasks.clone().iter().enumerate() {
match task.taskid {
id => { self.tasks.remove(i); },
_ => { return Err(Error::CommandFailed(String::from("this task does not exist"))); },
}
};
Ok(())
}
pub fn select(&mut self, idx: i32) -> Result<(), Error> {
self.current = idx;
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct Task {
taskid: usize,
content: String,
}
impl Task {
fn new(id: usize, content: String) -> Self {
Self {
taskid: id,
content,
}
}
}
View File
+2
View File
@@ -0,0 +1,2 @@
pub mod lib;
pub mod bin;