diff --git a/src/app/state.rs b/src/app/state.rs index 66b1163..30f6319 100644 --- a/src/app/state.rs +++ b/src/app/state.rs @@ -130,12 +130,18 @@ impl State { let output = match &mut session_live.expecting { ReplSessionExpecting::ClearlineBeforeInitialPrompt { cl_progress } => { use ClearLineProgressStatus::*; - match cl_progress.clone().character(ch)? { + match cl_progress.clone().character(ch) { InProgress(progress) => { *cl_progress = progress; vec![] } ReachedEnd => self.next_query(&id)?, + UnexpectedCharacter => { + let mut line = cl_progress.progress().to_owned(); + line.push(ch); + session_live.expecting = ReplSessionExpecting::UnexpectedLine { line }; + vec![] + } } } ReplSessionExpecting::ClearLineBeforeResult { @@ -143,7 +149,7 @@ impl State { expected_result, } => { use ClearLineProgressStatus::*; - match cl_progress.clone().character(ch)? { + match cl_progress.clone().character(ch) { InProgress(progress) => { *cl_progress = progress; } @@ -154,6 +160,11 @@ impl State { expected_result: expected_result.clone(), }; } + UnexpectedCharacter => { + let mut line = cl_progress.progress().to_owned(); + line.push(ch); + session_live.expecting = ReplSessionExpecting::UnexpectedLine { line }; + } }; vec![] } @@ -190,6 +201,15 @@ impl State { self.next_query(&id)? } + ReplSessionExpecting::UnexpectedLine { line } => { + line.push(ch); + + if ch == '\n' { + bail!("{id}: unexepcted line: {line}"); + } + + vec![] + } }; Ok(output) @@ -342,23 +362,27 @@ pub(crate) enum ExampleState { const CLEAR_LINE: &str = "\r\u{1b}[K"; #[derive(Debug, Clone)] -pub struct ClearLineProgress(std::iter::Peekable>); +pub struct ClearLineProgress(std::iter::Peekable>>); impl ClearLineProgress { - fn character(mut self, ch: char) -> anyhow::Result { - let expected = self.0.next().unwrap(); + fn character(mut self, ch: char) -> ClearLineProgressStatus { + let (_i, expected) = self.0.next().unwrap(); if ch != expected { - bail!("expected {expected:?}, got {ch:?}") - } - Ok(if self.0.peek().is_none() { + ClearLineProgressStatus::UnexpectedCharacter + } else if self.0.peek().is_none() { ClearLineProgressStatus::ReachedEnd } else { ClearLineProgressStatus::InProgress(self) - }) + } } fn new() -> Self { - Self(CLEAR_LINE.chars().peekable()) + Self(CLEAR_LINE.chars().enumerate().peekable()) + } + + fn progress(&mut self) -> &'static str { + let &(i, _) = self.0.peek().unwrap(); + &CLEAR_LINE[..i] } } @@ -366,4 +390,19 @@ impl ClearLineProgress { enum ClearLineProgressStatus { InProgress(ClearLineProgress), ReachedEnd, + UnexpectedCharacter, +} + +#[cfg(test)] +mod test { + use pretty_assertions::assert_eq; + + use super::ClearLineProgress; + + #[test] + fn clear_line_progress() { + let mut cl_progress = ClearLineProgress::new(); + let progress = cl_progress.progress(); + assert_eq!(progress, ""); + } } diff --git a/src/app/state/repl_state.rs b/src/app/state/repl_state.rs index 654fa22..37208eb 100644 --- a/src/app/state/repl_state.rs +++ b/src/app/state/repl_state.rs @@ -57,6 +57,9 @@ pub(crate) enum ReplSessionExpecting { acc: String, expected_result: ExpectedResult, }, + UnexpectedLine { + line: String, + }, } impl ReplSessionLive {