tangled-cli 0.1.0

CLI for interacting with Tangled, an AT Protocol-based git collaboration platform
use std::future::Future;
use std::io::{self, IsTerminal};
use std::time::Duration;

use indicatif::{ProgressBar, ProgressStyle};

/// Runs `future` while displaying a transient spinner on stderr.
///
/// Progress indicators are hidden automatically when stderr is not a TTY, so
/// JSON output, tests, and redirected command output stay deterministic.
pub async fn with_spinner<T>(
    message: impl Into<String>,
    future: impl Future<Output = T>,
) -> T {
    let pb = spinner(message);
    let result = future.await;
    pb.finish_and_clear();
    result
}

pub fn spinner(message: impl Into<String>) -> ProgressBar {
    let pb = if io::stderr().is_terminal() {
        ProgressBar::new_spinner()
    } else {
        ProgressBar::hidden()
    };
    pb.set_style(
        ProgressStyle::with_template("{spinner:.cyan} {msg}")
            .expect("spinner template is valid")
            .tick_strings(&["", "", "", "", "", "", "", "", "", ""]),
    );
    pb.set_message(message.into());
    pb.enable_steady_tick(Duration::from_millis(100));
    pb
}

pub fn progress_bar(message: impl Into<String>) -> ProgressBar {
    let pb = if io::stderr().is_terminal() {
        ProgressBar::new(0)
    } else {
        ProgressBar::hidden()
    };
    pb.set_style(
        ProgressStyle::with_template(
            "{spinner:.cyan} {msg} [{wide_bar:.cyan/blue}] {pos}/{len}",
        )
        .expect("progress bar template is valid")
        .progress_chars("=>-"),
    );
    pb.set_message(message.into());
    pb.enable_steady_tick(Duration::from_millis(100));
    pb
}