better CLI

This commit is contained in:
Daniel Bulant 2022-02-21 15:08:22 +01:00
parent b0b6eb7d48
commit 33571b0c03
5 changed files with 143 additions and 13 deletions

91
Cargo.lock generated
View file

@ -32,6 +32,17 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.1.0"
@ -71,6 +82,21 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5f1fea81f183005ced9e59cdb01737ef2423956dac5a6d731b06b2ecfaa3467"
dependencies = [
"atty",
"bitflags",
"indexmap",
"os_str_bytes",
"strsim",
"termcolor",
"textwrap",
]
[[package]]
name = "filedescriptor"
version = "0.8.1"
@ -88,6 +114,31 @@ version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "indexmap"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "libc"
version = "0.2.107"
@ -125,6 +176,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "os_str_bytes"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
dependencies = [
"memchr",
]
[[package]]
name = "proc-macro2"
version = "1.0.32"
@ -166,6 +226,7 @@ name = "rush"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"filedescriptor",
"termion",
"utf8-chars",
@ -177,6 +238,12 @@ version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.82"
@ -188,6 +255,15 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "termion"
version = "1.5.6"
@ -200,6 +276,12 @@ dependencies = [
"redox_termios",
]
[[package]]
name = "textwrap"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
[[package]]
name = "thiserror"
version = "1.0.30"
@ -251,6 +333,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"

View file

@ -3,6 +3,7 @@ name = "rush"
version = "0.1.0"
authors = ["Daniel Bulant <danbulant@gmail.com>"]
edition = "2018"
description = "A simple rust shell"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -10,6 +11,7 @@ edition = "2018"
utf8-chars = "1.0.0"
termion = "1.5.6"
filedescriptor = "0.8.1"
clap = "3.1.0"
[dependencies.anyhow]
version = "1.0.54"

View file

@ -2,14 +2,17 @@ mod parser;
use std::io::{self, BufRead, Stdout, Write};
use std::cmp;
use std::collections::HashMap;
use std::convert::TryInto;
use std::path::Path;
use std::process;
use clap::{Arg, Command, arg};
use termion::raw::{IntoRawMode, RawTerminal};
use termion::input::TermRead;
use termion::cursor::{DetectCursorPos};
use termion::event::*;
use std::fs::File;
use std::io::BufReader;
use anyhow::Result;
struct Term {
input: String,
@ -70,7 +73,7 @@ impl Shell {
}
}
fn main() {
fn start_shell() {
let mut shell = Shell::new();
loop {
print!("$: ");
@ -85,6 +88,48 @@ fn main() {
}
}
const VERSION: &str = env!("CARGO_PKG_VERSION");
const AUTHORS: &str = env!("CARGO_PKG_AUTHORS");
const DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION");
fn load_and_run<P: AsRef<Path>>(path: P) -> Result<()> {
let mut ctx = parser::vars::Context::new();
let src = File::open(path).unwrap();
parser::exec(&mut BufReader::new(src), &mut ctx)
}
fn main() {
let matches = Command::new("Rush")
.version(VERSION)
.author(AUTHORS)
.about(DESCRIPTION)
.arg(
arg!([file] "File to execute")
)
.arg(
arg!(-c --command <COMMAND> "Command to execute")
.required(false)
)
.get_matches();
match matches.value_of("command") {
Some(command) => {
let mut ctx = parser::vars::Context::new();
parser::exec(&mut command.as_bytes(), &mut ctx).unwrap();
return;
},
None => {}
};
match matches.value_of("file") {
Some(file) => {
load_and_run(file).unwrap();
return;
},
None => {}
};
start_shell();
}
#[cfg(test)]
mod test {
use std::fs::File;

View file

@ -400,10 +400,8 @@ impl Tree {
if lvl != 0 {
bail!("Parenthesis do not match");
}
dbg!(&self, len);
let val = Value::Expressions(self.parse_sub(self.i + len)?);
self.inc();
dbg!(self);
return Ok(val);
},
Tokens::Else => buf.push(Value::Literal(token.to_str())),
@ -444,12 +442,10 @@ impl Tree {
let mut expr: Option<Expression> = None;
let mut token = self.get_current_token();
loop {
dbg!(token);
match token {
Tokens::Space => {self.inc();},
Tokens::CommandEnd(_) => { if matches!(expr, Some(_)) { break }; self.inc();},
Tokens::Literal(_) => if matches!(expr, Some(_)) {
dbg!(expr);
bail!("Unexpected literal. After file redirect, you need to use a semicolon or newline.");
} else {
expr = Some(self.parse_call(end)?);
@ -498,14 +494,14 @@ impl Tree {
_ => expr = Some(self.parse_call(end)?)
},
Tokens::Else => bail!("Unexpected token ELSE"),
Tokens::End => { dbg!(expr); bail!("Unexpected token END"); },
Tokens::End => { bail!("Unexpected token END"); },
Tokens::For => match expr {
Some(_) => bail!("Commands must be ended properly"),
None => expr = Some(Expression::ForExpression(self.parse_for(end)?)),
},
Tokens::If => match expr {
Some(_) => bail!("Commands must be ended properly"),
None => {expr = Some(Expression::IfExpression(self.parse_if(end)?)); dbg!(&expr); },
None => {expr = Some(Expression::IfExpression(self.parse_if(end)?)); },
}
Tokens::Let => return Ok(self.parse_let(end)?),
Tokens::While => return Ok(Expression::WhileExpression(self.parse_while(end)?)),
@ -539,7 +535,6 @@ impl Tree {
Tokens::JobCommandEnd => bail!("Jobs not yet implemented")
}
if self.i >= end - 1 { break }
dbg!("finished loop", &expr);
token = self.get_current_token();
}
match expr {
@ -566,7 +561,6 @@ pub fn build_tree(tokens: Vec<Tokens>) -> Result<Vec<Expression>> {
Ok(val) => expressions.push(val),
Err(error) => {
if error.to_string() == "No expression found" { break }
dbg!(tree);
return Err(error);
}
}

View file

@ -13,8 +13,6 @@ pub fn exec(reader: &mut dyn std::io::BufRead, ctx: &mut vars::Context) -> Resul
let expressions = build_tree(tokens)?;
dbg!(&expressions);
exec_tree(expressions, ctx)?;
Ok(())
}