diff --git a/docs/meli.conf.5 b/docs/meli.conf.5 index 8c856ab3..56197ada 100644 --- a/docs/meli.conf.5 +++ b/docs/meli.conf.5 @@ -1039,49 +1039,67 @@ This setting can be toggled with String to show in status bar if mouse is active. .\" default value .Pq Em 🖱️ -.It Ic progress_spinner_sequence Ar Either \&< Integer, [String] \&> -Choose between 30-something built in sequences (integers between 0-30) or define your own list of strings for the progress spinner animation. +.It Ic progress_spinner_sequence Ar Either \&< Integer, ProgressSpinner \&> +Choose between 37 built in sequences (integers between 0-36) or define your own list of strings for the progress spinner animation. Set to an empty array to disable the progress spinner. .\" default value -.Pq Em 19 +.Pq Em 20 +.Pp Builtin sequences are: .Bd -literal -0 ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"] -1 ["⣀", "⣄", "⣤", "⣦", "⣶", "⣷", "⣿"] -2 ["⣀", "⣄", "⣆", "⣇", "⣧", "⣷", "⣿"] -3 ["○", "◔", "◐", "◕", "⬤"] -4 ["□", "◱", "◧", "▣", "■"] -5 ["□", "◱", "▨", "▩", "■"] -6 ["□", "◱", "▥", "▦", "■"] -7 ["░", "▒", "▓", "█"] -8 ["░", "█"] -9 ["⬜", "⬛"] -10 ["▱", "▰"] -11 ["▭", "◼"] -12 ["▯", "▮"] -13 ["◯", "⬤"] -14 ["⚪", "⚫"] -15 ["▖", "▗", "▘", "▝", "▞", "▚", "▙", "▟", "▜", "▛"] -16 ["|", "/", "-", "\\"] -17 [".", "o", "O", "@", "*"] -18 ["◡◡", "⊙⊙", "◠◠", "⊙⊙"] -19 ["◜ ", " ◝", " ◞", "◟ "] -10 ["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"] -11 ["▁", "▃", "▄", "▅", "▆", "▇", "█", "▇", "▆", "▅", "▄", "▃"] -22 ["▉", "▊", "▋", "▌", "▍", "▎", "▏", "▎", "▍", "▌", "▋", "▊", "▉"] -23 ["▖", "▘", "▝", "▗"] -24 ["▌", "▀", "▐", "▄"] -25 ["┤", "┘", "┴", "└", "├", "┌", "┬", "┐"] -26 ["◢", "◣", "◤", "◥"] -27 ["⠁", "⠂", "⠄", "⡀", "⢀", "⠠", "⠐", "⠈"] -28 ["⢎⡰", "⢎⡡", "⢎⡑", "⢎⠱", "⠎⡱", "⢊⡱", "⢌⡱", "⢆⡱"] -29 [".", "o", "O", "°", "O", "o", "."] +0 ["-", "\\", "|", "/"] +1 ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"] +2 ["⣀", "⣄", "⣤", "⣦", "⣶", "⣷", "⣿"] +3 ["⣀", "⣄", "⣆", "⣇", "⣧", "⣷", "⣿"] +4 ["○", "◔", "◐", "◕", "⬤"] +5 ["□", "◱", "◧", "▣", "■"] +6 ["□", "◱", "▨", "▩", "■"] +7 ["□", "◱", "▥", "▦", "■"] +8 ["░", "▒", "▓", "█"] +9 ["░", "█"] +10 ["⬜", "⬛"] +11 ["▱", "▰"] +12 ["▭", "◼"] +13 ["▯", "▮"] +14 ["◯", "⬤"] +15 ["⚪", "⚫"] +16 ["▖", "▗", "▘", "▝", "▞", "▚", "▙", "▟", "▜", "▛"] +17 ["|", "/", "-", "\\"] +18 [".", "o", "O", "@", "*"] +19 ["◡◡", "⊙⊙", "◠◠", "⊙⊙"] +20 ["◜ ", " ◝", " ◞", "◟ "] +21 ["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"] +22 ["▁", "▃", "▄", "▅", "▆", "▇", "█", "▇", "▆", "▅", "▄", "▃"] +23 [ "▉", "▊", "▋", "▌", "▍", "▎", "▏", "▎", "▍", "▌", "▋", "▊", "▉" ] +24 ["▖", "▘", "▝", "▗"] +25 ["▌", "▀", "▐", "▄"] +26 ["┤", "┘", "┴", "└", "├", "┌", "┬", "┐"] +27 ["◢", "◣", "◤", "◥"] +28 ["⠁", "⠂", "⠄", "⡀", "⢀", "⠠", "⠐", "⠈"] +29 ["⢎⡰", "⢎⡡", "⢎⡑", "⢎⠱", "⠎⡱", "⢊⡱", "⢌⡱", "⢆⡱"] +30 [".", "o", "O", "°", "O", "o", "."] +31 ["㊂", "㊀", "㊁"] +32 ["💛 ", "💙 ", "💜 ", "💚 ", "❤️ "] +33 [ "🕛 ", "🕐 ", "🕑 ", "🕒 ", "🕓 ", "🕔 ", "🕕 ", "🕖 ", "🕗 ", "🕘 ", "🕙 ", "🕚 " ] +34 ["🌍 ", "🌎 ", "🌏 "] +35 [ "[ ]", "[= ]", "[== ]", "[=== ]", "[ ===]", "[ ==]", "[ =]", "[ ]", "[ =]", "[ ==]", "[ ===]", "[====]", "[=== ]", "[== ]", "[= ]" ] +36 ["🌑 ", "🌒 ", "🌓 ", "🌔 ", "🌕 ", "🌖 ", "🌗 ", "🌘 "] .Ed -Or, define an array of strings each consisting of a frame in the progress sequence indicator: +.Pp +Or, define an array of strings each consisting of a frame in the progress sequence indicator for a custom spinner: +.Bl -tag -width 36n +.It Ic interval_ms Ar u64 +.Pq Em optional +Frame interval. +.\" default value +.Pq 50 +.It Ic frames Ar [String] +The animation frames. +.El +.Pp +Example: .Bd -literal -# 𝄈⡂″⡈߳܃⢂:߳̈⢁܄ː“⢐″„⠑։ ⡁⡈;ܹ⡂։𝂬̤⡂꞉⣀ܹ⢁⠊𝄈⠉⠑ܸ̈׃ ;⢐;߳⠡܉˸⠒߳꞉⁚𝂬⠑⠒܅⠊;⠔⠢܄ ”⠉ֵ”⢂⢁̈⁚⠊˸⠌ܸ̤⣀𝂬⠤⠨⠢‥¨ ⡠܉꞉꞉⠑׃⠑⡐⠨؛ܸ܆„ܹ⡈⢁;⢄܄؛ ܲ⢄⠡⡁‥؛ܲ⢂“⢈։⠔⢄”꞉܉⠔ -# Taken from @SmoothUnicode@botsin.space -progress_spinner_sequence = ["։","𝄈","⡂","″","⡈߳","܃","⢂",":߳̈","⢁","܄","ː","“","⢐","″","„","⠑","։"," ","⡁","⡈",";ܹ","⡂","։","𝂬̤","⡂","꞉","⣀ܹ","⢁","⠊","𝄈","⠉","⠑ܸ̈","׃"," ",";","⢐",";߳","⠡","܉","˸","⠒߳","꞉","⁚","𝂬","⠑","⠒","܅","⠊",";","⠔","⠢","܄"," ","”","⠉ֵ","”","⢂","⢁̈","⁚","⠊","˸","⠌ܸ̤","⣀","𝂬","⠤","⠨","⠢","‥","¨"," ","⡠","܉","꞉","꞉","⠑","׃","⠑","⡐","⠨","؛ܸ","܆","„ܹ","⡈","⢁",";","⢄܄","؛"," ܲ","⢄","⠡","⡁","‥","؛ܲ","⢂","“","⢈","։","⠔","⢄","”","꞉","܉","⠔"] +progress_spinner_sequence = { interval_ms = 150, frames = [ "-", "=", "≡" ] } .Ed .El .Sh LOG diff --git a/src/components/utilities.rs b/src/components/utilities.rs index 69bf2d72..406c7136 100644 --- a/src/components/utilities.rs +++ b/src/components/utilities.rs @@ -78,13 +78,16 @@ impl fmt::Display for StatusBar { impl StatusBar { pub fn new(context: &Context, container: Box) -> Self { - let mut progress_spinner = ProgressSpinner::new(19, context); + let mut progress_spinner = ProgressSpinner::new(20, context); match context.settings.terminal.progress_spinner_sequence.as_ref() { Some(conf::terminal::ProgressSpinnerSequence::Integer(k)) => { progress_spinner.set_kind(*k); } - Some(conf::terminal::ProgressSpinnerSequence::Custom(ref s)) => { - progress_spinner.set_custom_kind(s.clone()); + Some(conf::terminal::ProgressSpinnerSequence::Custom { + ref frames, + ref interval_ms, + }) => { + progress_spinner.set_custom_kind(frames.clone(), *interval_ms); } None => {} } @@ -472,13 +475,16 @@ impl Component for StatusBar { match event { UIEvent::ConfigReload { old_settings: _ } => { - let mut progress_spinner = ProgressSpinner::new(19, context); + let mut progress_spinner = ProgressSpinner::new(20, context); match context.settings.terminal.progress_spinner_sequence.as_ref() { Some(conf::terminal::ProgressSpinnerSequence::Integer(k)) => { progress_spinner.set_kind(*k); } - Some(conf::terminal::ProgressSpinnerSequence::Custom(ref s)) => { - progress_spinner.set_custom_kind(s.clone()); + Some(conf::terminal::ProgressSpinnerSequence::Custom { + ref frames, + ref interval_ms, + }) => { + progress_spinner.set_custom_kind(frames.clone(), *interval_ms); } None => {} } diff --git a/src/components/utilities/widgets.rs b/src/components/utilities/widgets.rs index 361f0841..7082aebc 100644 --- a/src/components/utilities/widgets.rs +++ b/src/components/utilities/widgets.rs @@ -22,6 +22,7 @@ use super::*; use std::borrow::Cow; use std::collections::HashMap; +use std::time::Duration; type AutoCompleteFn = Box Vec + Send + Sync>; @@ -1238,54 +1239,93 @@ pub struct ProgressSpinner { } impl ProgressSpinner { - pub const KINDS: [&'static [&'static str]; 30] = [ - &["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"], - &["⣀", "⣄", "⣤", "⣦", "⣶", "⣷", "⣿"], - &["⣀", "⣄", "⣆", "⣇", "⣧", "⣷", "⣿"], - &["○", "◔", "◐", "◕", "⬤"], - &["□", "◱", "◧", "▣", "■"], - &["□", "◱", "▨", "▩", "■"], - &["□", "◱", "▥", "▦", "■"], - &["░", "▒", "▓", "█"], - &["░", "█"], - &["⬜", "⬛"], - &["▱", "▰"], - &["▭", "◼"], - &["▯", "▮"], - &["◯", "⬤"], - &["⚪", "⚫"], - &["▖", "▗", "▘", "▝", "▞", "▚", "▙", "▟", "▜", "▛"], - &["|", "/", "-", "\\"], - &[".", "o", "O", "@", "*"], - &["◡◡", "⊙⊙", "◠◠", "⊙⊙"], - &["◜ ", " ◝", " ◞", "◟ "], - &["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"], - &["▁", "▃", "▄", "▅", "▆", "▇", "█", "▇", "▆", "▅", "▄", "▃"], - &[ - "▉", "▊", "▋", "▌", "▍", "▎", "▏", "▎", "▍", "▌", "▋", "▊", "▉", - ], - &["▖", "▘", "▝", "▗"], - &["▌", "▀", "▐", "▄"], - &["┤", "┘", "┴", "└", "├", "┌", "┬", "┐"], - &["◢", "◣", "◤", "◥"], - &["⠁", "⠂", "⠄", "⡀", "⢀", "⠠", "⠐", "⠈"], - &["⢎⡰", "⢎⡡", "⢎⡑", "⢎⠱", "⠎⡱", "⢊⡱", "⢌⡱", "⢆⡱"], - &[".", "o", "O", "°", "O", "o", "."], + pub const KINDS: [(Duration, &'static [&'static str]); 37] = [ + (Duration::from_millis(130), &["-", "\\", "|", "/"]), + (Self::INTERVAL, &["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"]), + (Self::INTERVAL, &["⣀", "⣄", "⣤", "⣦", "⣶", "⣷", "⣿"]), + (Self::INTERVAL, &["⣀", "⣄", "⣆", "⣇", "⣧", "⣷", "⣿"]), + (Self::INTERVAL, &["○", "◔", "◐", "◕", "⬤"]), + (Self::INTERVAL, &["□", "◱", "◧", "▣", "■"]), + (Self::INTERVAL, &["□", "◱", "▨", "▩", "■"]), + (Self::INTERVAL, &["□", "◱", "▥", "▦", "■"]), + (Self::INTERVAL, &["░", "▒", "▓", "█"]), + (Self::INTERVAL, &["░", "█"]), + (Self::INTERVAL, &["⬜", "⬛"]), + (Self::INTERVAL, &["▱", "▰"]), + (Self::INTERVAL, &["▭", "◼"]), + (Self::INTERVAL, &["▯", "▮"]), + (Self::INTERVAL, &["◯", "⬤"]), + (Self::INTERVAL, &["⚪", "⚫"]), + ( + Self::INTERVAL, + &["▖", "▗", "▘", "▝", "▞", "▚", "▙", "▟", "▜", "▛"], + ), + (Self::INTERVAL, &["|", "/", "-", "\\"]), + (Self::INTERVAL, &[".", "o", "O", "@", "*"]), + (Self::INTERVAL, &["◡◡", "⊙⊙", "◠◠", "⊙⊙"]), + (Self::INTERVAL, &["◜ ", " ◝", " ◞", "◟ "]), + (Self::INTERVAL, &["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"]), + ( + Self::INTERVAL, + &["▁", "▃", "▄", "▅", "▆", "▇", "█", "▇", "▆", "▅", "▄", "▃"], + ), + ( + Self::INTERVAL, + &[ + "▉", "▊", "▋", "▌", "▍", "▎", "▏", "▎", "▍", "▌", "▋", "▊", "▉", + ], + ), + (Self::INTERVAL, &["▖", "▘", "▝", "▗"]), + (Self::INTERVAL, &["▌", "▀", "▐", "▄"]), + (Self::INTERVAL, &["┤", "┘", "┴", "└", "├", "┌", "┬", "┐"]), + (Self::INTERVAL, &["◢", "◣", "◤", "◥"]), + (Self::INTERVAL, &["⠁", "⠂", "⠄", "⡀", "⢀", "⠠", "⠐", "⠈"]), + ( + Self::INTERVAL, + &["⢎⡰", "⢎⡡", "⢎⡑", "⢎⠱", "⠎⡱", "⢊⡱", "⢌⡱", "⢆⡱"], + ), + (Self::INTERVAL, &[".", "o", "O", "°", "O", "o", "."]), + (Duration::from_millis(100), &["㊂", "㊀", "㊁"]), + ( + Duration::from_millis(100), + &["💛 ", "💙 ", "💜 ", "💚 ", "❤️ "], + ), + ( + Duration::from_millis(100), + &[ + "🕛 ", "🕐 ", "🕑 ", "🕒 ", "🕓 ", "🕔 ", "🕕 ", "🕖 ", "🕗 ", "🕘 ", "🕙 ", "🕚 ", + ], + ), + (Duration::from_millis(100), &["🌍 ", "🌎 ", "🌏 "]), + ( + Duration::from_millis(80), + &[ + "[ ]", "[= ]", "[== ]", "[=== ]", "[ ===]", "[ ==]", "[ =]", "[ ]", + "[ =]", "[ ==]", "[ ===]", "[====]", "[=== ]", "[== ]", "[= ]", + ], + ), + ( + Duration::from_millis(80), + &["🌑 ", "🌒 ", "🌓 ", "🌔 ", "🌕 ", "🌖 ", "🌗 ", "🌘 "], + ), ]; - const INTERVAL: std::time::Duration = std::time::Duration::from_millis(50); + pub const INTERVAL_MS: u64 = 50; + const INTERVAL: std::time::Duration = std::time::Duration::from_millis(Self::INTERVAL_MS); pub fn new(kind: usize, context: &Context) -> Self { - let timer = context - .job_executor - .clone() - .create_timer(Self::INTERVAL, Self::INTERVAL); let kind = kind % Self::KINDS.len(); let width = Self::KINDS[kind] + .1 .iter() .map(|f| f.grapheme_len()) .max() .unwrap_or(0); + let interval = Self::KINDS[kind].0; + let timer = context + .job_executor + .clone() + .create_timer(interval, interval); let mut theme_attr = crate::conf::value(context, "status.bar"); if !context.settings.terminal.use_color() { theme_attr.attrs |= Attr::REVERSE; @@ -1310,21 +1350,25 @@ impl ProgressSpinner { pub fn set_kind(&mut self, kind: usize) { self.stage = 0; self.width = Self::KINDS[kind % Self::KINDS.len()] + .1 .iter() .map(|f| f.grapheme_len()) .max() .unwrap_or(0); self.kind = Ok(kind % Self::KINDS.len()); + let interval = Self::KINDS[kind % Self::KINDS.len()].0; + self.timer.set_interval(interval); self.dirty = true; } - pub fn set_custom_kind(&mut self, custom: Vec) { + pub fn set_custom_kind(&mut self, frames: Vec, interval: u64) { self.stage = 0; - self.width = custom.iter().map(|f| f.grapheme_len()).max().unwrap_or(0); + self.width = frames.iter().map(|f| f.grapheme_len()).max().unwrap_or(0); if self.width == 0 { self.stop(); } - self.kind = Err(custom); + self.kind = Err(frames); + self.timer.set_interval(Duration::from_millis(interval)); self.dirty = true; } @@ -1356,7 +1400,7 @@ impl Component for ProgressSpinner { if self.active { write_string_to_grid( match self.kind.as_ref() { - Ok(kind) => Self::KINDS[*kind][self.stage].as_ref(), + Ok(kind) => (Self::KINDS[*kind].1)[self.stage].as_ref(), Err(custom) => custom[self.stage].as_ref(), }, grid, @@ -1377,7 +1421,7 @@ impl Component for ProgressSpinner { UIEvent::Timer(id) if *id == self.timer.id() => { match self.kind.as_ref() { Ok(kind) => { - self.stage = (self.stage + 1).wrapping_rem(Self::KINDS[*kind].len()); + self.stage = (self.stage + 1).wrapping_rem(Self::KINDS[*kind].1.len()); } Err(custom) => { self.stage = (self.stage + 1).wrapping_rem(custom.len()); diff --git a/src/conf/terminal.rs b/src/conf/terminal.rs index 088836e2..21c2b31b 100644 --- a/src/conf/terminal.rs +++ b/src/conf/terminal.rs @@ -114,7 +114,15 @@ impl DotAddressable for TerminalSettings { #[serde(untagged)] pub enum ProgressSpinnerSequence { Integer(usize), - Custom(Vec), + Custom { + frames: Vec, + #[serde(default = "interval_ms_val")] + interval_ms: u64, + }, +} + +const fn interval_ms_val() -> u64 { + crate::components::utilities::ProgressSpinner::INTERVAL_MS } impl DotAddressable for ProgressSpinnerSequence {}