diff options
-rw-r--r-- | Makefile | 24 | ||||
-rw-r--r-- | src/main.rs | 12 | ||||
-rw-r--r-- | src/parser.rs | 35 | ||||
-rw-r--r-- | src/parser/command.rs | 28 | ||||
-rw-r--r-- | src/prompt.rs | 3 |
5 files changed, 72 insertions, 30 deletions
@@ -1,6 +1,26 @@ PREFIX ?= /usr/local -MAN_PREFIX ?= ${PREFIX}/man +BIN_DEST ?= ${PREFIX}/bin +MAN_DEST ?= ${PREFIX}/man +CARGO ?= cargo +SCDOC ?= scdoc +RM ?= rm + +default: + @${CARGO} build +release: + @${CARGO} build --release --locked --all-features --target-dir=target manpage: - scdoc < man/rs.1.scd > man/rs.1 + @${SCDOC} < man/rs.1.scd > man/rs.1 +install: release manpage + install -Dm 755 -t "${BIN_DEST}" target/release/rs + install -Dm 555 -t "${MAN_DEST}" man/rs.1 + +run: + @${CARGO} run +fmt: + @${CARGO} fmt +clean: + @${RM} man/rs.1 + @${CARGO} clean diff --git a/src/main.rs b/src/main.rs index cb67e45..efd32c2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,6 @@ fn main() { } let prompt = prompt::Prompt::new().unwrap(); - let mut cwd = std::env::current_dir().unwrap(); let mut status = None; // `()` can be used when no completer is required @@ -22,15 +21,14 @@ fn main() { }*/ 'repl: loop { - match rl.readline(&prompt.print(&cwd)) { + match rl.readline(&prompt.print()) { Ok(line) => { rl.add_history_entry(line.as_str()); - let i = parser::tokenize(&line); - match i.run(&prompt.home, &mut cwd, &status) { - Ok(parser::command::RunResult::Command(s)) => status = Some(s), - Ok(parser::command::RunResult::Builtin) => {} - Err(e) => eprintln!("{}", e), + let cmd = parser::CommandLine::new(&line); + match cmd.run(&prompt.home, status) { + Ok(s) => status = s, + Err(e) => eprintln!("{}", e) } } Err(ReadlineError::Interrupted) => { diff --git a/src/parser.rs b/src/parser.rs index af4aed4..a96b679 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,14 +1,45 @@ +use std::io::Error; +use std::path::PathBuf; +use std::process::ExitStatus; + // > overwrite // >> append // | pipe +// : on prev cmd any // && on prev cmd okay // || on prev cmd fail -pub mod command; - +mod command; use command::*; +pub struct CommandLine(Vec<CommandInfo>); + +impl CommandLine { + pub fn new(line: &str) -> Self { + let split = line.split(':'); + let mut v = CommandLine(Vec::new()); + for x in split { + v.0.push(tokenize(x)); + } + v + } + + pub fn run( + &self, + home: &PathBuf, + mut status: Option<ExitStatus>, + ) -> Result<Option<ExitStatus>, Error> { + for cmd in &self.0 { + match cmd.run(&home, &status)? { + RunResult::Command(s) => status = Some(s), + RunResult::Builtin => {} + } + } + Ok(status) + } +} + enum TokenType { Argument, StdoutFileOverwrite, diff --git a/src/parser/command.rs b/src/parser/command.rs index 52b4666..5d129c3 100644 --- a/src/parser/command.rs +++ b/src/parser/command.rs @@ -3,14 +3,14 @@ use std::path::{Path, PathBuf}; use std::process::{Command, ExitStatus}; #[derive(Debug)] -pub enum Redirect { +pub(in crate::parser) enum Redirect { Std, FileOverwrite(String), FileAppend(String), } #[derive(Debug, PartialEq)] -pub enum RunOn { +pub(in crate::parser) enum RunOn { Always, ExitSuccess, ExitFailure, @@ -23,13 +23,13 @@ pub enum RunResult { #[derive(Debug)] pub struct CommandInfo { - pub args: Vec<String>, - pub stdout: Redirect, - pub when: RunOn, + pub(in crate::parser) args: Vec<String>, + pub(in crate::parser) stdout: Redirect, + pub(in crate::parser) when: RunOn, } impl CommandInfo { - pub fn new() -> CommandInfo { + pub(in crate::parser) fn new() -> CommandInfo { CommandInfo { args: Vec::new(), stdout: Redirect::Std, @@ -37,18 +37,13 @@ impl CommandInfo { } } - pub fn run( - &self, - home: &PathBuf, - cwd: &mut PathBuf, - status: &Option<ExitStatus>, - ) -> Result<RunResult, Error> { + pub 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, cwd), + "cd" => cd(&self.args[1..], home), "exit" => { std::process::exit(0); } @@ -62,7 +57,7 @@ impl CommandInfo { } } -fn cd(args: &[String], home: &PathBuf, cwd: &mut PathBuf) -> Result<RunResult, Error> { +fn cd(args: &[String], home: &PathBuf) -> Result<RunResult, Error> { if args.len() > 1 { return Err(Error::new( ErrorKind::InvalidInput, @@ -77,10 +72,7 @@ fn cd(args: &[String], home: &PathBuf, cwd: &mut PathBuf) -> Result<RunResult, E }; match std::env::set_current_dir(&root) { - Ok(_) => { - *cwd = root; - Ok(RunResult::Builtin) - } + Ok(_) => Ok(RunResult::Builtin), Err(e) => Err(e), } } diff --git a/src/prompt.rs b/src/prompt.rs index e70c958..12df7e0 100644 --- a/src/prompt.rs +++ b/src/prompt.rs @@ -27,7 +27,8 @@ impl Prompt { Ok(Prompt { ps1, home }) } - pub fn print(&self, pwd: &std::path::PathBuf) -> std::string::String { + pub fn print(&self) -> std::string::String { + let pwd = std::env::current_dir().unwrap(); let path = if pwd.starts_with(&self.home) { "~".to_owned() + &pwd.strip_prefix(&self.home).unwrap().display().to_string() } else { |