1use super::Ui;
2use anyhow::{Result, bail};
3use dialoguer::{Confirm, Input, Select, theme::ColorfulTheme};
4use std::io::Write;
5
6impl<W: Write> Ui<W> {
7 pub fn page_title(&mut self, title: &str) {
8 let _ = title;
9 }
10
11 pub fn confirm(&mut self, message: &str, default: bool) -> Result<bool> {
12 if self.default_yes {
13 return Ok(true);
14 }
15
16 Confirm::with_theme(&ColorfulTheme::default())
17 .with_prompt(message)
18 .default(default)
19 .interact()
20 .map_err(Into::into)
21 }
22
23 pub fn prompt_text(&mut self, message: &str, default: Option<&str>) -> Result<String> {
24 let theme = ColorfulTheme::default();
25 let input = Input::<String>::with_theme(&theme).with_prompt(message);
26 let input = if let Some(default) = default {
27 input.default(default.to_string())
28 } else {
29 input
30 };
31
32 input.interact_text().map_err(Into::into)
33 }
34
35 pub fn prompt_number(&mut self, message: &str, max: usize) -> Result<usize> {
36 if max == 0 {
37 bail!("cannot prompt for selection from an empty list");
38 }
39
40 loop {
41 let value = self.prompt_text(message, None)?;
42 match value.trim().parse::<usize>() {
43 Ok(number) if (1..=max).contains(&number) => return Ok(number - 1),
44 _ => self.warn(format!("Enter a number between 1 and {max}.")),
45 }
46 }
47 }
48
49 pub fn select_index(&mut self, message: &str, items: &[String]) -> Result<usize> {
50 if items.is_empty() {
51 bail!("cannot prompt for selection from an empty list");
52 }
53
54 Select::with_theme(&ColorfulTheme::default())
55 .with_prompt(message)
56 .items(items)
57 .default(0)
58 .interact()
59 .map_err(Into::into)
60 }
61}