console-rs / dialoguer

Rust utility library for nice command line prompts and similar things
MIT License
1.33k stars 142 forks source link

Add header and footer options to (Fuzzy)Select (for making borders/tables) #305

Open Andrew15-5 opened 8 months ago

Andrew15-5 commented 8 months ago

Right now I only was able to make something like this:

image

But I had to redefine the style:

    let theme = ColorfulTheme {
        prompt_style: Style::new().for_stderr().white(),
        prompt_suffix: style(format!(
            "\n  {}\n  {:11}{:8}{:7}{:15}{}\n  {}",
            "-".repeat(58),
            "name",
            "fstype",
            "size",
            "label",
            "partlabel",
            "-".repeat(58),
        )).for_stderr().bold(),
        ..Default::default()
    };
FuzzySelect::with_theme(&theme)
.with_prompt("Which partition do you want to mount?")

And separately also define the item's Display trait implementation:

impl Display for Partition {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let map = |x| format!("{}", x);
        write!(
            f,
            "{:11}{:8}{:7}{:15}{}",
            self.name,
            self.fstype,
            self.size,
            self.label.as_ref().map_or("".into(), map).as_str(),
            self.partlabel.as_ref().map_or("".into(), map).as_str(),
        )
    }
}

I want to use this:

    let selected_index = FuzzySelect::with_theme(&theme)
        .with_prompt("Which partition do you want to mount?")
        .header(format!(
            "  {}\n  {:11}{:8}{:7}{:15}{}\n  {}",
            "-".repeat(58),
            "name",
            "fstype",
            "size",
            "label",
            "partlabel",
            "-".repeat(58),
        ))
        .footer(format!("  {}", "-".repeat(58)))
        .items(&items)
        .default(0)
        .interact_opt()
        .context("Failed to start interactive question.")?
        .unwrap_or_else(|| process::exit(1));

Where header will go under the prompt/cursor and before the first item. Footer goes after the first item. By default, there should be no header/footer. The only way I see right now fixing the implicit LF being inserted when header/footer is set is to use enum. So if they are set, then you would need to wrap your string in Some() and by default it is None.

Then also add the header_style and footer_style to the ColorfulTheme.

So basically I want this library to provide a nice way to create "tables" or just frames/borders to make prompts look even prettier.

Header can't go above the prompt, because this can be achieved by redefining the prompt_prefex (which is also not ideal if it has to be more than a few chars, but a good first middle ground).