formatting and more vscode settings

This commit is contained in:
Arthur Beck 2025-05-05 14:34:44 -05:00
parent 268b1ecc65
commit 587abe6f9a
4 changed files with 99 additions and 13 deletions

3
.gitignore vendored
View file

@ -23,3 +23,6 @@ Cargo.lock
# ignore files used for testing stuff like loadf
/test*
# benchmark files
dhat.out.*

View file

@ -8,7 +8,7 @@ pub const BUILTINS: [(
&str,
fn(args: Vec<String>, unsplit_args: String, state: &mut super::State) -> i32,
&str,
); 15] = [
); 17] = [
("cd", cd, "[dir]"),
("exit", exit, ""),
("echo", echo, "[-e] [text ...]"),
@ -24,6 +24,8 @@ pub const BUILTINS: [(
("pastef", pastef, ""),
("setf", setf, "var [var ...]"),
("getf", getf, "var"),
("()", nop, ""),
("if", _if, "condition ( statement ) [ ( else_statement )"),
];
/// Change the directory
@ -52,6 +54,10 @@ pub fn exit(_: Vec<String>, _: String, state: &mut super::State) -> i32 {
/// Echo a string
pub fn echo(args: Vec<String>, mut unsplit_args: String, _: &mut super::State) -> i32 {
if args.len() == 1 {
println!();
return 0;
}
unsplit_args = unsplit_args[(args[0].len() + 1)..].to_string();
if args.len() != 1 && args[1] == "-e" {
unsplit_args = unsplit_args[3..].to_string();
@ -325,3 +331,35 @@ pub fn getf(args: Vec<String>, _: String, state: &mut super::State) -> i32 {
state.focus = super::Focus::Str(val);
0
}
/// Empty function that does nothing. Mainly used for benchmarking evaluating.
pub fn nop(_: Vec<String>, _: String, _: &mut super::State) -> i32 {
0
}
/// if statement
pub fn _if(args: Vec<String>, _: String, state: &mut super::State) -> i32 {
if args.len() < 3 {
println!(
"sesh: {0}: usage: {0} condition (statement) [ (else_statement) ]",
args[0]
);
return 1;
}
super::eval(&args[1].clone(), state);
state.shell_env.reverse();
let mut status = 0i32;
for var in &state.shell_env {
if var.name == "STATUS" {
status = var.value.parse().unwrap();
}
}
state.shell_env.sort_by(|v1, v2| v1.name.cmp(&v2.name));
if status == 0 {
super::eval(&args[2].clone(), state);
} else if args.len() == 8 {
super::eval(&args[3].clone(), state);
}
0
}

View file

@ -3,6 +3,7 @@
#![warn(missing_docs, clippy::missing_docs_in_private_items)]
#![feature(cfg_match)]
#![feature(slice_concat_trait)]
#![feature(test)]
use std::{
ffi::OsStr,
@ -17,6 +18,8 @@ use termion::raw::IntoRawMode;
mod builtins;
mod escapes;
#[cfg(test)]
mod tests;
/// sesh is a shell designed to be as semantic to use as possible
#[derive(Parser, Debug)]
@ -85,8 +88,6 @@ impl Display for Focus {
struct State {
/// Shell-local variables only accessible via builtins.
shell_env: ShellVars,
/// The previous history of the states.
history: Vec<State>,
/// Current working directory.
working_dir: PathBuf,
/// A list of aliases from name to actual.
@ -103,20 +104,37 @@ unsafe impl Send for State {}
/// Split a statement.
fn split_statement(statement: &str) -> Vec<String> {
let mut out = vec![String::new()];
let mut i: usize = 0;
let mut i = 0usize;
let mut in_str = (false, ' ');
let mut escape = false;
let mut f = 0usize;
for ch in statement.chars() {
if ch == '\\' && !in_str.0 {
escape = true;
}
if ['"', '\'', '`'].contains(&ch) && !escape {
if in_str.0 && in_str.1 == ch {
in_str.0 = false
} else {
in_str = (true, ch);
if in_str.0 && in_str.1 == ch {
in_str.0 = false;
if ch == ']' {
out[i].push(ch);
}
escape = false;
f += 1;
continue;
}
if !(!['"', '\'', '`', '(', '['].contains(&ch) || escape || in_str.0 || ch == '[' && f <= 1)
{
in_str = (true, ch);
if ch == '(' {
in_str.1 = ')';
}
if ch == '[' {
in_str.1 = ']';
}
if ch == '[' {
out[i].push(ch);
}
escape = false;
f += 1;
continue;
}
if !in_str.0 && ch == ' ' {
@ -125,10 +143,12 @@ fn split_statement(statement: &str) -> Vec<String> {
out.push(String::new());
}
escape = false;
f += 1;
continue;
}
out[i].push(ch);
escape = false;
f += 1;
}
out.iter()
.map(|v| v.trim().to_string())
@ -326,9 +346,6 @@ fn eval(statement: &str, state: &mut State) {
}
}
}
let s = state.clone();
state.history.push(s);
}
/// Write the prompt to the screen.
@ -388,7 +405,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut state = State {
shell_env: Vec::new(),
history: Vec::new(),
focus: Focus::Str(String::new()),
working_dir: std::env::current_dir()
.unwrap_or(std::env::home_dir().unwrap_or(PathBuf::from("/"))),

29
src/tests.rs Normal file
View file

@ -0,0 +1,29 @@
#![allow(clippy::unit_arg)]
extern crate test; // needed
use super::*;
#[bench]
pub fn bench_eval(bencher: &mut test::Bencher) {
bencher.iter(|| {
let mut state = State {
shell_env: Vec::new(),
focus: Focus::Str(String::new()),
working_dir: std::env::current_dir()
.unwrap_or(std::env::home_dir().unwrap_or(PathBuf::from("/"))),
aliases: Vec::new(),
raw_term: None,
};
state.shell_env.push(ShellVar {
name: "PROMPT1".to_string(),
value: "\x1b[32m$u@$h\x1b[39m \x1b[34m$P\x1b[39m> ".to_string(),
});
state.shell_env.push(ShellVar {
name: "PROMPT2".to_string(),
value: "> ".to_string(),
});
core::hint::black_box(eval("", &mut state));
core::hint::black_box(eval("()", &mut state));
core::hint::black_box(eval("echo", &mut state));
});
}