use std::convert::TryFrom;
use crate::io::FileDescriptor;
use super::{ast, mem, SourcePos};
#[derive(Debug)]
pub enum ArgUnit {
Literal(Box<[u8]>),
Dollar {
slot_ix: mem::SlotIx,
pos: SourcePos,
}
}
#[derive(Debug)]
pub enum ArgPart {
Unit(ArgUnit),
Home, Range(i64, i64), Collection(Box<[ArgUnit]>),
Star, Percent, CharClass(Box<[u8]>), }
#[derive(Debug)]
pub struct Argument {
pub parts: Box<[ArgPart]>,
pub pos: SourcePos,
}
#[derive(Debug)]
pub enum RedirectionTarget {
Fd(FileDescriptor),
Overwrite(Argument),
Append(Argument),
}
#[derive(Debug)]
pub enum Redirection {
Output {
source: FileDescriptor,
target: RedirectionTarget,
},
Input {
literal: bool,
source: Argument,
},
}
#[derive(Debug, Copy, Clone)]
pub enum Builtin {
Alias,
Cd,
}
#[derive(Debug)]
pub struct InvalidBuiltin;
impl std::error::Error for InvalidBuiltin { }
impl<'a> TryFrom<&'a [u8]> for Builtin {
type Error = InvalidBuiltin;
fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
match value {
b"alias" => Ok(Self::Alias),
b"cd" => Ok(Self::Cd),
_ => Err(InvalidBuiltin)
}
}
}
impl<'a> TryFrom<&'a ast::Argument> for Builtin {
type Error = InvalidBuiltin;
fn try_from(arg: &'a ast::Argument) -> Result<Self, Self::Error> {
match arg.parts.as_ref() {
[ ast::ArgPart::Unit(ast::ArgUnit::Literal(ref lit)) ] => Self::try_from(lit.as_ref()),
_ => Err(InvalidBuiltin),
}
}
}
#[derive(Debug)]
pub struct BasicCommand {
pub program: Argument,
pub env: Box<[(ArgUnit, Argument)]>,
pub arguments: Box<[Argument]>,
pub redirections: Box<[Redirection]>,
pub abort_on_error: bool,
pub pos: SourcePos,
}
#[derive(Debug)]
pub enum Command {
Builtin {
program: Builtin,
arguments: Box<[Argument]>,
abort_on_error: bool,
pos: SourcePos,
},
External {
head: BasicCommand,
tail: Box<[BasicCommand]>
}
}
#[derive(Debug)]
pub struct CommandBlock {
pub kind: CommandBlockKind,
pub head: Command,
pub tail: Box<[Command]>,
}
#[derive(Debug)]
pub enum CommandBlockKind {
Synchronous, Asynchronous, Capture, }
impl From<ast::CommandBlockKind> for CommandBlockKind {
fn from(kind: ast::CommandBlockKind) -> Self {
match kind {
ast::CommandBlockKind::Synchronous => CommandBlockKind::Synchronous,
ast::CommandBlockKind::Asynchronous => CommandBlockKind::Asynchronous,
ast::CommandBlockKind::Capture => CommandBlockKind::Capture,
}
}
}