aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs16
-rw-r--r--src/parse.rs88
2 files changed, 94 insertions, 10 deletions
diff --git a/src/main.rs b/src/main.rs
index 52fc234..8a6e84e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -8,14 +8,14 @@ use std::process::{Command, Stdio};
use std::thread::sleep;
use std::time::Duration;
-pub mod completion;
-pub mod cursor;
-pub mod linebuf;
-pub mod panic;
-pub mod parse;
-pub mod raw;
-pub mod reload;
-pub mod run;
+mod completion;
+mod cursor;
+mod linebuf;
+mod panic;
+mod parse;
+mod raw;
+mod reload;
+mod run;
mod basedir;
mod history;
diff --git a/src/parse.rs b/src/parse.rs
index 2da97c7..a685f5d 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -17,10 +17,94 @@ pub struct Pipes {
pub cmds: Vec<Command>,
}
+pub enum StringPart {
+ Boring(BString),
+ Var(BString),
+ Cmd(Ast),
+}
+
+/// `"hi ${var} $(cmd) "` gets mapped to `[Boring("hi "), Var("var"), String(" "), Cmd(...), Boring(" ")]`
+pub struct ShellString {
+ parts: Vec<StringPart>,
+}
+
+fn is_symbol(x: u8) -> bool {
+ match x {
+ b'|' => true,
+ _ => false,
+ }
+}
+
+impl Parse for ShellString {
+ fn parse(b: &mut Cursor<'_>) -> Result<Self> {
+ b.spaces();
+ if b.is_empty() {
+ return Err(ParseError::Eof);
+ }
+
+ let mut delim = b.peek();
+ if delim != b'\'' && delim != b'"' {
+ delim = b' ';
+ } else {
+ b.adv();
+ }
+
+ let mut parts = Vec::new();
+ let p = &mut parts;
+ let mut escaping = false;
+
+ let add_char = |p: &mut Vec<StringPart>, x: u8| match p.last_mut() {
+ Some(StringPart::Boring(v)) => v.push(x),
+ _ => p.push(StringPart::Boring(vec![x])),
+ };
+
+ while b.has() {
+ let x = b.peek();
+
+ if escaping {
+ add_char(p, x);
+ escaping = false;
+ b.adv();
+ continue;
+ }
+
+ if x == delim {
+ if delim != b' ' {
+ b.adv();
+ }
+ return Ok(Self { parts });
+ }
+
+ b.adv();
+
+ if x == b'\\' {
+ escaping = true;
+ continue;
+ }
+
+ if x == b'$' {
+ todo!()
+ }
+
+ if delim == b' ' && is_symbol(x) {
+ return Ok(Self { parts });
+ }
+
+ add_char(p, x);
+ }
+
+ if b.is_completion() {
+ Ok(Self { parts })
+ } else {
+ Err(ParseError::Eof)
+ }
+ }
+}
+
#[derive(Debug)]
pub struct Command {
- pub cmd: Vec<u8>,
- pub args: Vec<Vec<u8>>,
+ pub cmd: BString,
+ pub args: Vec<BString>,
}
#[derive(Debug)]