Files
nix-output/src/state.rs

91 lines
2.9 KiB
Rust

use std::{io, marker::PhantomData, rc::Rc};
use console::style;
use indicatif::{MultiProgress, ProgressBar, ProgressFinish, ProgressStyle};
use crate::handlers::{Handler, download::SubstituteHandler, global::GlobalHandler};
pub struct State {
pub multi_progress: Rc<MultiProgress>,
pub handlers: Vec<Box<dyn Handler>>,
pub term_width: u16,
pub separator: Option<ProgressBar>,
}
impl State {
pub fn new(term_width: u16) -> Self {
let mut state = Self {
multi_progress: Rc::new(MultiProgress::new()),
handlers: Vec::new(),
term_width,
separator: None,
};
state.plug(GlobalHandler);
state.plug(SubstituteHandler);
state
}
pub fn handle(&mut self, action: &crate::action::Action) -> color_eyre::Result<()> {
let mut prev_handlers = std::mem::take(&mut self.handlers);
// Check if terminal was resized
let (_, term_width) = console::Term::stderr().size();
if term_width != self.term_width {
self.term_width = term_width;
for handler in &mut prev_handlers {
handler.on_resize(self)?;
}
}
if let Some(separator) = &self.separator {
separator.tick();
}
// Applies handles
let mut retain_result = Ok(());
prev_handlers.retain_mut(|h| match h.handle(self, action) {
Ok(x) => x,
Err(err) => {
retain_result = Err(err);
false
}
});
let mut new_handlers = std::mem::replace(&mut self.handlers, prev_handlers);
self.handlers.append(&mut new_handlers);
retain_result
}
pub fn plug<H: Handler + 'static>(&mut self, handler: H) {
self.handlers.push(Box::new(handler))
}
pub fn add_pb(&mut self, pb: ProgressBar) -> ProgressBar {
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)
}
}