diff --git a/src/console/commands.rs b/src/console/commands.rs index e24cadf..2d0556c 100644 --- a/src/console/commands.rs +++ b/src/console/commands.rs @@ -2,6 +2,14 @@ use std::rc::Rc; use super::{Command, types::Content}; +// TODO: Remove this +use wasm_bindgen::prelude::*; +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_namespace = console)] + fn log(s: &str); +} + pub fn commands() -> Vec> { let mut available_commands: Vec> = Vec::new(); @@ -34,12 +42,7 @@ pub fn commands() -> Vec> { "Prints the args".to_string(), Vec::new(), |_console, args, _flags| { - let mut output = String::new(); - for arg in args { - output.push_str(&format!("{} ", arg)); - } - - Ok(Some(output)) + Ok(Some(args.join(" "))) }, ))); @@ -53,6 +56,9 @@ pub fn commands() -> Vec> { return Err("pwd does not take any arguments"); } + log(console.get_current_dir().borrow().get_name().as_str()); + log(console.get_current_dir().borrow().get_path().as_str()); + Ok(Some(console.get_current_dir().borrow().get_path())) }, ))); @@ -67,7 +73,7 @@ pub fn commands() -> Vec> { return Err("Only the path must be specified!"); } - match console.cd(args[0].clone()) { + match console.cd(args[0].clone(), None) { Ok(_) => Ok(None), Err(e) => Err(e), } @@ -82,24 +88,30 @@ pub fn commands() -> Vec> { Rc::new(super::Flag::new("list".to_string(), "l".to_string(), "Print contents in a list".to_string())), ], |console, args, flags| { - if args.len() > 0 { - return Err("ls does not take any arguments"); + if args.len() > 1 { + return Err("ls does not take any arguments but a path"); } - // TODO - // Virtual cd to read the contents there - let seperator = match flags.iter().find(|f| f.long == "list" ) { Some(_) => "\n", None => "\t", }; let mut output = String::new(); - let current_dir = console.get_current_dir(); - for dir in current_dir.borrow().get_subdirs() { + + let base = if args.len() == 0 { + console.get_current_dir() + } else { + match console.virtual_cd(args[0].clone(), Some(1)) { + Ok(dir) => dir, + Err(e) => return Err(e), + } + }; + + for dir in base.borrow().get_subdirs() { output.push_str(&format!("{}{}", dir.borrow().get_name(), seperator)); } - for file in current_dir.borrow().get_files() { + for file in base.borrow().get_files() { output.push_str(&format!("{}{}", file.borrow().get_name(), seperator)); } @@ -114,15 +126,15 @@ pub fn commands() -> Vec> { Vec::new(), |console, args, _flags| { if args.len() != 1 { - return Err("Only the name must be specified!"); + return Err("Only the path must be specified!"); } - // TODO - // virtual_cd - // Get the directory name from the path + let dir = match console.virtual_cd(args[0].clone(), Some(1)) { + Ok(dir) => dir, + Err(e) => return Err(e), + }; - let current_dir = console.get_current_dir(); - let result = match current_dir.borrow_mut().mkdir(args[0].clone()) { + let result = match dir.borrow_mut().mkdir(args[0].clone()) { Ok(_) => Ok(None), Err(e) => Err(e), }; @@ -138,15 +150,15 @@ pub fn commands() -> Vec> { Vec::new(), |console, args, _flags| { if args.len() != 1 { - return Err("Only the name must be specified!"); + return Err("Only the path must be specified!"); } - // TODO - // virtual_cd - // Get the directory name from the path + let dir = match console.virtual_cd(args[0].clone(), Some(1)) { + Ok(dir) => dir, + Err(e) => return Err(e), + }; - let current_dir = console.get_current_dir(); - let result = match current_dir.borrow_mut().touch(args[0].clone()) { + let result = match dir.borrow_mut().touch(args[0].clone()) { Ok(_) => Ok(None), Err(e) => Err(e), }; @@ -162,15 +174,15 @@ pub fn commands() -> Vec> { Vec::new(), |console, args, _flags| { if args.len() != 1 { - return Err("Only the name must be specified!"); + return Err("Only the file must be specified!"); } - // TODO - // virtual_cd - // Get the directory name from the path + let dir = match console.virtual_cd(args[0].clone(), Some(1)) { + Ok(dir) => dir, + Err(e) => return Err(e), + }; - let current_dir = console.get_current_dir(); - let file = match current_dir.borrow().get_file(args[0].clone()) { + let file = match dir.borrow().get_file(args[0].clone()) { Some(file) => file, None => return Err("File not found"), }; @@ -185,23 +197,32 @@ pub fn commands() -> Vec> { Rc::new(Command::new( "rm".to_string(), "Removes a file or directory".to_string(), - Vec::new(), - |console, args, _flags| { + vec![ + Rc::new(super::Flag::new("recursive".to_string(), "r".to_string(), "Remove directories and their contents recursively".to_string())), + ], + |console, args, flags| { if args.len() != 1 { return Err("Only the name must be specified!"); } - // TODO - // virtual_cd - // Get the directory name from the path - - let current_dir = console.get_current_dir(); - let result = match current_dir.borrow_mut().remove_file(args[0].clone()) { - Ok(_) => Ok(None), - Err(e) => Err(e), + let dir = match console.virtual_cd(args[0].clone(), Some(1)) { + Ok(dir) => dir, + Err(e) => return Err(e), }; - result + _ = match dir.borrow_mut().remove_file(args[0].clone()) { + Ok(_) => return Ok(None), + Err(_) => "", + }; + + if flags.iter().find(|f| f.long == "recursive" ).is_some() { + match dir.borrow_mut().remove_dir(args[0].clone()) { + Ok(_) => return Ok(None), + Err(e) => return Err(e), + }; + } else { + return Err("File could not be found!"); + } }, ))); @@ -214,21 +235,27 @@ pub fn commands() -> Vec> { Rc::new(super::Flag::new("append".to_string(), "a".to_string(), "Append to the file".to_string())), ], |console, args, flags| { - // TODO - // virtual_cd - // Get the directory name from the path + if args.len() < 2 { + return Err("Path and content must be specified!"); + } - let current_dir = console.get_current_dir(); - let file = match current_dir.borrow().get_file(args[0].clone()) { + log(format!("Args: {:?}", args).as_str()); + + let dir = match console.virtual_cd(args[0].clone(), Some(1)) { + Ok(dir) => dir, + Err(e) => return Err(e), + }; + + let file = match dir.borrow().get_file(args[0].clone()) { Some(file) => file, None => return Err("File not found"), }; if flags.iter().find(|f| f.long == "append" ).is_some() { - file.borrow_mut().append(args[1].clone()); + file.borrow_mut().append(args[1..].join(" ")); return Ok(None); } else { - file.borrow_mut().write(args[1].clone()); + file.borrow_mut().write(args[1..].join(" ")); Ok(None) } diff --git a/src/console/mod.rs b/src/console/mod.rs index 9197b24..eef5380 100644 --- a/src/console/mod.rs +++ b/src/console/mod.rs @@ -6,6 +6,12 @@ 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, @@ -88,11 +94,23 @@ impl Console { } } - fn cd(&mut self, path: String) -> Result<(), &'static str> { + fn cd(&mut self, path: String, skip_last_n: Option) -> 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(); @@ -123,12 +141,22 @@ impl Console { // Function to get a directory from a path // the PWD should be unchanged after this function - /*fn virtual_cd(&self, path: String) -> Result, &'static str> { + fn virtual_cd(&mut self, path: String, skip_last_n: Option) -> Result>, &'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 { let mut args: Vec = command.split(" ").map(|s| s.to_string()).collect(); + let command = match args.first() { Some(command) => command, None => return Some("No command entered".to_string()), @@ -156,7 +184,7 @@ impl Console { #[wasm_bindgen] impl Console { pub fn new() -> Console { - let root = Rc::new(RefCell::new(Directory::new("".to_string(), "/".to_string()))); + let root = Rc::new(RefCell::new(Directory::new("".to_string(), "".to_string()))); let console = Console { root, diff --git a/src/console/types.rs b/src/console/types.rs index d4a1a15..3a69c30 100644 --- a/src/console/types.rs +++ b/src/console/types.rs @@ -1,5 +1,12 @@ use std::{cell::RefCell, rc::Rc}; +// TODO: Remove this +use wasm_bindgen::prelude::*; +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_namespace = console)] + fn log(s: &str); +} pub trait Content { fn get_name(&self) -> String; @@ -7,7 +14,7 @@ pub trait Content { } pub struct File { - path: String, + parent_path: String, name: String, content: String, } @@ -18,25 +25,29 @@ impl Content for File { } fn get_path(&self) -> String { - self.path.clone() + if self.parent_path == "/" { + format!("/{}", &self.name) + } else { + format!("{}/{}", &self.parent_path, &self.name) + } } } #[allow(unused)] impl File { - pub fn new(name: String, content: String, path: String) -> File { + pub fn new(name: String, content: String, parent_path: String) -> File { File { name, content, - path, + parent_path, } } - pub fn empty_new(name: String, path: String) -> File { + pub fn empty_new(name: String, parent_path: String) -> File { File { name, content: String::new(), - path, + parent_path, } } @@ -61,7 +72,7 @@ pub struct Directory { name: String, files: RefCell>>>, subdirs: RefCell>>>, - path: String, + pub parent_path: String, } impl Content for Directory { @@ -70,25 +81,25 @@ impl Content for Directory { } fn get_path(&self) -> String { - self.path.clone() + if self.parent_path == "/" { + format!("/{}", &self.name) + } else { + format!("{}/{}", &self.parent_path, &self.name) + } } } #[allow(unused)] impl Directory { - pub fn new(name: String, path: String) -> Directory { + pub fn new(name: String, parent_path: String) -> Directory { Directory { name, files: RefCell::new(Vec::new()), subdirs: RefCell::new(Vec::new()), - path, + parent_path, } } - pub fn path(&self) -> String { - self.path.clone() + "/" + &self.name - } - pub fn add_file(&mut self, file: File) -> Result<(), &'static str>{ if self.get_dir(file.name.clone()).is_some() { return Err("File already exists"); @@ -121,7 +132,7 @@ impl Directory { return Err("Directory name cannot contain spraces, '/' or '\\'"); } - let dir = Rc::new(RefCell::new(Directory::new(name, self.path()))); + let dir = Rc::new(RefCell::new(Directory::new(name, self.get_path()))); self.subdirs.borrow_mut().push(dir.clone()); Ok(dir) } @@ -206,7 +217,7 @@ impl Directory { return Err("File name cannot contain spraces, '/' or '\\'"); } - let file = Rc::new(RefCell::new(File::empty_new(name, self.path.clone()))); + let file = Rc::new(RefCell::new(File::empty_new(name, self.get_path()))); self.files.borrow_mut().push(file.clone()); Ok(file) } @@ -219,7 +230,7 @@ impl Directory { return Err("File name cannot contain spraces, '/' or '\\'"); } - let file = Rc::new(RefCell::new(File::new(name, content, self.path()))); + let file = Rc::new(RefCell::new(File::new(name, content, self.get_path()))); self.files.borrow_mut().push(file.clone()); Ok(file) }