utilities/ProgressSpinner: add interval field and new spinners
parent
2dfeb29b75
commit
48d4343082
|
@ -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
|
||||
|
|
|
@ -78,13 +78,16 @@ impl fmt::Display for StatusBar {
|
|||
|
||||
impl StatusBar {
|
||||
pub fn new(context: &Context, container: Box<dyn Component>) -> 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 => {}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
use super::*;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
|
||||
type AutoCompleteFn = Box<dyn Fn(&Context, &str) -> Vec<AutoCompleteEntry> + 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<String>) {
|
||||
pub fn set_custom_kind(&mut self, frames: Vec<String>, 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());
|
||||
|
|
|
@ -114,7 +114,15 @@ impl DotAddressable for TerminalSettings {
|
|||
#[serde(untagged)]
|
||||
pub enum ProgressSpinnerSequence {
|
||||
Integer(usize),
|
||||
Custom(Vec<String>),
|
||||
Custom {
|
||||
frames: Vec<String>,
|
||||
#[serde(default = "interval_ms_val")]
|
||||
interval_ms: u64,
|
||||
},
|
||||
}
|
||||
|
||||
const fn interval_ms_val() -> u64 {
|
||||
crate::components::utilities::ProgressSpinner::INTERVAL_MS
|
||||
}
|
||||
|
||||
impl DotAddressable for ProgressSpinnerSequence {}
|
||||
|
|
Loading…
Reference in New Issue