work on multibar
This commit is contained in:
50
src/main.rs
50
src/main.rs
@@ -8,6 +8,7 @@ use crate::state_manager::{BuildEnumState, BuildState, State, StateManager};
|
||||
|
||||
pub mod action;
|
||||
pub mod action_raw;
|
||||
pub mod multibar;
|
||||
pub mod nix_path;
|
||||
pub mod state_manager;
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -62,35 +63,36 @@ impl TermLike for TextTerm {
|
||||
fn main() -> Result<(), color_eyre::Report> {
|
||||
color_eyre::install().unwrap();
|
||||
|
||||
let pb = ProgressBar::new(100);
|
||||
pb.set_draw_target(indicatif::ProgressDrawTarget::term_like(Box::new(TextTerm)));
|
||||
// let pb = ProgressBar::new(100);
|
||||
// pb.set_draw_target(indicatif::ProgressDrawTarget::term_like(Box::new(TextTerm)));
|
||||
//
|
||||
// pb.set_style(
|
||||
// ProgressStyle::default_bar()
|
||||
// .template("{msg} [{bar:40.cyan/blue}] {pos:>3}%")
|
||||
// .unwrap(),
|
||||
// );
|
||||
// pb.set_message("Example Progress Bar");
|
||||
// for i in 0..=5 {
|
||||
// pb.set_position(i);
|
||||
// sleep(Duration::from_millis(50));
|
||||
// }
|
||||
// pb.finish_and_clear();
|
||||
|
||||
pb.set_style(
|
||||
ProgressStyle::default_bar()
|
||||
.template("{msg} [{bar:40.cyan/blue}] {pos:>3}%")
|
||||
.unwrap(),
|
||||
);
|
||||
pb.set_message("Example Progress Bar");
|
||||
for i in 0..=5 {
|
||||
pb.set_position(i);
|
||||
sleep(Duration::from_millis(50));
|
||||
}
|
||||
pb.finish_and_clear();
|
||||
|
||||
return Ok(());
|
||||
// return Ok(());
|
||||
|
||||
let lines = std::fs::read_to_string("build.log")?;
|
||||
let lines = lines.lines().take(0).collect::<Vec<_>>().join("\n");
|
||||
// let lines = lines.lines().take(0).collect::<Vec<_>>().join("\n");
|
||||
|
||||
let mut state = State {
|
||||
progress: MultiProgress::new(),
|
||||
multi_progress: MultiProgress::new(),
|
||||
manager: StateManager::new(),
|
||||
separator: None,
|
||||
};
|
||||
|
||||
// let progress = MultiProgress::new();
|
||||
let lines_pb = state
|
||||
.progress
|
||||
.add(ProgressBar::new(lines.lines().count() as u64));
|
||||
// let lines_pb = state
|
||||
// .multi_progress
|
||||
// .add(ProgressBar::new(lines.lines().count() as u64));
|
||||
// progress.println("Parsing build.log...")?;
|
||||
// let pb1 = progress.add(ProgressBar::new(lines.lines().count() as u64));
|
||||
// pb1.set_style(
|
||||
@@ -111,15 +113,13 @@ fn main() -> Result<(), color_eyre::Report> {
|
||||
// let mut map = HashMap::new();
|
||||
|
||||
for line in lines.lines() {
|
||||
lines_pb.inc(1);
|
||||
// lines_pb.inc(1);
|
||||
let line = line.strip_prefix("@nix ").unwrap_or(line);
|
||||
sleep(Duration::from_millis(1));
|
||||
let action = action::Action::parse(line)?;
|
||||
match action {
|
||||
action::Action::Msg { level, msg } => {
|
||||
state
|
||||
.progress
|
||||
.println(format!("MSG (level {level}): {msg}"))?;
|
||||
state.println(format!("MSG (level {level}): {msg}"))?;
|
||||
}
|
||||
action::Action::Start {
|
||||
start_type,
|
||||
@@ -192,7 +192,7 @@ fn main() -> Result<(), color_eyre::Report> {
|
||||
}
|
||||
action::Action::Result { id, fields } => match fields {
|
||||
action::ResultFields::FetchStatus(status) => {
|
||||
state.progress.println(format!(
|
||||
state.println(format!(
|
||||
"RESULT FetchStatus (id: {}): status={}",
|
||||
id, status
|
||||
))?;
|
||||
|
||||
39
src/multibar.rs
Normal file
39
src/multibar.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MultiBar<'s, const N: usize>(pub [(&'s str, u64); N]);
|
||||
|
||||
impl<const N: usize> MultiBar<'_, N> {
|
||||
/// Total length of the bar
|
||||
pub(crate) fn length(&self) -> u64 {
|
||||
self.0.iter().map(|(_, len)| *len).sum()
|
||||
}
|
||||
|
||||
/// Transforms the bar to be of target size
|
||||
pub(crate) fn scale(&self, size: u64) -> Self {
|
||||
let length = std::cmp::max(self.length(), 1);
|
||||
let mut prev_prop = 0;
|
||||
let mut curr_prop = 0;
|
||||
|
||||
let inner = self.0.map(|(c, len)| {
|
||||
curr_prop += len;
|
||||
let nb_chars = size * curr_prop / length - size * prev_prop / length;
|
||||
prev_prop = curr_prop;
|
||||
(c, nb_chars)
|
||||
});
|
||||
|
||||
Self(inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> fmt::Display for MultiBar<'_, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for &(c, len) in &self.0 {
|
||||
for _ in 0..len {
|
||||
f.write_str(c)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,43 @@
|
||||
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
|
||||
use std::{borrow::Cow, collections::HashMap};
|
||||
use console::style;
|
||||
use indicatif::{MultiProgress, ProgressBar, ProgressFinish, ProgressStyle};
|
||||
use std::{borrow::Cow, collections::HashMap, io};
|
||||
|
||||
use crate::{action::StartFields, nix_path};
|
||||
|
||||
pub struct State<'a> {
|
||||
pub progress: MultiProgress,
|
||||
pub multi_progress: MultiProgress,
|
||||
pub manager: StateManager<'a>,
|
||||
pub separator: Option<ProgressBar>,
|
||||
}
|
||||
|
||||
impl<'a> State<'a> {
|
||||
pub fn add_pb(&mut self, pb: ProgressBar) -> ProgressBar {
|
||||
self.progress.add(pb)
|
||||
let separator = self.separator.get_or_insert_with(|| {
|
||||
let separator = ProgressBar::new_spinner()
|
||||
.with_style(
|
||||
ProgressStyle::default_spinner()
|
||||
.template(&style("··{wide_msg:<}").dim().to_string())
|
||||
.expect("invalid template"),
|
||||
)
|
||||
.with_message("·".repeat(512))
|
||||
.with_finish(ProgressFinish::AndClear);
|
||||
|
||||
let separator = self.multi_progress.insert(0, separator);
|
||||
separator.set_length(0);
|
||||
separator
|
||||
});
|
||||
|
||||
self.multi_progress.insert_after(separator, pb)
|
||||
// self.progress.add(pb)
|
||||
}
|
||||
pub fn add_pb_before(&mut self, before: &ProgressBar, pb: ProgressBar) -> ProgressBar {
|
||||
self.multi_progress.insert_before(before, pb)
|
||||
}
|
||||
pub fn add_pb_after(&mut self, after: &ProgressBar, pb: ProgressBar) -> ProgressBar {
|
||||
self.multi_progress.insert_after(after, pb)
|
||||
}
|
||||
pub fn println<I: AsRef<str>>(&self, msg: I) -> io::Result<()> {
|
||||
self.multi_progress.println(msg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,10 +54,12 @@ pub enum BuildEnumState<'a> {
|
||||
},
|
||||
SubstituteCopy {
|
||||
path: Cow<'a, str>,
|
||||
bar: ProgressBar,
|
||||
},
|
||||
SubstituteFetch {
|
||||
path: Cow<'a, str>,
|
||||
bar: ProgressBar,
|
||||
extract_bar: ProgressBar,
|
||||
download_bar: ProgressBar,
|
||||
},
|
||||
Query {
|
||||
path: Cow<'a, str>,
|
||||
@@ -74,12 +103,34 @@ impl<'a> BuildState<'a> {
|
||||
BuildEnumState::Substitute { source, target }
|
||||
}
|
||||
(BuildEnumState::Substitute { .. }, StartFields::CopyPath { path, .. }) => {
|
||||
BuildEnumState::SubstituteCopy { path }
|
||||
let name = nix_path::extract_package_name(&path).unwrap_or("unknown".to_string());
|
||||
let bar = state.add_pb(ProgressBar::new(100));
|
||||
bar.set_message(format!("Copying substitute for {}", name));
|
||||
bar.set_style(
|
||||
ProgressStyle::default_bar()
|
||||
.template("{prefix}{msg} [{bar:40.cyan/blue}] {pos:>3}%")
|
||||
.unwrap()
|
||||
.progress_chars("=> "),
|
||||
);
|
||||
bar.tick();
|
||||
BuildEnumState::SubstituteCopy { path, bar }
|
||||
}
|
||||
(BuildEnumState::SubstituteCopy { path }, StartFields::FileTransfer { .. }) => {
|
||||
(BuildEnumState::SubstituteCopy { path, bar }, StartFields::FileTransfer { .. }) => {
|
||||
let download_bar = state.add_pb_after(bar, ProgressBar::new(100));
|
||||
let name = nix_path::extract_package_name(path).unwrap_or("unknown".to_string());
|
||||
download_bar.set_message(format!("Fetching substitute for {}", name));
|
||||
download_bar.set_style(
|
||||
ProgressStyle::default_bar()
|
||||
.template("{prefix}{msg} [{bar:40.cyan/blue}] {pos:>3}%")
|
||||
.unwrap()
|
||||
.progress_chars("=> "),
|
||||
);
|
||||
download_bar.set_prefix("=== ");
|
||||
download_bar.tick();
|
||||
BuildEnumState::SubstituteFetch {
|
||||
path: path.clone(),
|
||||
bar: state.add_pb(ProgressBar::new(100)),
|
||||
extract_bar: bar.clone(),
|
||||
download_bar,
|
||||
}
|
||||
}
|
||||
(_, StartFields::Unknown) => BuildEnumState::Unknown,
|
||||
@@ -94,29 +145,23 @@ impl<'a> BuildState<'a> {
|
||||
pub fn tick(&mut self, state: &mut State<'a>) {
|
||||
match &self.state {
|
||||
BuildEnumState::QueryFetch { target } => {
|
||||
let pb = state.progress.add(ProgressBar::new_spinner());
|
||||
let pb = state.add_pb(ProgressBar::new_spinner());
|
||||
pb.set_message(format!("Fetching info for {}", target));
|
||||
pb.enable_steady_tick(std::time::Duration::from_millis(100));
|
||||
self.progress_bar = Some(pb);
|
||||
}
|
||||
BuildEnumState::SubstituteFetch { path, bar } => {
|
||||
let name = nix_path::extract_package_name(path).unwrap_or("unknown".to_string());
|
||||
bar.set_message(format!("Fetching substitute for {}", name));
|
||||
bar.set_style(
|
||||
ProgressStyle::default_bar()
|
||||
.template("{msg} [{bar:40.cyan/blue}] {pos:>3}%")
|
||||
.unwrap()
|
||||
.progress_chars("=> "),
|
||||
);
|
||||
// bar.enable_steady_tick(std::time::Duration::from_millis(100));
|
||||
// self.progress_bar = Some(bar.clone());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
pub fn progress(&mut self, done: u64, expected: u64) {
|
||||
match &self.state {
|
||||
BuildEnumState::SubstituteFetch { bar, .. } => {
|
||||
BuildEnumState::SubstituteFetch { download_bar, .. } => {
|
||||
let percentage = (done * 100 / expected) as u64;
|
||||
if percentage > download_bar.position() {
|
||||
download_bar.set_position(percentage);
|
||||
};
|
||||
}
|
||||
BuildEnumState::SubstituteCopy { path, bar } => {
|
||||
let percentage = (done * 100 / expected) as u64;
|
||||
if percentage > bar.position() {
|
||||
bar.set_position(percentage);
|
||||
|
||||
Reference in New Issue
Block a user