diff options
| author | sigoden <sigoden@gmail.com> | 2023-11-08 20:36:30 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-11-08 20:36:30 +0800 |
| commit | b40659613dcaf626ed8e47ad787bcc58e5ee48ab (patch) | |
| tree | 2436ac07190886a6e6bdbba635c59b20c7cdbbd0 /src/render | |
| parent | eb30d90391ef73429589a98f34dfe4d3d88d0a38 (diff) | |
| download | aichat-b40659613dcaf626ed8e47ad787bcc58e5ee48ab.tar.gz | |
feat: add a spinner to indicate waiting for response (#236)
Diffstat (limited to 'src/render')
| -rw-r--r-- | src/render/stream.rs | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/src/render/stream.rs b/src/render/stream.rs index 189862d..2e05c3a 100644 --- a/src/render/stream.rs +++ b/src/render/stream.rs @@ -64,14 +64,21 @@ fn markdown_stream_inner( let columns = terminal::size()?.0; + let mut spinner = Spinner::new(" Generating"); + loop { if abort.aborted() { return Ok(()); } + spinner.step(writer)?; if let Ok(evt) = rx.try_recv() { match evt { ReplyEvent::Text(text) => { + if spinner.is_running() { + spinner.stop(writer)?; + } + let (col, mut row) = cursor::position()?; // Fix unexpected duplicate lines on kitty, see https://github.com/sigoden/aichat/issues/105 @@ -155,6 +162,59 @@ fn markdown_stream_inner( Ok(()) } +struct Spinner { + index: usize, + message: String, + stopped: bool, +} + +impl Spinner { + const DATA: [&str; 10] = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; + + fn new(message: &str) -> Self { + Spinner { + index: 0, + message: message.to_string(), + stopped: false, + } + } + + fn is_running(&self) -> bool { + !self.stopped + } + + fn step(&mut self, writer: &mut Stdout) -> Result<()> { + if self.stopped { + return Ok(()); + } + let frame = Self::DATA[self.index % Self::DATA.len()]; + let dots = ".".repeat((self.index / 8) % 4); + let line = format!("{frame}{}{dots}", self.message); + queue!(writer, cursor::MoveToColumn(0), style::Print(line),)?; + if self.index == 0 { + queue!(writer, cursor::Hide)?; + } + writer.flush()?; + self.index += 1; + Ok(()) + } + + fn stop(&mut self, writer: &mut Stdout) -> Result<()> { + if self.stopped { + return Ok(()); + } + self.stopped = true; + queue!( + writer, + cursor::MoveToColumn(0), + terminal::Clear(terminal::ClearType::FromCursorDown), + cursor::Show + )?; + writer.flush()?; + Ok(()) + } +} + fn print_block(writer: &mut Stdout, text: &str, columns: u16) -> Result<u16> { let mut num = 0; for line in text.split('\n') { |
