So... a lot more works now

This commit is contained in:
Daniel Kluge 2024-01-03 12:29:39 +01:00
parent a5e3039f80
commit 798582ae7d
3 changed files with 138 additions and 72 deletions

View File

@ -2,6 +2,14 @@ use std::rc::Rc;
use super::{Command, types::Content}; 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<Rc<Command>> { pub fn commands() -> Vec<Rc<Command>> {
let mut available_commands: Vec<Rc<Command>> = Vec::new(); let mut available_commands: Vec<Rc<Command>> = Vec::new();
@ -34,12 +42,7 @@ pub fn commands() -> Vec<Rc<Command>> {
"Prints the args".to_string(), "Prints the args".to_string(),
Vec::new(), Vec::new(),
|_console, args, _flags| { |_console, args, _flags| {
let mut output = String::new(); Ok(Some(args.join(" ")))
for arg in args {
output.push_str(&format!("{} ", arg));
}
Ok(Some(output))
}, },
))); )));
@ -53,6 +56,9 @@ pub fn commands() -> Vec<Rc<Command>> {
return Err("pwd does not take any arguments"); 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())) Ok(Some(console.get_current_dir().borrow().get_path()))
}, },
))); )));
@ -67,7 +73,7 @@ pub fn commands() -> Vec<Rc<Command>> {
return Err("Only the path must be specified!"); return Err("Only the path must be specified!");
} }
match console.cd(args[0].clone()) { match console.cd(args[0].clone(), None) {
Ok(_) => Ok(None), Ok(_) => Ok(None),
Err(e) => Err(e), Err(e) => Err(e),
} }
@ -82,24 +88,30 @@ pub fn commands() -> Vec<Rc<Command>> {
Rc::new(super::Flag::new("list".to_string(), "l".to_string(), "Print contents in a list".to_string())), Rc::new(super::Flag::new("list".to_string(), "l".to_string(), "Print contents in a list".to_string())),
], ],
|console, args, flags| { |console, args, flags| {
if args.len() > 0 { if args.len() > 1 {
return Err("ls does not take any arguments"); 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" ) { let seperator = match flags.iter().find(|f| f.long == "list" ) {
Some(_) => "\n", Some(_) => "\n",
None => "\t", None => "\t",
}; };
let mut output = String::new(); 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)); 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)); output.push_str(&format!("{}{}", file.borrow().get_name(), seperator));
} }
@ -114,15 +126,15 @@ pub fn commands() -> Vec<Rc<Command>> {
Vec::new(), Vec::new(),
|console, args, _flags| { |console, args, _flags| {
if args.len() != 1 { if args.len() != 1 {
return Err("Only the name must be specified!"); return Err("Only the path must be specified!");
} }
// TODO let dir = match console.virtual_cd(args[0].clone(), Some(1)) {
// virtual_cd Ok(dir) => dir,
// Get the directory name from the path Err(e) => return Err(e),
};
let current_dir = console.get_current_dir(); let result = match dir.borrow_mut().mkdir(args[0].clone()) {
let result = match current_dir.borrow_mut().mkdir(args[0].clone()) {
Ok(_) => Ok(None), Ok(_) => Ok(None),
Err(e) => Err(e), Err(e) => Err(e),
}; };
@ -138,15 +150,15 @@ pub fn commands() -> Vec<Rc<Command>> {
Vec::new(), Vec::new(),
|console, args, _flags| { |console, args, _flags| {
if args.len() != 1 { if args.len() != 1 {
return Err("Only the name must be specified!"); return Err("Only the path must be specified!");
} }
// TODO let dir = match console.virtual_cd(args[0].clone(), Some(1)) {
// virtual_cd Ok(dir) => dir,
// Get the directory name from the path Err(e) => return Err(e),
};
let current_dir = console.get_current_dir(); let result = match dir.borrow_mut().touch(args[0].clone()) {
let result = match current_dir.borrow_mut().touch(args[0].clone()) {
Ok(_) => Ok(None), Ok(_) => Ok(None),
Err(e) => Err(e), Err(e) => Err(e),
}; };
@ -162,15 +174,15 @@ pub fn commands() -> Vec<Rc<Command>> {
Vec::new(), Vec::new(),
|console, args, _flags| { |console, args, _flags| {
if args.len() != 1 { if args.len() != 1 {
return Err("Only the name must be specified!"); return Err("Only the file must be specified!");
} }
// TODO let dir = match console.virtual_cd(args[0].clone(), Some(1)) {
// virtual_cd Ok(dir) => dir,
// Get the directory name from the path Err(e) => return Err(e),
};
let current_dir = console.get_current_dir(); let file = match dir.borrow().get_file(args[0].clone()) {
let file = match current_dir.borrow().get_file(args[0].clone()) {
Some(file) => file, Some(file) => file,
None => return Err("File not found"), None => return Err("File not found"),
}; };
@ -185,23 +197,32 @@ pub fn commands() -> Vec<Rc<Command>> {
Rc::new(Command::new( Rc::new(Command::new(
"rm".to_string(), "rm".to_string(),
"Removes a file or directory".to_string(), "Removes a file or directory".to_string(),
Vec::new(), vec![
|console, args, _flags| { 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 { if args.len() != 1 {
return Err("Only the name must be specified!"); return Err("Only the name must be specified!");
} }
// TODO let dir = match console.virtual_cd(args[0].clone(), Some(1)) {
// virtual_cd Ok(dir) => dir,
// Get the directory name from the path Err(e) => return Err(e),
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),
}; };
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<Command>> {
Rc::new(super::Flag::new("append".to_string(), "a".to_string(), "Append to the file".to_string())), Rc::new(super::Flag::new("append".to_string(), "a".to_string(), "Append to the file".to_string())),
], ],
|console, args, flags| { |console, args, flags| {
// TODO if args.len() < 2 {
// virtual_cd return Err("Path and content must be specified!");
// Get the directory name from the path }
let current_dir = console.get_current_dir(); log(format!("Args: {:?}", args).as_str());
let file = match current_dir.borrow().get_file(args[0].clone()) {
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, Some(file) => file,
None => return Err("File not found"), None => return Err("File not found"),
}; };
if flags.iter().find(|f| f.long == "append" ).is_some() { 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); return Ok(None);
} else { } else {
file.borrow_mut().write(args[1].clone()); file.borrow_mut().write(args[1..].join(" "));
Ok(None) Ok(None)
} }

View File

@ -6,6 +6,12 @@ use types::*;
use commands::commands; use commands::commands;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
pub struct Flag { pub struct Flag {
pub long: String, pub long: String,
pub short: 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<usize>) -> Result<(), &'static str> {
let segments = PathSegment::parse_path_segment(path); let segments = PathSegment::parse_path_segment(path);
let mut current = self.get_current_dir(); 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 { for segment in segments {
if index >= break_index {
break;
} else {
index += 1;
}
match segment { match segment {
PathSegment::Root => { PathSegment::Root => {
self.pwd.borrow_mut().clear(); self.pwd.borrow_mut().clear();
@ -123,12 +141,22 @@ impl Console {
// Function to get a directory from a path // Function to get a directory from a path
// the PWD should be unchanged after this function // the PWD should be unchanged after this function
/*fn virtual_cd(&self, path: String) -> Result<Box<&mut Directory>, &'static str> { 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> { fn execute_inner(&mut self, command: String) -> Option<String> {
let mut args: Vec<String> = command.split(" ").map(|s| s.to_string()).collect(); let mut args: Vec<String> = command.split(" ").map(|s| s.to_string()).collect();
let command = match args.first() { let command = match args.first() {
Some(command) => command, Some(command) => command,
None => return Some("No command entered".to_string()), None => return Some("No command entered".to_string()),
@ -156,7 +184,7 @@ impl Console {
#[wasm_bindgen] #[wasm_bindgen]
impl Console { impl Console {
pub fn new() -> 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 { let console = Console {
root, root,

View File

@ -1,5 +1,12 @@
use std::{cell::RefCell, rc::Rc}; 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 { pub trait Content {
fn get_name(&self) -> String; fn get_name(&self) -> String;
@ -7,7 +14,7 @@ pub trait Content {
} }
pub struct File { pub struct File {
path: String, parent_path: String,
name: String, name: String,
content: String, content: String,
} }
@ -18,25 +25,29 @@ impl Content for File {
} }
fn get_path(&self) -> String { fn get_path(&self) -> String {
self.path.clone() if self.parent_path == "/" {
format!("/{}", &self.name)
} else {
format!("{}/{}", &self.parent_path, &self.name)
}
} }
} }
#[allow(unused)] #[allow(unused)]
impl File { impl File {
pub fn new(name: String, content: String, path: String) -> File { pub fn new(name: String, content: String, parent_path: String) -> File {
File { File {
name, name,
content, content,
path, parent_path,
} }
} }
pub fn empty_new(name: String, path: String) -> File { pub fn empty_new(name: String, parent_path: String) -> File {
File { File {
name, name,
content: String::new(), content: String::new(),
path, parent_path,
} }
} }
@ -61,7 +72,7 @@ pub struct Directory {
name: String, name: String,
files: RefCell<Vec<Rc<RefCell<File>>>>, files: RefCell<Vec<Rc<RefCell<File>>>>,
subdirs: RefCell<Vec<Rc<RefCell<Directory>>>>, subdirs: RefCell<Vec<Rc<RefCell<Directory>>>>,
path: String, pub parent_path: String,
} }
impl Content for Directory { impl Content for Directory {
@ -70,25 +81,25 @@ impl Content for Directory {
} }
fn get_path(&self) -> String { fn get_path(&self) -> String {
self.path.clone() if self.parent_path == "/" {
format!("/{}", &self.name)
} else {
format!("{}/{}", &self.parent_path, &self.name)
}
} }
} }
#[allow(unused)] #[allow(unused)]
impl Directory { impl Directory {
pub fn new(name: String, path: String) -> Directory { pub fn new(name: String, parent_path: String) -> Directory {
Directory { Directory {
name, name,
files: RefCell::new(Vec::new()), files: RefCell::new(Vec::new()),
subdirs: 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>{ pub fn add_file(&mut self, file: File) -> Result<(), &'static str>{
if self.get_dir(file.name.clone()).is_some() { if self.get_dir(file.name.clone()).is_some() {
return Err("File already exists"); return Err("File already exists");
@ -121,7 +132,7 @@ impl Directory {
return Err("Directory name cannot contain spraces, '/' or '\\'"); 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()); self.subdirs.borrow_mut().push(dir.clone());
Ok(dir) Ok(dir)
} }
@ -206,7 +217,7 @@ impl Directory {
return Err("File name cannot contain spraces, '/' or '\\'"); 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()); self.files.borrow_mut().push(file.clone());
Ok(file) Ok(file)
} }
@ -219,7 +230,7 @@ impl Directory {
return Err("File name cannot contain spraces, '/' or '\\'"); 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()); self.files.borrow_mut().push(file.clone());
Ok(file) Ok(file)
} }