cli_prompts/prompts/
confirmation.rs1use crate::{engine::CommandBuffer, input::Key, prompts::EventOutcome, style::ConfirmationStyle};
2
3use super::Prompt;
4
5pub struct Confirmation {
29 label: String,
30 default_positive: bool,
31 is_submitted: bool,
32 selected_option: Option<bool>,
33 style: ConfirmationStyle,
34}
35
36impl Confirmation {
37
38 pub fn new<S: Into<String>>(label: S) -> Self {
40 Confirmation {
41 label: label.into(),
42 default_positive: true,
43 is_submitted: false,
44 selected_option: None,
45 style: ConfirmationStyle::default(),
46 }
47 }
48
49 pub fn default_positive(mut self, default_positive: bool) -> Self {
51 self.default_positive = default_positive;
52 self
53 }
54
55 pub fn style(mut self, s: ConfirmationStyle) -> Self {
57 self.style = s;
58 self
59 }
60}
61
62impl Prompt<bool> for Confirmation {
63 fn draw(&self, commands: &mut impl CommandBuffer) {
64 self.style.label_style.print(
65 format!(
66 "{} [{y}/{n}]",
67 self.label,
68 y = if self.default_positive { 'Y' } else { 'y' },
69 n = if !self.default_positive { 'N' } else { 'n' },
70 ),
71 commands,
72 );
73
74 let result: String = if let Some(is_positive) = self.selected_option.as_ref() {
75 if *is_positive {
76 "Yes".into()
77 } else {
78 "No".into()
79 }
80 } else {
81 String::new()
82 };
83
84 let formatting = if self.is_submitted {
85 &self.style.submitted_formatting
86 } else {
87 &self.style.input_formatting
88 };
89
90 formatting.print(result, commands);
91 }
92
93 fn on_key_pressed(&mut self, key: Key) -> EventOutcome<bool> {
94 match key {
95 Key::Enter => {
96 self.is_submitted = true;
97 if let Some(is_positive) = self.selected_option.as_ref() {
98 EventOutcome::Done(*is_positive)
99 } else {
100 self.selected_option = Some(self.default_positive);
101 EventOutcome::Done(self.default_positive)
102 }
103 }
104 Key::Char(c) if self.selected_option.is_none() => match c {
105 'y' | 'Y' => {
106 self.selected_option = Some(true);
107 EventOutcome::Continue
108 }
109 'n' | 'N' => {
110 self.selected_option = Some(false);
111 EventOutcome::Continue
112 }
113 _ => EventOutcome::Continue,
114 },
115 Key::Backspace => {
116 self.selected_option = None;
117 EventOutcome::Continue
118 }
119 Key::Esc => EventOutcome::Abort(super::AbortReason::Interrupt),
120 _ => EventOutcome::Continue,
121 }
122 }
123}