init
This commit is contained in:
80
src/executor.rs
Normal file
80
src/executor.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
/// Execute a shell command line and print output directly to stdout/stderr.
|
||||
/// Returns the exit code.
|
||||
pub fn execute(input: &str) -> i32 {
|
||||
let trimmed = input.trim();
|
||||
|
||||
// Handle cd specially - it must affect our process
|
||||
if trimmed == "cd" || trimmed.starts_with("cd ") {
|
||||
return handle_cd(trimmed);
|
||||
}
|
||||
|
||||
// Run everything else through sh -c for full shell semantics
|
||||
// (pipes, redirects, globs, etc.)
|
||||
let status = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(trimmed)
|
||||
.status();
|
||||
|
||||
match status {
|
||||
Ok(s) => s.code().unwrap_or(1),
|
||||
Err(e) => {
|
||||
eprintln!("aishell: {}", e);
|
||||
127
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_cd(input: &str) -> i32 {
|
||||
let target = input.strip_prefix("cd").unwrap().trim();
|
||||
|
||||
let dir: PathBuf = if target.is_empty() {
|
||||
// cd with no args → home directory
|
||||
match env::var("HOME") {
|
||||
Ok(home) => PathBuf::from(home),
|
||||
Err(_) => {
|
||||
eprintln!("aishell: cd: HOME not set");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else if target.starts_with('~') {
|
||||
// Expand ~ to HOME
|
||||
match env::var("HOME") {
|
||||
Ok(home) => PathBuf::from(target.replacen('~', &home, 1)),
|
||||
Err(_) => {
|
||||
eprintln!("aishell: cd: HOME not set");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else if target == "-" {
|
||||
// cd - → previous directory
|
||||
match env::var("OLDPWD") {
|
||||
Ok(old) => {
|
||||
println!("{}", old);
|
||||
PathBuf::from(old)
|
||||
}
|
||||
Err(_) => {
|
||||
eprintln!("aishell: cd: OLDPWD not set");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PathBuf::from(target)
|
||||
};
|
||||
|
||||
// Save current dir as OLDPWD
|
||||
if let Ok(cwd) = env::current_dir() {
|
||||
env::set_var("OLDPWD", cwd);
|
||||
}
|
||||
|
||||
match env::set_current_dir(&dir) {
|
||||
Ok(_) => 0,
|
||||
Err(e) => {
|
||||
eprintln!("aishell: cd: {}: {}", dir.display(), e);
|
||||
1
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user