User interaction

Ask for confirmation, selection, text input

inquire inquire-crates.io inquire-github inquire-lib.rs cat-command-line-interface cat-value-formatting

inquire provides several different prompts in order to interactively ask the user for information via the CLI.

use inquire::Confirm;
use inquire::Select;
use inquire::Text;

// The `inquire`` crate is used for creating interactive CLI prompts.
fn main() {
    let ans = Confirm::new("Do you want to proceed?")
        .with_default(false)
        .prompt()
        .expect("Failed to read input");
    println!("You answered: {:?}", ans);

    // Prompt for the user's name
    let name = Text::new("What's your name?")
        .prompt()
        .expect("Failed to read input");

    // Prompt for the user's favorite programming language
    let languages = vec!["Rust", "Python", "JavaScript", "C++", "Go", "Other"];
    let favorite_language = Select::new("What's your favorite programming language?", languages)
        //.with_help_message("Hint: it is Rust!")
        .prompt()
        .expect("Failed to read input");

    // Display the collected information
    println!("Hello, {}!", name);
    println!(
        "Your favorite programming language is {}.",
        favorite_language
    );
}

Display progress bars and spinners

indicatif indicatif-crates.io indicatif-github indicatif-lib.rs cat-command-line-interface

indicatif⮳ is a Rust library for indicating progress in command line applications to users.

This currently primarily provides progress bars and spinners as well as basic color support.

use std::thread;
use std::time::Duration;

use console::Emoji;
use console::Style;
use console::Term;
use indicatif::ProgressBar;
use indicatif::ProgressStyle;

fn spinner() -> anyhow::Result<()> {
    // `console` is a library for Rust that provides access to
    // terminal features, like styles and colors.
    // The terminal is abstracted through the `console::Term` type.
    let term = Term::stdout();
    term.clear_screen()?;
    term.write_line("Simulate the output of a compiler:")?;
    thread::sleep(Duration::from_millis(20));
    term.clear_line()?;
    // Print with styles / colors
    println!(
        "Target: {}",
        console::style("x86_64-unknown-linux-gnu").cyan()
    );

    // `indicatif` offers progress bars and spinners.
    // Create a progress bar with an indeterminate length:
    let pb = ProgressBar::new_spinner();
    pb.set_style(
        ProgressStyle::default_spinner()
            .template("{spinner:.green} [{elapsed_precise}] {msg}")
            .expect("Failed to set progress style"),
    );
    // Simulate different stages of the compilation process
    let stages = vec![
        ("Parsing source files", 1),
        ("Type checking", 3),
        ("Optimizing code", 2),
        ("Generating bytecode", 1),
        ("Linking objects", 1),
        ("Finalizing build", 1),
    ];
    // Spawns a background thread to tick the progress bar
    pb.enable_steady_tick(Duration::from_millis(100));
    for (stage, duration) in stages {
        pb.set_message(stage);
        thread::sleep(Duration::from_secs(duration));
    }
    pb.disable_steady_tick();
    pb.finish_with_message("Compilation complete!");
    // Print with style
    let cyan = Style::new().cyan();
    println!("Executable: {}", cyan.apply_to("./target/debug/my_program"));
    // Use emojis
    println!("{} Done!", Emoji("✨", ":-)"));
    Ok(())
}

fn main() -> anyhow::Result<()> {
    spinner()?;
    Ok(())
}
use std::thread;
use std::time::Duration;

use indicatif::ProgressBar;
use indicatif::ProgressStyle;

fn progress() {
    // Create a new progress bar with a length of 100
    // This progress bar by default draws directly to stderr.
    // If a non terminal is detected,
    // the progress bar will be completely hidden.
    let pb = ProgressBar::new(100);

    // Set a custom style for the progress bar
    pb.set_style(ProgressStyle::default_bar()
        // 40 characters wide and has cyan as primary style color and blue as alternative style color.
        .template("{spinner:.green} [{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}")
        .unwrap()
        .progress_chars("=>."));

    for _ in 0..100 {
        // Update the progress bar
        pb.inc(1);
        // Simulate work by sleeping for a short duration
        thread::sleep(Duration::from_millis(50));
    }
    // Finish the progress bar
    pb.finish_with_message("done"); // or use .finish();

    // Alternatively, you could wrap an iterator with a progress bar:
    // use indicatif::ProgressIterator;
    // for _ in (0..100).progress() {
    //     thread::sleep(Duration::from_millis(50));
    // }
}

fn main() -> anyhow::Result<()> {
    progress();
    Ok(())
}