dprint_cli_core/logging/
confirm.rs

1use anyhow::bail;
2use anyhow::Result;
3use crossterm::event::Event;
4use crossterm::event::KeyCode;
5
6use crate::logging::Logger;
7use crate::logging::LoggerRefreshItemKind;
8use crate::logging::LoggerTextItem;
9use crate::terminal::read_terminal_event;
10
11pub fn show_confirm(logger: &Logger, context_name: &str, prompt: &str, default_value: bool) -> Result<bool> {
12  let result = loop {
13    let text_items = vec![LoggerTextItem::Text(format!(
14      "{} ({}) \u{2588}", // show a cursor (block character)
15      prompt,
16      if default_value { "Y/n" } else { "y/N" }
17    ))];
18    logger.set_refresh_item(LoggerRefreshItemKind::Selection, text_items);
19
20    if let Event::Key(key_event) = read_terminal_event()? {
21      match &key_event.code {
22        KeyCode::Char(c) if *c == 'Y' || *c == 'y' => {
23          break true;
24        }
25        KeyCode::Char(c) if *c == 'N' || *c == 'n' => {
26          break false;
27        }
28        KeyCode::Enter => {
29          break default_value;
30        }
31        KeyCode::Esc => {
32          logger.remove_refresh_item(LoggerRefreshItemKind::Selection);
33          bail!("Confirmation cancelled.");
34        }
35        _ => {}
36      }
37    } else {
38      // cause a refresh anyway
39    }
40  };
41  logger.remove_refresh_item(LoggerRefreshItemKind::Selection);
42
43  logger.log_text_items(
44    &[LoggerTextItem::Text(format!("{} {}", prompt, if result { "Y" } else { "N" }))],
45    context_name,
46    crate::terminal::get_terminal_width(),
47  );
48
49  Ok(result)
50}