on 2158366 help sign in
helix/helix-term/src/ui/spinner.rs
75 lines 1.7 kB history raw
1use std::{collections::HashMap, time::SystemTime};
3#[derive(Default, Debug)]
4pub struct ProgressSpinners {
5 inner: HashMap<usize, Spinner>,
6}
8impl ProgressSpinners {
9 pub fn get(&self, id: usize) -> Option<&Spinner> {
10 self.inner.get(&id)
11 }
13 pub fn get_or_create(&mut self, id: usize) -> &mut Spinner {
14 self.inner.entry(id).or_insert_with(Spinner::default)
15 }
18impl Default for Spinner {
19 fn default() -> Self {
20 Self::dots(80)
21 }
24#[derive(Debug)]
25pub struct Spinner {
26 frames: Vec<&'static str>,
27 count: usize,
28 start: Option<SystemTime>,
29 interval: u64,
32impl Spinner {
33 /// Creates a new spinner with `frames` and `interval`.
34 /// Expects the frames count and interval to be greater than 0.
35 pub fn new(frames: Vec<&'static str>, interval: u64) -> Self {
36 let count = frames.len();
37 assert!(count > 0);
38 assert!(interval > 0);
40 Self {
41 frames,
42 count,
43 interval,
44 start: None,
45 }
46 }
48 pub fn dots(interval: u64) -> Self {
49 Self::new(vec!["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"], interval)
50 }
52 pub fn start(&mut self) {
53 self.start = Some(SystemTime::now());
54 }
56 pub fn frame(&self) -> Option<&str> {
57 let idx = (self
58 .start
59 .map(|time| SystemTime::now().duration_since(time))?
60 .ok()?
61 .as_millis()
62 / self.interval as u128) as usize
63 % self.count;
65 self.frames.get(idx).copied()
66 }
68 pub fn stop(&mut self) {
69 self.start = None;
70 }
72 pub fn is_stopped(&self) -> bool {
73 self.start.is_none()
74 }