Restructuring
This commit is contained in:
parent
2d9db49fef
commit
c0fe46cf34
@ -1,11 +1,9 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::{Command, types::Content};
|
||||
|
||||
// TODO: Remove this
|
||||
use wasm_bindgen::prelude::*;
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
extern {
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
fn log(s: &str);
|
||||
}
|
@ -1,220 +0,0 @@
|
||||
extern crate console_error_panic_hook;
|
||||
mod types;
|
||||
mod commands;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use types::*;
|
||||
use commands::commands;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
fn log(s: &str);
|
||||
}
|
||||
|
||||
pub struct Flag {
|
||||
pub long: String,
|
||||
pub short: String,
|
||||
pub description: String,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
impl Flag {
|
||||
pub fn new(long: String, short: String, description: String) -> Flag {
|
||||
Flag {
|
||||
long,
|
||||
short,
|
||||
description,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Command {
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub flags: Vec<Rc<Flag>>,
|
||||
function: fn(&mut Console, Vec<String>, Vec<Rc<Flag>>) -> Result<Option<String>, &'static str>,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
pub fn new(name: String, description: String, flags: Vec<Rc<Flag>>, function: fn(&mut Console, Vec<String>, Vec<Rc<Flag>>) -> Result<Option<String>, &'static str>) -> Command {
|
||||
Command {
|
||||
name,
|
||||
description,
|
||||
flags,
|
||||
function,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_flags(&self, args: Vec<String>) -> (Vec<Rc<Flag>>, Vec<String>) {
|
||||
let mut flags: Vec<Rc<Flag>> = Vec::new();
|
||||
let mut other = Vec::new();
|
||||
|
||||
for arg in args {
|
||||
if arg.starts_with("--") {
|
||||
let f = match self.flags.iter().find(|f| arg[2..] == f.long) {
|
||||
Some(f) => Rc::clone(f),
|
||||
None => continue,
|
||||
};
|
||||
flags.push(f);
|
||||
} else if arg.starts_with("-") {
|
||||
let f = match self.flags.iter().find(|f| arg[1..] == f.short) {
|
||||
Some(f) => Rc::clone(f),
|
||||
None => continue,
|
||||
};
|
||||
flags.push(f);
|
||||
} else {
|
||||
other.push(arg);
|
||||
}
|
||||
}
|
||||
|
||||
(flags, other)
|
||||
}
|
||||
|
||||
pub fn execute(&self, console: &mut Console, args: Vec<String>) -> Result<Option<String>, &'static str> {
|
||||
let (flags, args) = self.parse_flags(args.clone());
|
||||
(self.function)(console, args, flags)
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct Console {
|
||||
root: Rc<RefCell<Directory>>,
|
||||
pwd: RefCell<Vec<Rc<RefCell<Directory>>>>,
|
||||
last_commands: Vec<String>,
|
||||
available_commands: Vec<Rc<Command>>,
|
||||
output: Vec<String>,
|
||||
}
|
||||
|
||||
impl Console {
|
||||
fn get_current_dir(&self) -> Rc<RefCell<Directory>> {
|
||||
match self.pwd.borrow().last() {
|
||||
Some(dir) => Rc::clone(dir),
|
||||
None => Rc::clone(&self.root),
|
||||
}
|
||||
}
|
||||
|
||||
fn cd(&mut self, path: String, skip_last_n: Option<usize>) -> Result<(), &'static str> {
|
||||
let segments = PathSegment::parse_path_segment(path);
|
||||
let mut current = self.get_current_dir();
|
||||
|
||||
let mut index = 0;
|
||||
let break_index = match skip_last_n {
|
||||
Some(n) => segments.len() - n as usize,
|
||||
None => segments.len(),
|
||||
};
|
||||
|
||||
for segment in segments {
|
||||
if index >= break_index {
|
||||
break;
|
||||
} else {
|
||||
index += 1;
|
||||
}
|
||||
|
||||
match segment {
|
||||
PathSegment::Root => {
|
||||
self.pwd.borrow_mut().clear();
|
||||
continue;
|
||||
},
|
||||
PathSegment::This => continue,
|
||||
PathSegment::Parent => {
|
||||
if self.pwd.borrow().len() == 0 {
|
||||
return Err("Cannot go above root directory");
|
||||
}
|
||||
self.pwd.borrow_mut().pop();
|
||||
continue;
|
||||
},
|
||||
PathSegment::SubDirectory(name) => {
|
||||
let dir = match current.borrow().get_dir(name) {
|
||||
Some(dir) => dir,
|
||||
None => return Err("Directory does not exist"),
|
||||
};
|
||||
self.pwd.borrow_mut().push(dir);
|
||||
},
|
||||
}
|
||||
|
||||
current = self.get_current_dir();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Function to get a directory from a path
|
||||
// the PWD should be unchanged after this function
|
||||
fn virtual_cd(&mut self, path: String, skip_last_n: Option<usize>) -> Result<Rc<RefCell<Directory>>, &'static str> {
|
||||
let pwd = self.pwd.borrow().clone();
|
||||
|
||||
match self.cd(path, skip_last_n) {
|
||||
Ok(_) => (),
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
let result = self.get_current_dir();
|
||||
self.pwd.replace(pwd);
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn execute_inner(&mut self, command: String) -> Option<String> {
|
||||
let mut args: Vec<String> = command.split(" ").map(|s| s.to_string()).collect();
|
||||
|
||||
let command = match args.first() {
|
||||
Some(command) => command,
|
||||
None => return Some("No command entered".to_string()),
|
||||
};
|
||||
|
||||
let command = match self.available_commands.iter().find(|c| c.name == *command) {
|
||||
Some(command) => command.clone(),
|
||||
None => return Some(format!("Command {} not found", command)),
|
||||
};
|
||||
|
||||
args.remove(0);
|
||||
|
||||
let result = command.execute(self, args);
|
||||
|
||||
match result {
|
||||
Ok(result) => {
|
||||
self.last_commands.push(command.name.clone());
|
||||
result
|
||||
},
|
||||
Err(e) => Some(e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl Console {
|
||||
pub fn new() -> Console {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let root = Rc::new(RefCell::new(Directory::new("".to_string(), "".to_string())));
|
||||
|
||||
let console = Console {
|
||||
root,
|
||||
pwd: RefCell::new(Vec::new()),
|
||||
output: Vec::new(),
|
||||
last_commands: Vec::new(),
|
||||
available_commands: commands(),
|
||||
};
|
||||
|
||||
console
|
||||
}
|
||||
|
||||
pub fn get_output(&self) -> Vec<String> {
|
||||
self.output.clone()
|
||||
}
|
||||
|
||||
pub fn get_last_commands(&self) -> Vec<String> {
|
||||
self.last_commands.clone()
|
||||
}
|
||||
|
||||
pub fn execute(&mut self, command: String) -> Option<String> {
|
||||
self.output.push(format!("$ {}", command));
|
||||
self.last_commands.push(command.clone());
|
||||
let result = self.execute_inner(command);
|
||||
if result.is_some() {
|
||||
self.output.push(result.clone().unwrap());
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
222
src/lib.rs
222
src/lib.rs
@ -1 +1,221 @@
|
||||
mod console;
|
||||
extern crate console_error_panic_hook;
|
||||
mod types;
|
||||
mod commands;
|
||||
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use types::*;
|
||||
use commands::commands;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
fn log(s: &str);
|
||||
}
|
||||
|
||||
pub struct Flag {
|
||||
pub long: String,
|
||||
pub short: String,
|
||||
pub description: String,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
impl Flag {
|
||||
pub fn new(long: String, short: String, description: String) -> Flag {
|
||||
Flag {
|
||||
long,
|
||||
short,
|
||||
description,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Command {
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub flags: Vec<Rc<Flag>>,
|
||||
function: fn(&mut Console, Vec<String>, Vec<Rc<Flag>>) -> Result<Option<String>, &'static str>,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
pub fn new(name: String, description: String, flags: Vec<Rc<Flag>>, function: fn(&mut Console, Vec<String>, Vec<Rc<Flag>>) -> Result<Option<String>, &'static str>) -> Command {
|
||||
Command {
|
||||
name,
|
||||
description,
|
||||
flags,
|
||||
function,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_flags(&self, args: Vec<String>) -> (Vec<Rc<Flag>>, Vec<String>) {
|
||||
let mut flags: Vec<Rc<Flag>> = Vec::new();
|
||||
let mut other = Vec::new();
|
||||
|
||||
for arg in args {
|
||||
if arg.starts_with("--") {
|
||||
let f = match self.flags.iter().find(|f| arg[2..] == f.long) {
|
||||
Some(f) => Rc::clone(f),
|
||||
None => continue,
|
||||
};
|
||||
flags.push(f);
|
||||
} else if arg.starts_with("-") {
|
||||
let f = match self.flags.iter().find(|f| arg[1..] == f.short) {
|
||||
Some(f) => Rc::clone(f),
|
||||
None => continue,
|
||||
};
|
||||
flags.push(f);
|
||||
} else {
|
||||
other.push(arg);
|
||||
}
|
||||
}
|
||||
|
||||
(flags, other)
|
||||
}
|
||||
|
||||
pub fn execute(&self, console: &mut Console, args: Vec<String>) -> Result<Option<String>, &'static str> {
|
||||
let (flags, args) = self.parse_flags(args.clone());
|
||||
(self.function)(console, args, flags)
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct Console {
|
||||
root: Rc<RefCell<Directory>>,
|
||||
pwd: RefCell<Vec<Rc<RefCell<Directory>>>>,
|
||||
last_commands: Vec<String>,
|
||||
available_commands: Vec<Rc<Command>>,
|
||||
output: Vec<String>,
|
||||
}
|
||||
|
||||
impl Console {
|
||||
fn get_current_dir(&self) -> Rc<RefCell<Directory>> {
|
||||
match self.pwd.borrow().last() {
|
||||
Some(dir) => Rc::clone(dir),
|
||||
None => Rc::clone(&self.root),
|
||||
}
|
||||
}
|
||||
|
||||
fn cd(&mut self, path: String, skip_last_n: Option<usize>) -> Result<(), &'static str> {
|
||||
let segments = PathSegment::parse_path_segment(path);
|
||||
let mut current = self.get_current_dir();
|
||||
|
||||
let mut index = 0;
|
||||
let break_index = match skip_last_n {
|
||||
Some(n) => segments.len() - n as usize,
|
||||
None => segments.len(),
|
||||
};
|
||||
|
||||
for segment in segments {
|
||||
if index >= break_index {
|
||||
break;
|
||||
} else {
|
||||
index += 1;
|
||||
}
|
||||
|
||||
match segment {
|
||||
PathSegment::Root => {
|
||||
self.pwd.borrow_mut().clear();
|
||||
continue;
|
||||
},
|
||||
PathSegment::This => continue,
|
||||
PathSegment::Parent => {
|
||||
if self.pwd.borrow().len() == 0 {
|
||||
return Err("Cannot go above root directory");
|
||||
}
|
||||
self.pwd.borrow_mut().pop();
|
||||
continue;
|
||||
},
|
||||
PathSegment::SubDirectory(name) => {
|
||||
let dir = match current.borrow().get_dir(name) {
|
||||
Some(dir) => dir,
|
||||
None => return Err("Directory does not exist"),
|
||||
};
|
||||
self.pwd.borrow_mut().push(dir);
|
||||
},
|
||||
}
|
||||
|
||||
current = self.get_current_dir();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Function to get a directory from a path
|
||||
// the PWD should be unchanged after this function
|
||||
fn virtual_cd(&mut self, path: String, skip_last_n: Option<usize>) -> Result<Rc<RefCell<Directory>>, &'static str> {
|
||||
let pwd = self.pwd.borrow().clone();
|
||||
|
||||
match self.cd(path, skip_last_n) {
|
||||
Ok(_) => (),
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
let result = self.get_current_dir();
|
||||
self.pwd.replace(pwd);
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn execute_inner(&mut self, command: String) -> Option<String> {
|
||||
let mut args: Vec<String> = command.split(" ").map(|s| s.to_string()).collect();
|
||||
|
||||
let command = match args.first() {
|
||||
Some(command) => command,
|
||||
None => return Some("No command entered".to_string()),
|
||||
};
|
||||
|
||||
let command = match self.available_commands.iter().find(|c| c.name == *command) {
|
||||
Some(command) => command.clone(),
|
||||
None => return Some(format!("Command {} not found", command)),
|
||||
};
|
||||
|
||||
args.remove(0);
|
||||
|
||||
let result = command.execute(self, args);
|
||||
|
||||
match result {
|
||||
Ok(result) => {
|
||||
self.last_commands.push(command.name.clone());
|
||||
result
|
||||
},
|
||||
Err(e) => Some(e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl Console {
|
||||
pub fn new() -> Console {
|
||||
// TODO remove in release
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let root = Rc::new(RefCell::new(Directory::new("".to_string(), "".to_string())));
|
||||
|
||||
let console = Console {
|
||||
root,
|
||||
pwd: RefCell::new(Vec::new()),
|
||||
output: Vec::new(),
|
||||
last_commands: Vec::new(),
|
||||
available_commands: commands(),
|
||||
};
|
||||
|
||||
console
|
||||
}
|
||||
|
||||
pub fn get_output(&self) -> Vec<String> {
|
||||
self.output.clone()
|
||||
}
|
||||
|
||||
pub fn get_last_commands(&self) -> Vec<String> {
|
||||
self.last_commands.clone()
|
||||
}
|
||||
|
||||
pub fn execute(&mut self, command: String) -> Option<String> {
|
||||
self.output.push(format!("$ {}", command));
|
||||
self.last_commands.push(command.clone());
|
||||
let result = self.execute_inner(command);
|
||||
if result.is_some() {
|
||||
self.output.push(result.clone().unwrap());
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
// TODO: Remove this
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
extern {
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
fn log(s: &str);
|
||||
}
|
Loading…
Reference in New Issue
Block a user