diff options
| author | Jonas Maier <> | 2026-03-06 16:01:15 +0100 |
|---|---|---|
| committer | Jonas Maier <> | 2026-03-06 16:01:15 +0100 |
| commit | 40387917c8ba4703aee111e1cf37dcd793e39ba2 (patch) | |
| tree | 5759ff0c2d0011c4b94bd7979734ce106b6217b0 /src/parse.rs | |
| parent | f6736ab046e8e5f6eef9211bf9f72a3faa8c597c (diff) | |
| download | pish-40387917c8ba4703aee111e1cf37dcd793e39ba2.tar.gz | |
partial shell string parser
Diffstat (limited to 'src/parse.rs')
| -rw-r--r-- | src/parse.rs | 88 |
1 files changed, 86 insertions, 2 deletions
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)] |
