Browse Source

feat: use trait to define builtins

main
fdai7451 2 years ago
parent
commit
b9f3007d9e
  1. 7
      Cargo.lock
  2. 1
      Cargo.toml
  3. 14
      src/builtins/cd.rs
  4. 7
      src/builtins/exit.rs
  5. 20
      src/builtins/mod.rs

7
Cargo.lock

@ -169,10 +169,17 @@ dependencies = [
"static_assertions",
]
[[package]]
name = "once_cell"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "pmuw-project"
version = "0.1.0"
dependencies = [
"once_cell",
"rustyline",
"shlex",
]

1
Cargo.toml

@ -4,5 +4,6 @@ version = "0.1.0"
edition = "2021"
[dependencies]
once_cell = "1.17"
rustyline = "10.1.0"
shlex = "1.1"

14
src/builtins/cd.rs

@ -1,8 +1,16 @@
use crate::builtins::Builtin;
use std::env::set_current_dir;
use crate::error::ShellError;
pub fn run(args: Vec<String>) -> Result<(), ShellError> {
set_current_dir(args.get(0).unwrap());
Ok(())
pub struct Cd;
impl Builtin for Cd {
fn execute(&mut self, args: Vec<String>) -> Result<(), ShellError> {
let Some(first) = args.get(0) else {
return Err(ShellError::ExecuteFailure("no argument given".to_string()))
};
set_current_dir(first).map_err(|e| ShellError::ExecuteFailure(e.to_string()))
}
}

7
src/builtins/exit.rs

@ -1,5 +1,10 @@
use crate::builtins::Builtin;
use crate::error::ShellError;
pub fn run() -> Result<(), ShellError> {
pub struct Exit;
impl Builtin for Exit {
fn execute(&mut self, _: Vec<String>) -> Result<(), ShellError> {
Err(ShellError::Exit)
}
}

20
src/builtins/mod.rs

@ -1,18 +1,26 @@
use crate::error::ShellError;
use once_cell::unsync::Lazy;
mod cd;
mod exit;
const BUILTINS: &[&str] = &["exit", "cd"];
trait Builtin: Sync + Send {
fn execute(&mut self, args: Vec<String>) -> Result<(), ShellError>;
}
const BUILTINS: Lazy<Vec<(&str, Box<dyn Builtin>)>> =
Lazy::new(|| vec![("cd", Box::new(cd::Cd)), ("exit", Box::new(exit::Exit))]);
pub fn is_builtin(keyword: &str) -> bool {
BUILTINS.contains(&keyword)
BUILTINS.iter().find(|(k, _)| k == &keyword).is_some()
}
#[allow(const_item_mutation)]
pub fn execute_builtin(keyword: &str, args: Vec<String>) -> Result<(), ShellError> {
match keyword {
"exit" => exit::run()?,
"cd" => cd::run(args)?,
_ => {}
if let Some(builtin) = BUILTINS
.iter_mut()
.find_map(|(k, c)| if k == &keyword { Some(c) } else { None })
{
builtin.execute(args)?
}
Ok(())
}

Loading…
Cancel
Save