1use dialoguer::theme::{ColorfulTheme, Theme};
2use nu_plugin::{LabeledError, Plugin};
3use nu_protocol::{PluginSignature, SyntaxShape};
4
5mod confirm;
6mod multiselect;
7mod password;
8mod prompt;
9mod select;
10
11pub struct DialogPlugin {
12 pub(crate) theme: Box<dyn Theme>,
13}
14
15impl DialogPlugin {
16 pub fn new() -> Self {
17 Self {
18 theme: Box::new(ColorfulTheme::default()),
19 }
20 }
21}
22
23impl Plugin for DialogPlugin {
24 fn signature(&self) -> Vec<nu_protocol::PluginSignature> {
25 vec![
26 PluginSignature::build("ask").required(
27 "subcommand",
28 SyntaxShape::String,
29 "The ask subcommand to run",
30 ),
31 PluginSignature::build("ask confirm")
32 .usage("Prompt the user with a confirmation prompt.")
33 .required(
34 "prompt",
35 SyntaxShape::String,
36 "The question to ask the user.",
37 )
38 .switch("abortable", "If set users can abort the prompt.", None)
39 .named(
40 "default",
41 SyntaxShape::Boolean,
42 "The default selection.",
43 None,
44 )
45 .category(nu_protocol::Category::Misc),
46 PluginSignature::build("ask select")
47 .usage("Prompt the user with a selection prompt.")
48 .required(
49 "items",
50 SyntaxShape::List(Box::new(SyntaxShape::String)),
51 "The items out of which one can be selected.",
52 )
53 .switch("fuzzy", "To add a fuzzy search to the select.", None)
54 .switch("abortable", "If set users can abort the prompt.", None)
55 .named(
56 "prompt",
57 SyntaxShape::String,
58 "An optional prompt that can be shown to the user for the selection.",
59 None,
60 )
61 .named(
62 "default",
63 SyntaxShape::Number,
64 "The default selection.",
65 None,
66 )
67 .category(nu_protocol::Category::Misc),
68 PluginSignature::build("ask multiselect")
69 .usage("Prompt the user with a selection prompt.")
70 .required(
71 "items",
72 SyntaxShape::List(Box::new(SyntaxShape::String)),
73 "The items out of which one can be selected.",
74 )
75 .switch("abortable", "If set users can abort the prompt.", None)
76 .named(
77 "prompt",
78 SyntaxShape::String,
79 "An optional prompt that can be shown to the user for the selection.",
80 None,
81 )
82 .named(
83 "default",
84 SyntaxShape::String,
85 "The default selections as a comma separated string of indices",
86 None,
87 )
88 .category(nu_protocol::Category::Misc),
89 PluginSignature::build("ask password")
90 .usage("Prompt the user with a password input.")
91 .named(
92 "prompt",
93 SyntaxShape::String,
94 "The prompt to this password input",
95 None,
96 )
97 .switch(
98 "confirm",
99 "Prompts the user twice for matching password inputs",
100 None,
101 )
102 .switch(
103 "allow-empty",
104 "Allows the user to input an empty password",
105 None,
106 )
107 .category(nu_protocol::Category::Misc),
108 ]
109 }
110
111 fn run(
112 &mut self,
113 name: &str,
114 call: &nu_plugin::EvaluatedCall,
115 input: &nu_protocol::Value,
116 ) -> Result<nu_protocol::Value, nu_plugin::LabeledError> {
117 match name {
118 "ask confirm" => self.confirm(call, input),
119 "ask select" => self.select(call, input),
120 "ask multiselect" => self.multiselect(call, input),
121 "ask password" => self.password(call, input),
122 "ask" =>
123 Err(LabeledError {
124 label: "Missing subcommand".into(),
125 msg: "the subcommand to the ask command is missing".into(),
126 span: Some(call.head),
127 }),
128 _ => Err(LabeledError {
129 label: "Plugin call with wrong name signature".into(),
130 msg: "the signature used to call the plugin does not match any name in the plugin signature vector".into(),
131 span: Some(call.head),
132 })
133 }
134 }
135}