summaryrefslogtreecommitdiffstats
path: root/src/utils/spinner.rs
diff options
context:
space:
mode:
authorsigoden <sigoden@gmail.com>2024-04-21 06:52:22 +0800
committerGitHub <noreply@github.com>2024-04-21 06:52:22 +0800
commitb3162a72b50f88d78ca3d57c1f8b3421cecfe2b4 (patch)
treecee11116acce66ffcc7599dc13dcc9588d174620 /src/utils/spinner.rs
parent8b75080973e6caa3128e9673440a57deb38fc0c9 (diff)
downloadaichat-b3162a72b50f88d78ca3d57c1f8b3421cecfe2b4.tar.gz
refactor: shell execution with spinner and select prompt (#425)
Diffstat (limited to 'src/utils/spinner.rs')
-rw-r--r--src/utils/spinner.rs52
1 files changed, 52 insertions, 0 deletions
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(())
+ }
+}