feat(ash): rework command handling

This commit is contained in:
user0-07161 2025-09-10 17:58:27 +02:00
parent 4c6ac174ff
commit 6d93a1d4f6
5 changed files with 79 additions and 31 deletions

View file

@ -1,53 +1,51 @@
use boxutils::commands::Command;
use std::env;
use std::io::{self, ErrorKind, Write};
use std::path::Path;
use std::process::Command as stdCommand;
use std::io::{self, Write};
use std::process;
use crate::built_in::{Action, run_if_exists};
pub struct Ash;
impl Command for Ash {
fn execute(&self) {
let mut path = env::current_dir().unwrap().display().to_string();
loop {
let path = env::current_dir();
let userchar = if boxutils::cross::user::is_admin() {
'#'
} else {
'$'
};
print!("{} {} ", path.expect("unknown").display(), userchar);
print!("{} {} ", path.clone(), userchar);
let _ = io::stdout().flush();
let mut input = String::new();
io::stdin().read_line(&mut input).unwrap();
let mut full_cmd = input.trim().split_whitespace();
let command = full_cmd.next().unwrap();
let mut arguments = full_cmd;
match command {
"exit" => return,
"cd" => {
let new_path = arguments.next();
let new_path = Path::new(new_path.unwrap());
let _ = env::set_current_dir(&new_path).is_ok();
let command = full_cmd.next().unwrap_or(" ");
let arguments: Vec<&str> = full_cmd.collect();
if let Some(action) = run_if_exists(command.to_string(), arguments.clone()) {
match action {
Action::Exit => {
break;
}
command => {
let out = stdCommand::new(command).args(arguments).spawn();
Action::ChangeDirectory(directory) => {
path = directory;
env::set_current_dir(&path).unwrap();
}
}
} else {
let out = process::Command::new(command)
.args(arguments.clone())
.spawn();
match out {
Ok(mut out) => {
let _ = out.wait();
}
Err(err) => match err.kind() {
ErrorKind::NotFound => {
eprintln!("ash: {}: not found", command);
}
ErrorKind::PermissionDenied => {
eprintln!("ash: {}: permission denied", command);
}
_ => {
eprintln!("ash: uncaught error: {}", err);
}
},
}
Err(err) => println!("{:?}", err),
}
}
}

9
shell/src/built_in/cd.rs Normal file
View file

@ -0,0 +1,9 @@
use crate::built_in::Action;
pub fn cd(arguments: Vec<&str>) -> Action {
if arguments.len() < 1 {
panic!("cd expects **one** argument");
}
Action::ChangeDirectory(arguments[0].to_owned().clone())
}

View file

@ -0,0 +1,5 @@
use crate::built_in::Action;
pub fn exit(_: Vec<&str>) -> Action {
Action::Exit
}

35
shell/src/built_in/mod.rs Normal file
View file

@ -0,0 +1,35 @@
mod cd;
mod exit;
#[derive(Debug)]
pub enum Action {
Exit,
ChangeDirectory(String),
}
fn get_function(command: String) -> Option<fn(Vec<&str>) -> Action> {
let registry = [
("exit", exit::exit as fn(Vec<&str>) -> Action),
("cd", cd::cd as fn(Vec<&str>) -> Action),
];
let mut function: Option<fn(Vec<&str>) -> Action> = None;
for entry in registry {
if entry.0 == &command {
function = Some(entry.1)
}
}
function
}
pub fn run_if_exists(command: String, arguments: Vec<&str>) -> Option<Action> {
let function = get_function(command);
if let Some(function) = function {
let action = function(arguments);
Some(action)
} else {
None
}
}

View file

@ -1 +1,2 @@
pub mod ash;
mod built_in;