aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile24
-rw-r--r--src/main.rs12
-rw-r--r--src/parser.rs35
-rw-r--r--src/parser/command.rs28
-rw-r--r--src/prompt.rs3
5 files changed, 72 insertions, 30 deletions
diff --git a/Makefile b/Makefile
index ec06e96..47220d7 100644
--- a/Makefile
+++ b/Makefile
@@ -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 {