summaryrefslogtreecommitdiffstats
path: root/src/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/mod.rs2
-rw-r--r--src/utils/spinner.rs52
2 files changed, 54 insertions, 0 deletions
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
index 15af4ca..3df1a09 100644
--- a/src/utils/mod.rs
+++ b/src/utils/mod.rs
@@ -2,12 +2,14 @@ mod abort_signal;
mod clipboard;
mod prompt_input;
mod render_prompt;
+mod spinner;
mod tiktoken;
pub use self::abort_signal::{create_abort_signal, AbortSignal};
pub use self::clipboard::set_text;
pub use self::prompt_input::*;
pub use self::render_prompt::render_prompt;
+pub use self::spinner::Spinner;
pub use self::tiktoken::cl100k_base_singleton;
use fancy_regex::Regex;
diff --git a/src/utils/spinner.rs b/src/utils/spinner.rs
new file mode 100644
index 0000000..c684901
--- /dev/null
+++ b/src/utils/spinner.rs
@@ -0,0 +1,52 @@
+use anyhow::Result;
+use crossterm::{cursor, queue, style, terminal};
+use std::io::{Stdout, Write};
+
+pub struct Spinner {
+ index: usize,
+ message: String,
+ stopped: bool,
+}
+
+impl Spinner {
+ const DATA: [&'static str; 10] = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
+
+ pub fn new(message: &str) -> Self {
+ Spinner {
+ index: 0,
+ message: message.to_string(),
+ stopped: false,
+ }
+ }
+
+ pub 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 / 5) % 4);
+ let line = format!("{frame}{}{:<3}", self.message, dots);
+ queue!(writer, cursor::MoveToColumn(0), style::Print(line),)?;
+ if self.index == 0 {
+ queue!(writer, cursor::Hide)?;
+ }
+ writer.flush()?;
+ self.index += 1;
+ Ok(())
+ }
+
+ pub 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(())
+ }
+}