entrust_dialog/input/
confirmation.rs1use crate::dialog::DialogState;
2use crate::input::InputDialog;
3use crate::input::prompt::Prompt;
4use crate::input::validator::Validator;
5use std::mem;
6
7#[derive(Debug, Clone)]
8pub struct Confirmation<'c> {
9 prompt: Prompt<'c>,
10 validation_message: &'static str,
11 is_active: bool,
12}
13
14impl<'c> Confirmation<'c> {
15 pub fn new(prompt: Prompt<'c>) -> Self {
16 Confirmation {
17 prompt,
18 validation_message: "no match",
19 is_active: false,
20 }
21 }
22
23 pub fn with_validation_message(mut self, validation_message: &'static str) -> Self {
24 self.validation_message = validation_message;
25 self
26 }
27}
28
29impl<'p, 'c> InputDialog<'p, 'c> {
30 pub(super) fn confirm(&mut self) {
31 match self.confirmation.as_mut() {
32 None => self.state = DialogState::Completed,
33 Some(confirmation) if confirmation.is_active => self.state = DialogState::Completed,
34 Some(confirmation) => {
35 let first = mem::take(&mut self.content);
36 self.cursor.set_index(0);
37 let message = confirmation.validation_message;
38 self.validator = Validator::new(move |chars| {
39 if chars == first {
40 None
41 } else {
42 Some(message.into())
43 }
44 });
45 confirmation.is_active = true;
46 }
47 }
48 }
49
50 pub(super) fn prompt_with_confirmation(&self) -> Prompt<'_> {
51 self.confirmation
52 .as_ref()
53 .and_then(|c| {
54 if c.is_active {
55 Some(c.prompt.clone())
56 } else {
57 None
58 }
59 })
60 .unwrap_or(self.prompt.clone())
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67 use crate::dialog::Dialog;
68 use crate::input::Update;
69 use crate::input::prompt::Prompt;
70 use ratatui::prelude::Line;
71
72 #[test]
73 fn test() {
74 let prompt_header = "header prompt";
75 let prompt_inline = "inline prompt";
76 let confirmation_header = "repeat";
77 let validation_message = "no match";
78 let mut dialog = InputDialog::default()
79 .with_prompt(Prompt::new(prompt_header, prompt_inline))
80 .with_confirmation(
81 Confirmation::new(Prompt::header(confirmation_header))
82 .with_validation_message(validation_message),
83 );
84
85 dialog.perform_update(Update::InsertChar('a')).unwrap();
86 assert!(!dialog.confirmation.as_ref().unwrap().is_active);
87 assert_eq!(
88 Line::raw(prompt_header),
89 dialog.prompt_with_confirmation().header
90 );
91
92 dialog.perform_update(Update::Confirm).unwrap();
93 assert!(dialog.content.is_empty());
94 assert!(dialog.confirmation.as_ref().unwrap().is_active);
95 assert_eq!(
96 Line::raw(confirmation_header),
97 dialog.prompt_with_confirmation().header
98 );
99
100 dialog.perform_update(Update::InsertChar('b')).unwrap();
101 dialog.perform_update(Update::Confirm).unwrap();
102 assert_eq!(Some(validation_message.into()), dialog.validation_message());
103 assert_eq!(DialogState::Pending, dialog.state);
104
105 dialog.perform_update(Update::DeleteBeforeCursor).unwrap();
106 dialog.perform_update(Update::InsertChar('a')).unwrap();
107 assert_eq!(None, dialog.validation_message());
108 dialog.perform_update(Update::Confirm).unwrap();
109 assert_eq!(DialogState::Completed, dialog.state);
110 }
111}