You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
1.7 KiB
82 lines
1.7 KiB
use crate::error::ShellError;
|
|
use crate::prompt::PromptStyle;
|
|
use once_cell::unsync::Lazy;
|
|
|
|
mod cd;
|
|
mod change_prompt;
|
|
mod exit;
|
|
mod pwd;
|
|
|
|
pub struct BuiltinConfig {
|
|
pub prompt_style: PromptStyle,
|
|
}
|
|
|
|
impl BuiltinConfig {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
prompt_style: PromptStyle::Default,
|
|
}
|
|
}
|
|
}
|
|
|
|
trait Builtin: Sync + Send {
|
|
fn execute(&mut self, config: &mut BuiltinConfig, args: Vec<String>) -> Result<(), ShellError>;
|
|
}
|
|
|
|
const BUILTINS: Lazy<Vec<(&str, Box<dyn Builtin>)>> = Lazy::new(|| {
|
|
vec![
|
|
("cd", Box::new(cd::Cd)),
|
|
("change-prompt", Box::new(change_prompt::ChangePrompt)),
|
|
("exit", Box::new(exit::Exit)),
|
|
("pwd", Box::new(pwd::Pwd)),
|
|
]
|
|
});
|
|
|
|
pub fn is_builtin(keyword: &str) -> bool {
|
|
BUILTINS.iter().find(|(k, _)| k == &keyword).is_some()
|
|
}
|
|
|
|
#[allow(const_item_mutation)]
|
|
pub fn execute_builtin(
|
|
keyword: &str,
|
|
config: &mut BuiltinConfig,
|
|
args: Vec<String>,
|
|
) -> Result<(), ShellError> {
|
|
if let Some(builtin) = BUILTINS
|
|
.iter_mut()
|
|
.find_map(|(k, c)| if k == &keyword { Some(c) } else { None })
|
|
{
|
|
builtin.execute(config, args)?
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_is_builtin_exit() {
|
|
assert_eq!(is_builtin("exit"), true);
|
|
}
|
|
|
|
#[test]
|
|
fn test_is_builtin_cd() {
|
|
assert_eq!(is_builtin("cd"), true);
|
|
}
|
|
|
|
#[test]
|
|
fn test_is_builtin_pwd() {
|
|
assert_eq!(is_builtin("pwd"), true);
|
|
}
|
|
|
|
#[test]
|
|
fn test_is_builtin_change_prompt() {
|
|
assert_eq!(is_builtin("change-prompt"), true);
|
|
}
|
|
|
|
#[test]
|
|
fn test_is_builtin_notabuiltin() {
|
|
assert_eq!(is_builtin("notabuiltin"), false)
|
|
}
|
|
}
|