use ast::{AndOr, DefaultArithmetic, DefaultParameter, RedirectOrCmdWord, RedirectOrEnvVar};
mod default_builder;
mod empty_builder;
pub use self::default_builder::*;
pub use self::empty_builder::EmptyBuilder;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SeparatorKind {
Semi,
Amp,
Newline,
Other,
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum LoopKind {
While,
Until,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct CommandGroup<C> {
pub commands: Vec<C>,
pub trailing_comments: Vec<Newline>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct GuardBodyPairGroup<C> {
pub guard: CommandGroup<C>,
pub body: CommandGroup<C>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct IfFragments<C> {
pub conditionals: Vec<GuardBodyPairGroup<C>>,
pub else_branch: Option<CommandGroup<C>>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ForFragments<W, C> {
pub var: String,
pub var_comment: Option<Newline>,
pub words: Option<(Vec<Newline>, Vec<W>, Option<Newline>)>,
pub pre_body_comments: Vec<Newline>,
pub body: CommandGroup<C>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct CaseFragments<W, C> {
pub word: W,
pub post_word_comments: Vec<Newline>,
pub in_comment: Option<Newline>,
pub arms: Vec<CaseArm<W, C>>,
pub post_arms_comments: Vec<Newline>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct CaseArm<W, C> {
pub patterns: CasePatternFragments<W>,
pub body: CommandGroup<C>,
pub arm_comment: Option<Newline>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct CasePatternFragments<W> {
pub pre_pattern_comments: Vec<Newline>,
pub pattern_alternatives: Vec<W>,
pub pattern_comment: Option<Newline>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ComplexWordKind<C> {
Concat(Vec<WordKind<C>>),
Single(WordKind<C>),
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum WordKind<C> {
Simple(SimpleWordKind<C>),
DoubleQuoted(Vec<SimpleWordKind<C>>),
SingleQuoted(String),
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum SimpleWordKind<C> {
Literal(String),
Param(DefaultParameter),
Subst(Box<ParameterSubstitutionKind<ComplexWordKind<C>, C>>),
CommandSubst(CommandGroup<C>),
Escaped(String),
Star,
Question,
SquareOpen,
SquareClose,
Tilde,
Colon,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum RedirectKind<W> {
Read(Option<u16>, W),
Write(Option<u16>, W),
ReadWrite(Option<u16>, W),
Append(Option<u16>, W),
Clobber(Option<u16>, W),
Heredoc(Option<u16>, W),
DupRead(Option<u16>, W),
DupWrite(Option<u16>, W),
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ParameterSubstitutionKind<W, C> {
Command(CommandGroup<C>),
Len(DefaultParameter),
Arith(Option<DefaultArithmetic>),
Default(bool, DefaultParameter, Option<W>),
Assign(bool, DefaultParameter, Option<W>),
Error(bool, DefaultParameter, Option<W>),
Alternative(bool, DefaultParameter, Option<W>),
RemoveSmallestSuffix(DefaultParameter, Option<W>),
RemoveLargestSuffix(DefaultParameter, Option<W>),
RemoveSmallestPrefix(DefaultParameter, Option<W>),
RemoveLargestPrefix(DefaultParameter, Option<W>),
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Newline(pub Option<String>);
pub trait Builder {
type Command;
type CommandList;
type ListableCommand;
type PipeableCommand;
type CompoundCommand;
type Word;
type Redirect;
type Error;
fn complete_command(&mut self,
pre_cmd_comments: Vec<Newline>,
list: Self::CommandList,
separator: SeparatorKind,
cmd_comment: Option<Newline>)
-> Result<Self::Command, Self::Error>;
fn and_or_list(&mut self,
first: Self::ListableCommand,
rest: Vec<(Vec<Newline>, AndOr<Self::ListableCommand>)>)
-> Result<Self::CommandList, Self::Error>;
fn pipeline(&mut self,
bang: bool,
cmds: Vec<(Vec<Newline>, Self::PipeableCommand)>)
-> Result<Self::ListableCommand, Self::Error>;
fn simple_command(
&mut self,
redirects_or_env_vars: Vec<RedirectOrEnvVar<Self::Redirect, String, Self::Word>>,
redirects_or_cmd_words: Vec<RedirectOrCmdWord<Self::Redirect, Self::Word>>
) -> Result<Self::PipeableCommand, Self::Error>;
fn brace_group(&mut self,
cmds: CommandGroup<Self::Command>,
redirects: Vec<Self::Redirect>)
-> Result<Self::CompoundCommand, Self::Error>;
fn subshell(&mut self,
cmds: CommandGroup<Self::Command>,
redirects: Vec<Self::Redirect>)
-> Result<Self::CompoundCommand, Self::Error>;
fn loop_command(&mut self,
kind: LoopKind,
guard_body_pair: GuardBodyPairGroup<Self::Command>,
redirects: Vec<Self::Redirect>)
-> Result<Self::CompoundCommand, Self::Error>;
fn if_command(&mut self,
fragments: IfFragments<Self::Command>,
redirects: Vec<Self::Redirect>)
-> Result<Self::CompoundCommand, Self::Error>;
fn for_command(&mut self,
fragments: ForFragments<Self::Word, Self::Command>,
redirects: Vec<Self::Redirect>)
-> Result<Self::CompoundCommand, Self::Error>;
fn case_command(&mut self,
fragments: CaseFragments<Self::Word, Self::Command>,
redirects: Vec<Self::Redirect>)
-> Result<Self::CompoundCommand, Self::Error>;
fn compound_command_into_pipeable(&mut self,
cmd: Self::CompoundCommand)
-> Result<Self::PipeableCommand, Self::Error>;
fn function_declaration(&mut self,
name: String,
post_name_comments: Vec<Newline>,
body: Self::CompoundCommand)
-> Result<Self::PipeableCommand, Self::Error>;
fn comments(&mut self,
comments: Vec<Newline>)
-> Result<(), Self::Error>;
fn word(&mut self,
kind: ComplexWordKind<Self::Command>)
-> Result<Self::Word, Self::Error>;
fn redirect(&mut self,
kind: RedirectKind<Self::Word>)
-> Result<Self::Redirect, Self::Error>;
}
macro_rules! impl_builder_body {
($T:ident) => {
type Command = $T::Command;
type CommandList = $T::CommandList;
type ListableCommand = $T::ListableCommand;
type PipeableCommand = $T::PipeableCommand;
type CompoundCommand = $T::CompoundCommand;
type Word = $T::Word;
type Redirect = $T::Redirect;
type Error = $T::Error;
fn complete_command(&mut self,
pre_cmd_comments: Vec<Newline>,
list: Self::CommandList,
separator: SeparatorKind,
cmd_comment: Option<Newline>)
-> Result<Self::Command, Self::Error>
{
(**self).complete_command(pre_cmd_comments, list, separator, cmd_comment)
}
fn and_or_list(&mut self,
first: Self::ListableCommand,
rest: Vec<(Vec<Newline>, AndOr<Self::ListableCommand>)>)
-> Result<Self::CommandList, Self::Error>
{
(**self).and_or_list(first, rest)
}
fn pipeline(&mut self,
bang: bool,
cmds: Vec<(Vec<Newline>, Self::PipeableCommand)>)
-> Result<Self::ListableCommand, Self::Error>
{
(**self).pipeline(bang, cmds)
}
fn simple_command(
&mut self,
redirects_or_env_vars: Vec<RedirectOrEnvVar<Self::Redirect, String, Self::Word>>,
redirects_or_cmd_words: Vec<RedirectOrCmdWord<Self::Redirect, Self::Word>>
) -> Result<Self::PipeableCommand, Self::Error>
{
(**self).simple_command(redirects_or_env_vars, redirects_or_cmd_words)
}
fn brace_group(&mut self,
cmds: CommandGroup<Self::Command>,
redirects: Vec<Self::Redirect>)
-> Result<Self::CompoundCommand, Self::Error>
{
(**self).brace_group(cmds, redirects)
}
fn subshell(&mut self,
cmds: CommandGroup<Self::Command>,
redirects: Vec<Self::Redirect>)
-> Result<Self::CompoundCommand, Self::Error>
{
(**self).subshell(cmds, redirects)
}
fn loop_command(&mut self,
kind: LoopKind,
guard_body_pair: GuardBodyPairGroup<Self::Command>,
redirects: Vec<Self::Redirect>)
-> Result<Self::CompoundCommand, Self::Error>
{
(**self).loop_command(kind, guard_body_pair, redirects)
}
fn if_command(&mut self,
fragments: IfFragments<Self::Command>,
redirects: Vec<Self::Redirect>)
-> Result<Self::CompoundCommand, Self::Error>
{
(**self).if_command(fragments, redirects)
}
fn for_command(&mut self,
fragments: ForFragments<Self::Word, Self::Command>,
redirects: Vec<Self::Redirect>)
-> Result<Self::CompoundCommand, Self::Error>
{
(**self).for_command(fragments, redirects)
}
fn case_command(&mut self,
fragments: CaseFragments<Self::Word, Self::Command>,
redirects: Vec<Self::Redirect>)
-> Result<Self::CompoundCommand, Self::Error>
{
(**self).case_command(fragments, redirects)
}
fn compound_command_into_pipeable(&mut self,
cmd: Self::CompoundCommand)
-> Result<Self::PipeableCommand, Self::Error>
{
(**self).compound_command_into_pipeable(cmd)
}
fn function_declaration(&mut self,
name: String,
post_name_comments: Vec<Newline>,
body: Self::CompoundCommand)
-> Result<Self::PipeableCommand, Self::Error>
{
(**self).function_declaration(name, post_name_comments, body)
}
fn comments(&mut self,
comments: Vec<Newline>)
-> Result<(), Self::Error>
{
(**self).comments(comments)
}
fn word(&mut self,
kind: ComplexWordKind<Self::Command>)
-> Result<Self::Word, Self::Error>
{
(**self).word(kind)
}
fn redirect(&mut self,
kind: RedirectKind<Self::Word>)
-> Result<Self::Redirect, Self::Error>
{
(**self).redirect(kind)
}
}
}
impl<'a, T: Builder + ?Sized> Builder for &'a mut T {
impl_builder_body!(T);
}
impl<T: Builder + ?Sized> Builder for Box<T> {
impl_builder_body!(T);
}