mirror of
https://github.com/danbulant/rush
synced 2026-05-19 04:18:35 +00:00
better CLI
This commit is contained in:
parent
b0b6eb7d48
commit
33571b0c03
5 changed files with 143 additions and 13 deletions
91
Cargo.lock
generated
91
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
51
src/main.rs
51
src/main.rs
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue