use crate::core::ScriptBlock;
use crate::parser::patterns::match_prompt_line;
#[derive(Debug)]
enum ParseState {
Start,
ExpectOutput,
}
pub(crate) fn parse_script_blocks(input: &str) -> Vec<ScriptBlock> {
let mut blocks = Vec::new();
let mut current_output: Vec<String> = Vec::new();
let mut state = ParseState::Start;
let mut has_seen_prompt = false;
for line in input.lines() {
let trimmed = line.trim_end();
if trimmed.is_empty() {
if matches!(state, ParseState::ExpectOutput) || !has_seen_prompt {
current_output.push("".to_string());
}
continue;
}
if let Some((prompt, command)) = match_prompt_line(trimmed) {
if !has_seen_prompt && !current_output.is_empty() {
blocks.push(ScriptBlock::Output(current_output.clone()));
current_output.clear();
}
if !current_output.is_empty() {
blocks.push(ScriptBlock::Output(current_output.clone()));
current_output.clear();
}
blocks.push(ScriptBlock::Prompt(prompt.to_string()));
if !command.is_empty() {
blocks.push(ScriptBlock::Command(command.to_string()));
state = ParseState::ExpectOutput;
} else {
state = ParseState::Start;
}
has_seen_prompt = true;
continue;
}
if matches!(state, ParseState::ExpectOutput) || !has_seen_prompt {
current_output.push(trimmed.to_string());
}
}
if !current_output.is_empty() {
blocks.push(ScriptBlock::Output(current_output));
}
blocks
}