aboutsummaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/command.rs204
1 files changed, 0 insertions, 204 deletions
diff --git a/src/parser/command.rs b/src/parser/command.rs
deleted file mode 100644
index 4dea8a6..0000000
--- a/src/parser/command.rs
+++ /dev/null
@@ -1,204 +0,0 @@
-use std::io::{Error, ErrorKind};
-use std::path::{Path, PathBuf};
-use std::process::{Command, ExitStatus};
-
-// > overwrite
-// >> append
-// | pipe
-
-#[derive(Debug)]
-enum Redirect {
- Std,
- FileOverwrite(String),
- FileAppend(String),
-}
-
-#[derive(Debug, PartialEq, Copy, Clone)]
-pub(in crate::parser) enum RunOn {
- Always,
- ExitSuccess,
- ExitFailure,
-}
-
-impl RunOn {
- pub(in crate::parser) fn can_run(&self, status: &Option<ExitStatus>) -> bool {
- if *self == RunOn::Always {
- return true;
- }
- match status {
- Some(s) => {
- (*self == RunOn::ExitSuccess && s.success())
- || (*self == RunOn::ExitFailure && !s.success())
- }
- None => true,
- }
- }
-}
-
-pub(in crate::parser) enum RunResult {
- Command(ExitStatus),
- Builtin,
-}
-
-#[derive(Debug)]
-pub struct CommandInfo {
- args: Vec<String>,
- stdout: Redirect,
- pub(in crate::parser) when: RunOn,
-}
-
-impl CommandInfo {
- pub(in crate::parser) fn new(line: &str, when: RunOn) -> CommandInfo {
- let (args, stdout) = tokenize(line);
- CommandInfo { args, stdout, when }
- }
-
- pub(in crate::parser) fn run(
- &self,
- home: &PathBuf,
- status: &Option<ExitStatus>,
- ) -> Result<RunResult, Error> {
- match self.args[0].as_str() {
- "!" => {
- println!("{:?}", status);
- Ok(RunResult::Builtin)
- }
- "cd" => cd(&self.args[1..], home),
- "exit" => {
- std::process::exit(0);
- }
- "set" => set(&self.args[1..]),
- "unset" => unset(&self.args[1..]),
- _ => {
- let mut child = Command::new(&self.args[0]).args(&self.args[1..]).spawn()?;
- Ok(RunResult::Command(child.wait().unwrap()))
- }
- }
- }
-}
-
-enum TokenType {
- Argument,
- StdoutFileOverwrite,
- StdoutFileAppend,
-}
-
-fn tokenize(line: &str) -> (Vec<String>, Redirect) {
- let mut args: Vec<String> = Vec::new();
- let mut stdout = Redirect::Std;
-
- let mut iter = line.chars().peekable();
- let mut token = String::new();
- let mut token_type = TokenType::Argument;
- let mut quote = false;
-
- while let Some(i) = iter.next() {
- match i {
- ' ' => {
- if quote {
- token.push(' ');
- }
- }
- '\'' => match iter.peek() {
- Some(&'\'') | Some(&'>') | Some(&'&') => {
- token.push(iter.next().unwrap());
- }
- _ => {
- quote = !quote;
- }
- },
- '>' => {
- if iter.peek() == Some(&'>') {
- token_type = TokenType::StdoutFileAppend;
- iter.next();
- } else {
- token_type = TokenType::StdoutFileOverwrite;
- }
- }
- _ => {
- token.push(i);
- }
- }
-
- if !token.is_empty() && ((iter.peek() == Some(&' ') && !quote) || iter.peek() == None) {
- match token_type {
- TokenType::Argument => args.push(token),
- TokenType::StdoutFileOverwrite => stdout = Redirect::FileOverwrite(token),
- TokenType::StdoutFileAppend => stdout = Redirect::FileAppend(token),
- }
- token = String::new();
- }
- }
-
- (args, stdout)
-}
-/*
-#[test]
-fn test_tokenizer() {
- {
- let ls = tokenize("ls -l");
- assert_eq!(ls.args, vec!("ls", "-l"));
- let string = tokenize("ls -l 'something else'");
- assert_eq!(string.args, vec!("ls", "-l", "something else"));
- let escape = tokenize("ls -l 'junction jan''s'");
- assert_eq!(escape.args, vec!("ls", "-l", "junction jan\'s"));
- }
- {
- let o = tokenize("&& ls");
- assert_eq!(o.args, vec!("ls"));
- assert_eq!(o.when, RunOn::ExitSuccess);
- let f = tokenize("|| ls");
- assert_eq!(f.args, vec!("ls"));
- assert_eq!(f.when, RunOn::ExitFailure);
- }
- println!("{:?}", tokenize("ls -l something'>"));
- println!("{:?}", tokenize("ls -l something'>'>"));
- println!("{:?}", tokenize("ls -l something >output"));
- println!("{:?}", tokenize("ls -l something > output"));
- println!("{:?}", tokenize("ls -l something >'junction jan''s'"));
- println!("{:?}", tokenize("ls -l something >>output"));
- println!("{:?}", tokenize("ls -l something >> output"));
- println!("{:?}", tokenize("ls -l something >>'junction jan''s'"));
-}
-*/
-fn cd(args: &[String], home: &PathBuf) -> Result<RunResult, Error> {
- if args.len() > 1 {
- return Err(Error::new(
- ErrorKind::InvalidInput,
- "Too many arguments passed to cd",
- ));
- }
-
- let root = if args.len() == 0 {
- home.to_path_buf()
- } else {
- std::fs::canonicalize(Path::new(args[0].as_str()))?
- };
-
- match std::env::set_current_dir(&root) {
- Ok(_) => Ok(RunResult::Builtin),
- Err(e) => Err(e),
- }
-}
-
-fn set(args: &[String]) -> Result<RunResult, Error> {
- if args.len() != 2 {
- return Err(Error::new(
- ErrorKind::InvalidInput,
- format!("set requires 2 arguments, got {}", args.len()),
- ));
- }
- std::env::set_var(&args[0], &args[1]);
- Ok(RunResult::Builtin)
-}
-
-fn unset(args: &[String]) -> Result<RunResult, Error> {
- if args.len() != 1 {
- return Err(Error::new(
- ErrorKind::InvalidInput,
- format!("unset requires 1 argument, got {}", args.len()),
- ));
- }
- std::env::remove_var(&args[0]);
- Ok(RunResult::Builtin)
-}