use std::sync::Arc;
use super::renderer::{Renderer, StatusFields, Table, Writer};
use super::{Printer, Role};
pub struct SectionGuard<'p> {
pub(crate) printer: &'p Printer,
pub(crate) renderer: Arc<Renderer>,
pub(crate) sink: Arc<dyn Writer>,
pub(crate) depth: usize,
}
impl<'p> SectionGuard<'p> {
pub fn bullet(&self, text: impl Into<String>) -> &Self {
self.renderer
.render_bullet(self.sink.as_ref(), self.depth, &text.into());
self
}
pub fn kv(&self, key: impl Into<String>, value: impl Into<String>) -> &Self {
self.renderer.render_kv(&key.into(), &value.into());
self
}
pub fn kv_block<I, K, V>(&self, pairs: I) -> &Self
where
I: IntoIterator<Item = (K, V)>,
K: Into<String>,
V: Into<String>,
{
let pairs: Vec<(String, String)> = pairs
.into_iter()
.map(|(k, v)| (k.into(), v.into()))
.collect();
self.renderer
.render_kv_block(self.sink.as_ref(), self.depth, &pairs);
self
}
pub fn hint(&self, text: impl Into<String>) -> &Self {
self.renderer
.render_hint(self.sink.as_ref(), self.depth, &text.into());
self
}
pub fn note(&self, text: impl Into<String>) -> &Self {
self.renderer
.render_note(self.sink.as_ref(), self.depth, &text.into());
self
}
pub fn table(&self, table: Table) -> &Self {
self.renderer
.render_table(self.sink.as_ref(), self.depth, &table);
self
}
pub fn empty_state(&self, text: impl Into<String>) -> &Self {
self.renderer.render_section_empty_state(&text.into());
self
}
pub fn status_simple(&self, role: Role, subject: impl Into<String>) -> &Self {
let subject = subject.into();
self.renderer.render_status(
self.sink.as_ref(),
self.depth,
&StatusFields {
role,
subject: &subject,
detail: None,
duration: None,
target: None,
},
);
self
}
pub fn status(
&self,
role: Role,
subject: impl Into<String>,
) -> super::status_builder::StatusBuilder<'_> {
super::status_builder::StatusBuilder::new(
self.renderer.clone(),
self.sink.clone(),
self.depth,
role,
subject,
)
}
#[must_use = "section closes when SectionGuard is dropped; bind it"]
pub fn section(&self, name: impl Into<String>) -> SectionGuard<'_> {
self.renderer
.render_section_open(&name.into(), true);
SectionGuard {
printer: self.printer,
renderer: self.renderer.clone(),
sink: self.sink.clone(),
depth: self.depth + 1,
}
}
#[must_use = "section closes when SectionGuard is dropped; bind it"]
pub fn section_or_collapse(&self, name: impl Into<String>) -> SectionGuard<'_> {
self.renderer
.render_section_open(&name.into(), false);
SectionGuard {
printer: self.printer,
renderer: self.renderer.clone(),
sink: self.sink.clone(),
depth: self.depth + 1,
}
}
#[must_use]
pub fn spinner(&self, message: impl Into<String>) -> super::spinner::Spinner<'_> {
let message = message.into();
let bar = super::spinner::make_spinner_bar(
&self.printer.multi_progress,
&self.renderer,
self.printer.verbosity(),
&message,
);
super::spinner::Spinner {
renderer: self.renderer.clone(),
sink: self.sink.clone(),
depth: self.depth,
bar,
message,
finished: false,
_phantom: std::marker::PhantomData,
}
}
#[must_use]
pub fn progress_bar(
&self,
total: u64,
message: impl Into<String>,
) -> super::spinner::ProgressBar<'_> {
let bar = super::spinner::make_progress_bar(
&self.printer.multi_progress,
total,
self.printer.verbosity(),
&message.into(),
);
super::spinner::ProgressBar {
bar,
_phantom: std::marker::PhantomData,
}
}
pub fn run(
&self,
cmd: &mut std::process::Command,
label: impl Into<String>,
) -> std::io::Result<super::process::CommandOutput> {
super::process::run_command(
&self.renderer,
self.sink.as_ref(),
&self.printer.multi_progress,
self.depth,
cmd,
&label.into(),
)
}
pub fn close(self) {
}
}
impl Drop for SectionGuard<'_> {
fn drop(&mut self) {
self.renderer.render_section_close(self.sink.as_ref());
}
}