From 9ef178e8a63975a9467c64aaf00e0f8a405ea4b3 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 24 Oct 2025 03:28:52 -0400 Subject: [PATCH] repline: Increased history cap, fully swappable prompts --- src/editor.rs | 4 ++-- src/repline.rs | 29 +++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index 903028b..0bbc1bf 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -26,8 +26,8 @@ pub struct Editor<'a> { tail: VecDeque, pub color: &'a str, - begin: &'a str, - again: &'a str, + pub begin: &'a str, + pub again: &'a str, } impl<'a> Editor<'a> { diff --git a/src/repline.rs b/src/repline.rs index 822816e..d45965e 100644 --- a/src/repline.rs +++ b/src/repline.rs @@ -14,6 +14,7 @@ use std::{ pub struct Repline<'a, R: Read> { input: Chars, Bytes>>, + history_cap: usize, history: VecDeque, // previous lines hindex: usize, // current index into the history buffer @@ -31,6 +32,7 @@ impl<'a, R: Read> Repline<'a, R> { pub fn with_input(input: R, color: &'a str, begin: &'a str, again: &'a str) -> Self { Self { input: Chars(Flatten(input.bytes())), + history_cap: 200, history: Default::default(), hindex: 0, ed: Editor::new(color, begin, again), @@ -39,6 +41,7 @@ impl<'a, R: Read> Repline<'a, R> { pub fn swap_input(self, new_input: S) -> Repline<'a, S> { Repline { input: Chars(Flatten(new_input.bytes())), + history_cap: self.history_cap, history: self.history, hindex: self.hindex, ed: self.ed, @@ -48,6 +51,13 @@ impl<'a, R: Read> Repline<'a, R> { pub fn set_color(&mut self, color: &'a str) { self.ed.color = color } + + /// Set the entire terminal prompt sequence + pub fn set_prompt(&mut self, color: &'a str, begin: &'a str, again: &'a str) { + let Editor { color: ed_color, begin: ed_begin, again: ed_again, .. } = &mut self.ed; + (*ed_color, *ed_begin, *ed_again) = (color, begin, again); + } + /// Append line to history and clear it pub fn accept(&mut self) { self.history_append(self.ed.to_string()); @@ -108,7 +118,10 @@ impl<'a, R: Read> Repline<'a, R> { } c if c.is_ascii_control() => { if cfg!(debug_assertions) { - self.ed.extend(c.escape_debug(), stdout)?; + self.print_err( + stdout, + format_args!("\t\x1b[30mUnhandled ASCII C0 {c:?}\x1b[0m"), + )?; } } c => { @@ -133,9 +146,14 @@ impl<'a, R: Read> Repline<'a, R> { /// Handle ANSI Escape fn escape(&mut self, w: &mut W) -> ReplResult<()> { match self.input.next().ok_or(Error::EndOfInput)?? { + '\r' => Err(Error::EndOfInput)?, '[' => self.csi(w)?, 'O' => todo!("Process alternate character mode"), - other => self.ed.extend(other.escape_debug(), w)?, + other => { + if cfg!(debug_assertions) { + self.print_err(w, format_args!("\t\x1b[30mANSI escape: {other:?}\x1b[0m"))?; + } + } } Ok(()) } @@ -173,7 +191,10 @@ impl<'a, R: Read> Repline<'a, R> { } other => { if cfg!(debug_assertions) { - self.print_err(w, other.escape_debug())?; + self.print_err( + w, + format_args!("\t\x1b[30mUnhandled control sequence: {other:?}\x1b[0m"), + )?; } } } @@ -203,7 +224,7 @@ impl<'a, R: Read> Repline<'a, R> { .expect("should have just found this"); }; self.history.push_back(buf); - while self.history.len() > 20 { + while self.history.len() > self.history_cap { self.history.pop_front(); } }