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
|
//! builtins to sesh
|
||||||
#![allow(clippy::type_complexity)]
|
#![allow(clippy::type_complexity)]
|
||||||
|
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
/// List of builtins
|
/// List of builtins
|
||||||
pub const BUILTINS: [(
|
pub const BUILTINS: [(
|
||||||
&str,
|
&str,
|
||||||
fn(args: Vec<String>, unsplit_args: String, state: &mut super::State) -> i32,
|
fn(args: Vec<String>, unsplit_args: String, state: &mut super::State) -> i32,
|
||||||
&str,
|
&str,
|
||||||
); 5] = [
|
); 6] = [
|
||||||
("cd", cd, "[dir]"),
|
("cd", cd, "[dir]"),
|
||||||
("exit", exit, ""),
|
("exit", exit, ""),
|
||||||
("echo", echo, "[-e] [text ...]"),
|
("echo", echo, "[-e] [text ...]"),
|
||||||
("alias", alias, "[name] [value]"),
|
("alias", alias, "[name] [value]"),
|
||||||
("help", help, ""),
|
("help", help, ""),
|
||||||
|
("source", eval, "filename [arguments]"),
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Change the directory
|
/// 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 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!("Use `man -k' or `info' to find out more about commands not in this list.");
|
||||||
println!();
|
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);
|
println!("{} {}", builtin.0, builtin.2);
|
||||||
}
|
}
|
||||||
0
|
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.
|
/// A lot of [ShellVar]s.
|
||||||
type ShellVars = Vec<ShellVar>;
|
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.
|
/// A reference to a variable.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
enum Variable {
|
enum Variable {
|
||||||
|
@ -66,8 +58,6 @@ struct Alias {
|
||||||
/// The state of the shell
|
/// The state of the shell
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct State {
|
struct State {
|
||||||
/// Environment variables
|
|
||||||
env: Arc<Mutex<std::env::VarsOs>>,
|
|
||||||
/// Shell-local variables only accessible via builtins.
|
/// Shell-local variables only accessible via builtins.
|
||||||
shell_env: ShellVars,
|
shell_env: ShellVars,
|
||||||
/// The focused variable.
|
/// The focused variable.
|
||||||
|
@ -170,11 +160,20 @@ fn split_statements(statement: &str) -> Vec<String> {
|
||||||
.concat()
|
.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)]
|
#[allow(clippy::arc_with_non_send_sync)]
|
||||||
/// Evaluate a statement. May include multiple.
|
/// Evaluate a statement. May include multiple.
|
||||||
fn eval(statement: &str, state: &mut State) {
|
fn eval(statement: &str, state: &mut State) {
|
||||||
let statement = remove_comments(statement);
|
let statement = remove_comments(statement);
|
||||||
let statements = split_statements(&statement);
|
let statements = split_statements(&substitute_vars(&statement, state.clone()));
|
||||||
|
|
||||||
for statement in statements {
|
for statement in statements {
|
||||||
let mut statement_split = split_statement(&statement);
|
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();
|
let s = state.clone();
|
||||||
state.history.push(s);
|
state.history.push(s);
|
||||||
}
|
}
|
||||||
|
@ -284,7 +282,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let options = Args::parse();
|
let options = Args::parse();
|
||||||
|
|
||||||
let mut state = State {
|
let mut state = State {
|
||||||
env: Arc::new(Mutex::new(std::env::vars_os())),
|
|
||||||
shell_env: Vec::new(),
|
shell_env: Vec::new(),
|
||||||
focus: Variable::Local(String::new()),
|
focus: Variable::Local(String::new()),
|
||||||
history: Vec::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