pub fn execute_jobs(
    shell: &mut Shell, 
    mut jobs: Vec<Job>, 
    capture: bool
) -> Result<(i32, String), ShellError> {

    let mut captured = String::new();
    let mut execif: Option<Exec>;
    let mut result = CommandResult::new();

    if jobs[0].cmds[0].cmd.0 == Quote::NQuote {
        if jobs[0].cmds[0].cmd.1 == "func" {
            if let Some(job) = jobs.last() {
                if job.cmds[0].cmd.1 != "endfn" {
                    return Err(
                        ShellError::from("oyster: cannot parse function")
                    )
                }
            }
            let mut func = jobs.remove(0);
            let mut params_count = None;
            if func.cmds[0].args.len() > 2 {
                params_count = match func.cmds[0].args[2].1.parse::<usize>() {
                    Ok(int) => Some(int),
                    Err(_) => {
                        return Err(
                            ShellError::from("oyster: invalid function params count")
                        )
                    }
                };
            }
            let funcname = func.cmds.remove(0)
                           .args.remove(1).1;
            jobs.pop();
            shell.insert_func(&funcname, jobs, params_count);
            return Ok((0, String::new()))
        }
    }

    //if execute_jobs is called from scripting,
    //this should not return any shell constructs
    let jobs = extract_constructs(jobs)?;

    for job in jobs {
        match job {
            ExecType::Job(job) => {
                if job.cmds[0].cmd.0 == Quote::NQuote
                && job.cmds[0].cmd.1 == "return" {
                    return Ok((0, String::new()))
                }
                execif = job.execnext;
                if let Some(execcond) = execif {
                    match execcond {
                        Exec::And => { //continue if last job succeeded
                            if job.cmds[0].cmd.1.ends_with("()") {
                                result = execute_func(shell, job)?.into();
                            } else {
                                result = execute(shell, job, false, capture)?;
                            }
                            captured.push_str(&result.stdout);
                            if result.status == 0 {
                                continue;
                            } else {
                                return Ok((result.status, captured));
                            }
                        }
                        Exec::Or => { //continue if last job failed
                            if job.cmds[0].cmd.1.ends_with("()") {
                                result = execute_func(shell, job)?.into();
                            } else {
                                result = execute(shell, job, false, capture)?;
                            } 
                            captured.push_str(&result.stdout);
                            if result.status != 0 {
                                continue;
                            } else {
                                return Ok((result.status, captured));
                            }
                        }
                        Exec::Consec => { //unconditional execution
                            if job.cmds[0].cmd.1.ends_with("()") {
                                result = execute_func(shell, job)?.into();
                            } else {
                                result = execute(shell, job, false, capture)?;
                            }
                            captured.push_str(&result.stdout);
                            continue;
                        }
                        Exec::Background => { //run jobs asynchronously
                            if job.cmds[0].cmd.1.ends_with("()") {
                                result = execute_func(shell, job)?.into();
                            } else {
                                result = execute(shell, job, false, capture)?;
                            }
                            captured.push_str(&result.stdout);
                            continue;
                        }
                    }
                } else { //if is None; this should only occur on the last job
                    if job.cmds[0].cmd.1.ends_with("()") {
                        result = execute_func(shell, job)?.into();
                    } else {
                        result = execute(shell, job, false, capture)?;
                    }
                    captured.push_str(&result.stdout);
                }
            }
            ExecType::Script(script) => {
                //println!("got script: {:?}", script);
                let script = Construct::build(shell, script)?;
                result.status = script.execute(shell)?;
            }
        }
        
    }
    Ok((result.status, captured))
}
/// High level control of all jobs. Conditional execution is handled here.
/// Parses tokens into jobs, performs expansion and executes them.
High level control of all jobs. Conditional execution is handled here.
Parses tokens into jobs, performs expansion and executes them.
High level control of all jobs . Conditional execution is handled here . Parses tokens into jobs performs expansion and executes them .
pub fn execute_jobs(
    shell: &mut Shell, 
    mut jobs: Vec<Job>, 
    capture: bool
) -> Result<(i32, String), ShellError> {
    let mut captured = String::new();
    let mut execif: Option<Exec>;
    let mut result = CommandResult::new();
    if jobs[0].cmds[0].cmd.0 == Quote::NQuote {
        if jobs[0].cmds[0].cmd.1 == "func" {
            if let Some(job) = jobs.last() {
                if job.cmds[0].cmd.1 != "endfn" {
                    return Err(
                        ShellError::from("oyster: cannot parse function")
                    )
                }
            }
            let mut func = jobs.remove(0);
            let mut params_count = None;
            if func.cmds[0].args.len() > 2 {
                params_count = match func.cmds[0].args[2].1.parse::<usize>() {
                    Ok(int) => Some(int),
                    Err(_) => {
                        return Err(
                            ShellError::from("oyster: invalid function params count")
                        )
                    }
                };
            }
            let funcname = func.cmds.remove(0)
                           .args.remove(1).1;
            jobs.pop();
            shell.insert_func(&funcname, jobs, params_count);
            return Ok((0, String::new()))
        }
    }
    //if execute_jobs is called from scripting,
    //this should not return any shell constructs
    let jobs = extract_constructs(jobs)?;
    for job in jobs {
        match job {
            ExecType::Job(job) => {
                if job.cmds[0].cmd.0 == Quote::NQuote
                && job.cmds[0].cmd.1 == "return" {
                    return Ok((0, String::new()))
                }
                execif = job.execnext;
                if let Some(execcond) = execif {
                    match execcond {
                        Exec::And => { //continue if last job succeeded
                            if job.cmds[0].cmd.1.ends_with("()") {
                                result = execute_func(shell, job)?.into();
                            } else {
                                result = execute(shell, job, false, capture)?;
                            }
                            captured.push_str(&result.stdout);
                            if result.status == 0 {
                                continue;
                            } else {
                                return Ok((result.status, captured));
                            }
                        }
                        Exec::Or => { //continue if last job failed
                            if job.cmds[0].cmd.1.ends_with("()") {
                                result = execute_func(shell, job)?.into();
                            } else {
                                result = execute(shell, job, false, capture)?;
                            } 
                            captured.push_str(&result.stdout);
                            if result.status != 0 {
                                continue;
                            } else {
                                return Ok((result.status, captured));
                            }
                        }
                        Exec::Consec => { //unconditional execution
                            if job.cmds[0].cmd.1.ends_with("()") {
                                result = execute_func(shell, job)?.into();
                            } else {
                                result = execute(shell, job, false, capture)?;
                            }
                            captured.push_str(&result.stdout);
                            continue;
                        }
                        Exec::Background => { //run jobs asynchronously
                            if job.cmds[0].cmd.1.ends_with("()") {
                                result = execute_func(shell, job)?.into();
                            } else {
                                result = execute(shell, job, false, capture)?;
                            }
                            captured.push_str(&result.stdout);
                            continue;
                        }
                    }
                } else { //if is None; this should only occur on the last job
                    if job.cmds[0].cmd.1.ends_with("()") {
                        result = execute_func(shell, job)?.into();
                    } else {
                        result = execute(shell, job, false, capture)?;
                    }
                    captured.push_str(&result.stdout);
                }
            }
            ExecType::Script(script) => {
                //println!("got script: {:?}", script);
                let script = Construct::build(shell, script)?;
                result.status = script.execute(shell)?;
            }
        }
    }
    Ok((result.status, captured))
}
pub fn execute_jobs ( shell : & mut Shell , mut jobs : Vec < Job > , capture : bool ) -> Result < ( i32 , String ) , ShellError > { let mut captured = String :: new ( ) ; let mut execif : Option < Exec > ; let mut result = CommandResult :: new ( ) ; if jobs [ 0 ] . cmds [ 0 ] . cmd . 0 == Quote :: NQuote { if jobs [ 0 ] . cmds [ 0 ] . cmd . 1 == " " { if let Some ( job ) = jobs . last ( ) { if job . cmds [ 0 ] . cmd . 1 != " " { return Err ( ShellError :: from ( " " ) ) } } let mut func = jobs . remove ( 0 ) ; let mut params_count = None ; if func . cmds [ 0 ] . args . len ( ) > 2 { params_count = match func . cmds [ 0 ] . args [ 2 ] . 1 . parse :: < usize > ( ) { Ok ( int ) => Some ( int ) , Err ( _ ) => { return Err ( ShellError :: from ( " " ) ) } } ; } let funcname = func . cmds . remove ( 0 ) . args . remove ( 1 ) . 1 ; jobs . pop ( ) ; shell . insert_func ( & funcname , jobs , params_count ) ; return Ok ( ( 0 , String :: new ( ) ) ) } } //if execute_jobs is called from scripting, //this should not return any shell constructs let jobs = extract_constructs ( jobs ) ? ; for job in jobs { match job { ExecType :: Job ( job ) => { if job . cmds [ 0 ] . cmd . 0 == Quote :: NQuote && job . cmds [ 0 ] . cmd . 1 == " " { return Ok ( ( 0 , String :: new ( ) ) ) } execif = job . execnext ; if let Some ( execcond ) = execif { match execcond { Exec :: And => { //continue if last job succeeded if job . cmds [ 0 ] . cmd . 1 . ends_with ( " " ) { result = execute_func ( shell , job ) ? . into ( ) ; } else { result = execute ( shell , job , false , capture ) ? ; } captured . push_str ( & result . stdout ) ; if result . status == 0 { continue ; } else { return Ok ( ( result . status , captured ) ) ; } } Exec :: Or => { //continue if last job failed if job . cmds [ 0 ] . cmd . 1 . ends_with ( " " ) { result = execute_func ( shell , job ) ? . into ( ) ; } else { result = execute ( shell , job , false , capture ) ? ; } captured . push_str ( & result . stdout ) ; if result . status != 0 { continue ; } else { return Ok ( ( result . status , captured ) ) ; } } Exec :: Consec => { //unconditional execution if job . cmds [ 0 ] . cmd . 1 . ends_with ( " " ) { result = execute_func ( shell , job ) ? . into ( ) ; } else { result = execute ( shell , job , false , capture ) ? ; } captured . push_str ( & result . stdout ) ; continue ; } Exec :: Background => { //run jobs asynchronously if job . cmds [ 0 ] . cmd . 1 . ends_with ( " " ) { result = execute_func ( shell , job ) ? . into ( ) ; } else { result = execute ( shell , job , false , capture ) ? ; } captured . push_str ( & result . stdout ) ; continue ; } } } else { //if is None; this should only occur on the last job if job . cmds [ 0 ] . cmd . 1 . ends_with ( " " ) { result = execute_func ( shell , job ) ? . into ( ) ; } else { result = execute ( shell , job , false , capture ) ? ; } captured . push_str ( & result . stdout ) ; } } ExecType :: Script ( script ) => { //println!("got script: {:?}", script); let script = Construct :: build ( shell , script ) ? ; result . status = script . execute ( shell ) ? ; } } } Ok ( ( result . status , captured ) ) }
High level control of all jobs.
High level control of all jobs .
shell
&mut Shell
jobs
Vec<Job>
capture
bool