read_eval_loop

Function read_eval_loop 

Source
pub async fn read_eval_loop(
    env: &RefCell<&mut Env>,
    lexer: &mut Lexer<'_>,
) -> Result
Expand description

Reads input, parses it, and executes commands in a loop.

A read-eval loop uses a Lexer for reading and parsing input and Env for executing parsed commands. It creates a Parser from the lexer to parse command lines. The loop executes each command line before parsing the next one. The loop continues until the parser reaches the end of input or encounters a parser error, or the command execution results in a Break(Divert::...).

This function takes a RefCell containing the mutable reference to the environment. The RefCell should be shared only with the Input implementor used in the Lexer to avoid conflicting borrows.

If the input source code contains no commands, the exit status is set to zero. Otherwise, the exit status reflects the result of the last executed command.

Pending traps are run and subshell statuses are updated between parsing input and running commands.

For the top-level read-eval loop of an interactive shell, see interactive_read_eval_loop.

ยงExample

Executing a command:

let mut env = Env::new_virtual();
let mut lexer = Lexer::with_code("case foo in (bar) ;; esac");
let result = read_eval_loop(&RefCell::new(&mut env), &mut lexer).await;
assert_eq!(result, Continue(()));
assert_eq!(env.exit_status, ExitStatus::SUCCESS);

Using the Echo decorator with the shared environment:

let mut env = Env::new_virtual();
let mut ref_env = RefCell::new(&mut env);
let input = Box::new(Echo::new(Memory::new("case foo in (bar) ;; esac"), &ref_env));
let mut lexer = Lexer::new(input);
let result = read_eval_loop(&ref_env, &mut lexer).await;
drop(lexer);
assert_eq!(result, Continue(()));
assert_eq!(env.exit_status, ExitStatus::SUCCESS);