diff options
| author | Michelle Tilley <michelle@michelletilley.net> | 2026-03-26 19:19:47 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-27 02:19:47 +0000 |
| commit | b649a7ab8de6488c1341e94c37d032c07d5b3f13 (patch) | |
| tree | ca9aadc1175b8439dd85de135f3804681b755776 /crates/atuin-ai/src/tui/spinner.rs | |
| parent | fix: set WorkingDirectory in PowerShell Invoke-AtuinSearch (#3351) (diff) | |
| download | atuin-b649a7ab8de6488c1341e94c37d032c07d5b3f13.zip | |
feat: Use eye-declare for more performant and flexible AI TUI (#3343)
This PR replaces the mess of custom rendering code in Atuin AI with
[eye-declare](https://github.com/BinaryMuse/eye-declare), and updates
the TUI to feel more terminal-native: output appears inline and persists
in scrollback, so you can scroll up and look at previous conversations
for reference.
The "review" state — which used to exist between the LLM generating a
response and the user either executing or following up — has been
removed; just start typing to follow up with the LLM, or press `enter`
at the empty input box to execute the suggested command.
<img width="1203" height="633" alt="image"
src="https://github.com/user-attachments/assets/159ee447-9a2a-4edd-b56e-a79bf1aaaa94"
/>
Diffstat (limited to 'crates/atuin-ai/src/tui/spinner.rs')
| -rw-r--r-- | crates/atuin-ai/src/tui/spinner.rs | 99 |
1 files changed, 0 insertions, 99 deletions
diff --git a/crates/atuin-ai/src/tui/spinner.rs b/crates/atuin-ai/src/tui/spinner.rs deleted file mode 100644 index 138e0269..00000000 --- a/crates/atuin-ai/src/tui/spinner.rs +++ /dev/null @@ -1,99 +0,0 @@ -//! Spinner styles and configuration for TUI animations -//! -//! To experiment with different spinners, change `ACTIVE_SPINNER` below. - -use std::time::Duration; - -/// Active spinner style - change this to experiment with different styles -pub const ACTIVE_SPINNER: SpinnerStyle = SpinnerStyle::Dots; - -/// Spinner style definitions -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum SpinnerStyle { - /// Classic ASCII line spinner: / - \ | - Line, - /// Braille dots pattern - Dots, - /// Growing/shrinking dots - Pulse, - /// Simple arrow rotation - Arrow, - /// Block building - Block, -} - -impl SpinnerStyle { - /// Get the frames for this spinner style - pub const fn frames(&self) -> &'static [&'static str] { - match self { - SpinnerStyle::Line => &["/", "-", "\\", "|"], - SpinnerStyle::Dots => &["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"], - SpinnerStyle::Pulse => &["·", "•", "●", "•"], - SpinnerStyle::Arrow => &["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"], - SpinnerStyle::Block => &[ - "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█", "▉", "▊", "▋", "▌", "▍", "▎", "▏", - ], - } - } - - /// Get the recommended tick interval for this spinner style - /// Faster spinners need shorter intervals to look smooth - pub const fn tick_interval(&self) -> Duration { - match self { - SpinnerStyle::Line => Duration::from_millis(150), - SpinnerStyle::Dots => Duration::from_millis(80), - SpinnerStyle::Pulse => Duration::from_millis(200), - SpinnerStyle::Arrow => Duration::from_millis(100), - SpinnerStyle::Block => Duration::from_millis(80), - } - } - - /// Get the frame at the given index (wraps around) - pub fn frame_at(&self, index: usize) -> &'static str { - let frames = self.frames(); - frames[index % frames.len()] - } - - /// Get the number of frames in this spinner - pub fn frame_count(&self) -> usize { - self.frames().len() - } -} - -/// Get the active spinner's frame at the given index -pub fn active_frame(index: usize) -> &'static str { - ACTIVE_SPINNER.frame_at(index) -} - -/// Get the active spinner's tick interval -pub fn active_tick_interval() -> Duration { - ACTIVE_SPINNER.tick_interval() -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_frame_wrapping() { - let style = SpinnerStyle::Line; - assert_eq!(style.frame_at(0), "/"); - assert_eq!(style.frame_at(4), "/"); // wraps - assert_eq!(style.frame_at(5), "-"); - } - - #[test] - fn test_all_styles_have_frames() { - let styles = [ - SpinnerStyle::Line, - SpinnerStyle::Dots, - SpinnerStyle::Pulse, - SpinnerStyle::Arrow, - SpinnerStyle::Block, - ]; - for style in styles { - assert!(!style.frames().is_empty()); - assert!(style.tick_interval().as_millis() > 0); - } - } -} |
