start lexin
parent
0a0dfc2ee9
commit
d79a28b3b0
@ -1,5 +1,66 @@
|
||||
mod tail;
|
||||
mod command;
|
||||
mod tail;
|
||||
mod which;
|
||||
mod printenv;
|
||||
mod echo;
|
||||
|
||||
pub use tail::Tail;
|
||||
pub use command::Command;
|
||||
pub use echo::Echo;
|
||||
pub use tail::Tail;
|
||||
pub use which::Which;
|
||||
pub use printenv::Printenv;
|
||||
|
||||
/*
|
||||
Posix Shell builtins:
|
||||
|
||||
alias bg cd command false fc fg getopts hash jobs kill
|
||||
newgrp pwd read true type ulimit umask unalias wait
|
||||
|
||||
Bourne Shell builtins:
|
||||
|
||||
: - do nothing except expand arguments and perform redirections
|
||||
. - read and execute a file in the current shell context
|
||||
break - exit from a loop
|
||||
cd - change the current working directory to directory
|
||||
continue - resume the next iteration of a loop
|
||||
eval - evaluate the arguments as a single command
|
||||
exec - replace the shell without creating a new process
|
||||
exit - exits the process with a status
|
||||
export - exports environment variables
|
||||
getopts - used by shell scripts to parse arguments
|
||||
hash - displays the hash table used by the shell to map command names to files
|
||||
pwd - prints the absolute path of the current directory
|
||||
readonly - mark each name as readonly so that they cannot be reassigned
|
||||
return - causes a shell function to stop execution and return a value
|
||||
shift - shifts the position parameters to the left by n
|
||||
test - evaluate a conditional expression and return a status of 0 or 1
|
||||
times - print out the user and system times used by the shell and its children. sorry, what the fuck is this
|
||||
trap - execute commands when a given signal is received
|
||||
umask - set the shell process's file creation mask
|
||||
unset - clears variable or function names
|
||||
|
||||
Bash Builtins:
|
||||
|
||||
alias - creates an alias for a command
|
||||
bind - adds key bindings
|
||||
builtin - access a builtin function even if it has been masked by another function
|
||||
caller - tells you what line number you're executing?
|
||||
command - runs a command with a given name, ignoring shell functions
|
||||
declare - declare variables and give them attributes
|
||||
echo - echos the outputs
|
||||
enable - enable and disable builtin shell commands
|
||||
help - display help text about builtin commands
|
||||
let - perform arithmetic on shell variables
|
||||
local - create local variables
|
||||
logout - exits a login shell with a status
|
||||
mapfile - read lines from stdin or a file into an array
|
||||
printf - formats arguments using a format string
|
||||
read - reads one line from stdin or from a file
|
||||
readarray - read lines from stdin into an array or something
|
||||
source - executes the script in the current shell
|
||||
type - tells you if a thing is an alias, function, builtin, or file command
|
||||
typeset - synonym for declare, included for korn shell compatibility
|
||||
ulimit - provides control over the resources available to the processes started by the shell
|
||||
unalias - clears an alias
|
||||
|
||||
*/
|
||||
|
@ -1,7 +1,7 @@
|
||||
use anyhow::Result;
|
||||
|
||||
pub trait Command {
|
||||
fn name() -> String;
|
||||
|
||||
fn create() -> Self;
|
||||
|
||||
fn exec(&mut self, args: Vec<&str>) -> anyhow::Result<bool>;
|
||||
fn exec(&mut self, args: Vec<&str>) -> Result<bool>;
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
use crate::ext::Command;
|
||||
use anyhow::Result;
|
||||
|
||||
pub struct Echo {}
|
||||
|
||||
impl Command for Echo {
|
||||
fn name() -> String {
|
||||
String::from("echo")
|
||||
}
|
||||
|
||||
fn create() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
fn exec(&mut self, args: Vec<&str>) -> Result<bool> {
|
||||
println!("{}", args.join(" "));
|
||||
Ok(true)
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
use crate::ext::Command;
|
||||
use anyhow::Result;
|
||||
|
||||
pub struct Printenv {}
|
||||
|
||||
impl Command for Printenv {
|
||||
fn name() -> String {
|
||||
String::from("printenv")
|
||||
}
|
||||
|
||||
fn create() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
fn exec(&mut self, args: Vec<&str>) -> Result<bool> {
|
||||
if args.len() > 0 {
|
||||
let name = args[0];
|
||||
match std::env::var(name) {
|
||||
Ok(val) => {
|
||||
println!("{}", val);
|
||||
Ok(true)
|
||||
}
|
||||
Err(e) => {
|
||||
println!("ERROR {}", e);
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("which variable you fucking dork");
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
use crate::ext::Command;
|
||||
use anyhow::Result;
|
||||
|
||||
pub struct Which {}
|
||||
|
||||
impl Command for Which {
|
||||
fn name() -> String {
|
||||
String::from("which")
|
||||
}
|
||||
|
||||
fn create() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
fn exec(&mut self, args: Vec<&str>) -> Result<bool> {
|
||||
if args.len() > 0 {
|
||||
let path = std::env::var("path").unwrap();
|
||||
let dirs: Vec<&str> = path.split(";").collect();
|
||||
for d in dirs {
|
||||
let dir = std::path::Path::new(d);
|
||||
let fname = dir.join(args[0]).with_extension("exe");
|
||||
if fname.exists() && fname.is_file() {
|
||||
println!("{}", fname.to_str().unwrap());
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
println!("not found: {}", args[0]);
|
||||
Ok(false)
|
||||
} else {
|
||||
println!("what do you want to look for?");
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
#[derive(Debug)]
|
||||
pub enum Error {}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Token {
|
||||
Ident(String),
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn lex<S: AsRef<str>>(text: S) -> Result<Vec<Token>, Error> {
|
||||
Lexer::new(text.as_ref()).lex()
|
||||
}
|
||||
|
||||
struct Lexer<'text> {
|
||||
chars: std::str::Chars<'text>,
|
||||
peeked: Option<char>,
|
||||
}
|
||||
|
||||
impl<'text> Lexer<'text> {
|
||||
fn new(text: &'text str) -> Self {
|
||||
Self {
|
||||
chars: text.chars(),
|
||||
peeked: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn lex(&mut self) -> Result<Vec<Token>, Error> {
|
||||
let mut tokens = vec![];
|
||||
while self.peek().is_some() {
|
||||
self.skip_whitespace();
|
||||
match self.peek() {
|
||||
None => { return Ok(tokens) },
|
||||
Some(_) => {
|
||||
tokens.push(self.ident());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(tokens)
|
||||
}
|
||||
|
||||
fn skip_whitespace(&mut self) {
|
||||
loop {
|
||||
match self.peek() {
|
||||
None => break,
|
||||
Some(c) => {
|
||||
if c.is_whitespace() {
|
||||
self.skip()
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn peek(&mut self) -> Option<char> {
|
||||
match self.peeked {
|
||||
Some(c) => Some(c),
|
||||
None => match self.chars.next() {
|
||||
Some(c) => {
|
||||
self.peeked = Some(c);
|
||||
Some(c)
|
||||
}
|
||||
None => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn skip(&mut self) {
|
||||
if self.peeked.is_some() {
|
||||
self.peeked = None;
|
||||
} else {
|
||||
self.chars.next();
|
||||
}
|
||||
}
|
||||
|
||||
fn ident(&mut self) -> Token {
|
||||
let mut kept: Vec<char> = vec!();
|
||||
loop {
|
||||
match self.peek() {
|
||||
None => break,
|
||||
Some(c) => {
|
||||
if c.is_whitespace() {
|
||||
break;
|
||||
}
|
||||
kept.push(c);
|
||||
self.skip();
|
||||
}
|
||||
}
|
||||
}
|
||||
Token::Ident(kept.iter().collect())
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn parse(line: String) -> Result<Tree, Error> {
|
||||
// Ok(Tree::new())
|
||||
// }
|
||||
|
||||
// pub struct Tree {
|
||||
//
|
||||
// }
|
||||
|
||||
// impl Tree {
|
||||
// pub fn new() -> Self { Self { } }
|
||||
// }
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn lex_empty() -> Result<(), Error> {
|
||||
let tokens = lex("")?;
|
||||
assert_eq!(tokens.len(), 0);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lex_ident() -> Result<(), Error> {
|
||||
let tokens = lex("one")?;
|
||||
assert_eq!(tokens.len(), 1);
|
||||
assert_eq!(tokens[0], Token::Ident(String::from("one")));
|
||||
|
||||
let tokens = lex("one two")?;
|
||||
assert_eq!(tokens.len(), 2);
|
||||
assert_eq!(tokens[0], Token::Ident(String::from("one")));
|
||||
assert_eq!(tokens[1], Token::Ident(String::from("two")));
|
||||
Ok(())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue