rework multibar
This commit is contained in:
10
src/main.rs
10
src/main.rs
@@ -7,7 +7,7 @@ use console::{Term, style};
|
|||||||
use indicatif::{MultiProgress, ProgressBar, ProgressStyle, TermLike};
|
use indicatif::{MultiProgress, ProgressBar, ProgressStyle, TermLike};
|
||||||
|
|
||||||
use crate::action::StartFields;
|
use crate::action::StartFields;
|
||||||
use crate::multibar::MultiBar;
|
use crate::multibar::{BarSegment, MultiBar};
|
||||||
use crate::state_manager::{BuildEnumState, BuildState, State, StateManager};
|
use crate::state_manager::{BuildEnumState, BuildState, State, StateManager};
|
||||||
|
|
||||||
static LAZY: LazyLock<i32> = LazyLock::new(|| {
|
static LAZY: LazyLock<i32> = LazyLock::new(|| {
|
||||||
@@ -89,10 +89,10 @@ fn main() -> Result<(), color_eyre::Report> {
|
|||||||
let term = Term::stdout();
|
let term = Term::stdout();
|
||||||
let empty = style("-").blue().to_string();
|
let empty = style("-").blue().to_string();
|
||||||
let bar = MultiBar([
|
let bar = MultiBar([
|
||||||
("=", 50, false),
|
BarSegment::Dynamic("=", 10),
|
||||||
(">", 1, true),
|
BarSegment::Static(">"),
|
||||||
(empty.as_str(), 3, false),
|
BarSegment::Dynamic(empty.as_str(), 3),
|
||||||
(" ", 30, false),
|
BarSegment::Dynamic(" ", 50),
|
||||||
])
|
])
|
||||||
.scale(u64::from(term.size().1 - 2));
|
.scale(u64::from(term.size().1 - 2));
|
||||||
println!("[{}]", bar);
|
println!("[{}]", bar);
|
||||||
|
|||||||
@@ -1,37 +1,92 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum BarSegment<'s> {
|
||||||
|
Dynamic(&'s str, u64),
|
||||||
|
Static(&'s str),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'s> BarSegment<'s> {
|
||||||
|
fn char(&self) -> &'s str {
|
||||||
|
match self {
|
||||||
|
BarSegment::Dynamic(c, _) => c,
|
||||||
|
BarSegment::Static(c) => c,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn length(&self) -> u64 {
|
||||||
|
match self {
|
||||||
|
BarSegment::Dynamic(c, len) => *len,
|
||||||
|
BarSegment::Static(c) => c.len() as u64,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_static(&self) -> bool {
|
||||||
|
matches!(self, BarSegment::Static(_))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scaled(&self, new_len: u64) -> Self {
|
||||||
|
match self {
|
||||||
|
BarSegment::Dynamic(c, _) => BarSegment::Dynamic(c, new_len),
|
||||||
|
BarSegment::Static(c) => BarSegment::Static(c),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MultiBar<'s, const N: usize>(pub [(&'s str, u64, bool); N]);
|
pub struct MultiBar<'s, const N: usize>(pub [BarSegment<'s>; N]);
|
||||||
|
|
||||||
impl<const N: usize> MultiBar<'_, N> {
|
impl<const N: usize> MultiBar<'_, N> {
|
||||||
/// Total length of the bar
|
fn dynamic_length(&self) -> u64 {
|
||||||
pub(crate) fn length(&self) -> u64 {
|
self.0
|
||||||
self.0.iter().map(|(_, len, _)| *len).sum::<u64>()
|
.iter()
|
||||||
|
.filter(|seg| !seg.is_static())
|
||||||
|
.map(|seg| seg.length())
|
||||||
|
.sum::<u64>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn static_length(&self) -> u64 {
|
||||||
|
self.0
|
||||||
|
.iter()
|
||||||
|
.filter(|seg| seg.is_static())
|
||||||
|
.map(|seg| seg.length())
|
||||||
|
.sum::<u64>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transforms the bar to be of target size
|
/// Transforms the bar to be of target size
|
||||||
|
/// Static parts remain the same length, dynamic parts are scaled proportionally
|
||||||
pub(crate) fn scale(&self, size: u64) -> Self {
|
pub(crate) fn scale(&self, size: u64) -> Self {
|
||||||
let length = std::cmp::max(self.length(), 1);
|
let static_len = self.static_length();
|
||||||
|
let dynamic_len = std::cmp::max(self.dynamic_length(), 1);
|
||||||
|
|
||||||
|
let available_size = size.saturating_sub(static_len);
|
||||||
|
|
||||||
let mut prev_prop = 0;
|
let mut prev_prop = 0;
|
||||||
let mut curr_prop = 0;
|
let mut curr_prop = 0;
|
||||||
|
|
||||||
let inner = self.0.map(|(c, len, const_len)| {
|
let inner = self.0.map(|seg| match seg {
|
||||||
if const_len {
|
BarSegment::Static(_) => seg,
|
||||||
return (c, len, const_len);
|
BarSegment::Dynamic(c, len) => {
|
||||||
}
|
|
||||||
curr_prop += len;
|
curr_prop += len;
|
||||||
let nb_chars = size * curr_prop / length - size * prev_prop / length;
|
let nb_chars = available_size * curr_prop / dynamic_len
|
||||||
|
- available_size * prev_prop / dynamic_len;
|
||||||
prev_prop = curr_prop;
|
prev_prop = curr_prop;
|
||||||
(c, nb_chars, const_len)
|
BarSegment::Dynamic(c, nb_chars)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self(inner)
|
Self(inner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize> fmt::Display for MultiBar<'_, N> {
|
impl<const N: usize> fmt::Display for MultiBar<'_, N> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
for &(c, len, _) in &self.0 {
|
for seg in &self.0 {
|
||||||
|
let (c, len) = match seg {
|
||||||
|
BarSegment::Dynamic(c, len) => (c, *len),
|
||||||
|
BarSegment::Static(c) => (c, c.len() as u64),
|
||||||
|
};
|
||||||
|
|
||||||
for _ in 0..len {
|
for _ in 0..len {
|
||||||
f.write_str(c)?;
|
f.write_str(c)?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ pub struct State<'a> {
|
|||||||
pub multi_progress: MultiProgress,
|
pub multi_progress: MultiProgress,
|
||||||
pub manager: StateManager<'a>,
|
pub manager: StateManager<'a>,
|
||||||
pub separator: Option<ProgressBar>,
|
pub separator: Option<ProgressBar>,
|
||||||
|
pub width: u16,
|
||||||
|
pub current_width: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> State<'a> {
|
impl<'a> State<'a> {
|
||||||
@@ -74,7 +76,6 @@ pub struct BuildState<'a> {
|
|||||||
pub path: Option<String>,
|
pub path: Option<String>,
|
||||||
pub progress_bar: Option<ProgressBar>,
|
pub progress_bar: Option<ProgressBar>,
|
||||||
pub state: BuildEnumState<'a>,
|
pub state: BuildEnumState<'a>,
|
||||||
ref_count: usize,
|
|
||||||
}
|
}
|
||||||
impl<'a> BuildState<'a> {
|
impl<'a> BuildState<'a> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
@@ -82,7 +83,6 @@ impl<'a> BuildState<'a> {
|
|||||||
path: None,
|
path: None,
|
||||||
progress_bar: None,
|
progress_bar: None,
|
||||||
state: BuildEnumState::Init,
|
state: BuildEnumState::Init,
|
||||||
ref_count: 1,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user