sourcing
This commit is contained in:
parent
98e3fb15db
commit
bfa67385ef
3 changed files with 59 additions and 15 deletions
|
@ -1,17 +1,20 @@
|
|||
//! builtins to sesh
|
||||
#![allow(clippy::type_complexity)]
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
/// List of builtins
|
||||
pub const BUILTINS: [(
|
||||
&str,
|
||||
fn(args: Vec<String>, unsplit_args: String, state: &mut super::State) -> i32,
|
||||
&str,
|
||||
); 5] = [
|
||||
); 6] = [
|
||||
("cd", cd, "[dir]"),
|
||||
("exit", exit, ""),
|
||||
("echo", echo, "[-e] [text ...]"),
|
||||
("alias", alias, "[name] [value]"),
|
||||
("help", help, ""),
|
||||
("source", eval, "filename [arguments]"),
|
||||
];
|
||||
|
||||
/// Change the directory
|
||||
|
@ -86,8 +89,51 @@ pub fn help(_: Vec<String>, _: String, _: &mut super::State) -> i32 {
|
|||
println!("Use `man sesh` to find out more about the shell in general.");
|
||||
println!("Use `man -k' or `info' to find out more about commands not in this list.");
|
||||
println!();
|
||||
for builtin in BUILTINS {
|
||||
let mut builtins = BUILTINS.clone();
|
||||
builtins.sort_by(|v1, v2| v1.0.cmp(v2.0));
|
||||
|
||||
for builtin in builtins {
|
||||
println!("{} {}", builtin.0, builtin.2);
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
/// Run a file.
|
||||
pub fn eval(args: Vec<String>, _: String, state: &mut super::State) -> i32 {
|
||||
if args.len() < 2 {
|
||||
println!("sesh: {}: filename argument required", args[0]);
|
||||
println!("sesh: {0}: usage: {0} filename [arguments]", args[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
let file = std::fs::read(args[1].clone());
|
||||
if file.is_err() {
|
||||
println!(
|
||||
"sesh: {}: error opening file: {}",
|
||||
args[0],
|
||||
file.unwrap_err()
|
||||
);
|
||||
return 2;
|
||||
}
|
||||
let file = String::from_utf8(file.unwrap());
|
||||
if file.is_err() {
|
||||
println!("sesh: {}: invalid UTF-8: {}", args[0], file.unwrap_err());
|
||||
return 3;
|
||||
}
|
||||
let file = file.unwrap();
|
||||
|
||||
let mut state2 = state.clone();
|
||||
|
||||
let mut i = 0usize;
|
||||
for arg in &args[1..] {
|
||||
state2.shell_env.push(super::ShellVar {
|
||||
name: format!("{}", i),
|
||||
value: arg.clone(),
|
||||
});
|
||||
i += 1;
|
||||
}
|
||||
|
||||
super::eval(&file, &mut state2);
|
||||
|
||||
0
|
||||
}
|
||||
|
|
23
src/main.rs
23
src/main.rs
|
@ -38,14 +38,6 @@ struct ShellVar {
|
|||
/// A lot of [ShellVar]s.
|
||||
type ShellVars = Vec<ShellVar>;
|
||||
|
||||
/// Whether a variable is local or not.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
enum VariableLocality {
|
||||
/// A local variable.
|
||||
Local,
|
||||
/// A nonlocal variable.
|
||||
Nonlocal,
|
||||
}
|
||||
/// A reference to a variable.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
enum Variable {
|
||||
|
@ -66,8 +58,6 @@ struct Alias {
|
|||
/// The state of the shell
|
||||
#[derive(Clone, Debug)]
|
||||
struct State {
|
||||
/// Environment variables
|
||||
env: Arc<Mutex<std::env::VarsOs>>,
|
||||
/// Shell-local variables only accessible via builtins.
|
||||
shell_env: ShellVars,
|
||||
/// The focused variable.
|
||||
|
@ -170,11 +160,20 @@ fn split_statements(statement: &str) -> Vec<String> {
|
|||
.concat()
|
||||
}
|
||||
|
||||
/// Substitute in shell variables
|
||||
fn substitute_vars(statement: &str, state: State) -> String {
|
||||
let mut out = statement.to_string();
|
||||
for ShellVar { name, value } in state.shell_env {
|
||||
out = out.replace(&("$".to_owned()+&name), &value);
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
#[allow(clippy::arc_with_non_send_sync)]
|
||||
/// Evaluate a statement. May include multiple.
|
||||
fn eval(statement: &str, state: &mut State) {
|
||||
let statement = remove_comments(statement);
|
||||
let statements = split_statements(&statement);
|
||||
let statements = split_statements(&substitute_vars(&statement, state.clone()));
|
||||
|
||||
for statement in statements {
|
||||
let mut statement_split = split_statement(&statement);
|
||||
|
@ -236,7 +235,6 @@ fn eval(statement: &str, state: &mut State) {
|
|||
}
|
||||
}
|
||||
|
||||
state.env = Arc::new(Mutex::new(std::env::vars_os()));
|
||||
let s = state.clone();
|
||||
state.history.push(s);
|
||||
}
|
||||
|
@ -284,7 +282,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let options = Args::parse();
|
||||
|
||||
let mut state = State {
|
||||
env: Arc::new(Mutex::new(std::env::vars_os())),
|
||||
shell_env: Vec::new(),
|
||||
focus: Variable::Local(String::new()),
|
||||
history: Vec::new(),
|
||||
|
|
1
test.sesh
Normal file
1
test.sesh
Normal file
|
@ -0,0 +1 @@
|
|||
echo test $0 $1
|
Loading…
Add table
Add a link
Reference in a new issue