You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
56 lines
1.7 KiB
Rust
56 lines
1.7 KiB
Rust
use dialoguer::MultiSelect;
|
|
use nu_plugin::{EvaluatedCall, LabeledError};
|
|
use nu_protocol::{Span, Value};
|
|
|
|
use crate::{prompt::UserPrompt, DialogPlugin};
|
|
|
|
impl DialogPlugin {
|
|
pub(crate) fn multiselect(
|
|
&self,
|
|
call: &EvaluatedCall,
|
|
_input: &Value,
|
|
) -> Result<Value, LabeledError> {
|
|
let options: Vec<String> = call.req(0)?;
|
|
|
|
let mut select = MultiSelect::new();
|
|
select.items(&options);
|
|
|
|
if let Some(prompt) = call.get_flag::<String>("prompt")? {
|
|
select.with_prompt(prompt);
|
|
}
|
|
if let Some(def) = call.get_flag::<String>("default")? {
|
|
let defaults = def
|
|
.split(',')
|
|
.map(|v| v.trim())
|
|
.filter_map(|v| v.parse::<usize>().ok())
|
|
.collect::<Vec<_>>();
|
|
let check_states = (0..options.len())
|
|
.map(|i| defaults.contains(&i))
|
|
.collect::<Vec<_>>();
|
|
select.defaults(&check_states);
|
|
}
|
|
|
|
if call.has_flag("abortable") {
|
|
if let Some(selection) = select.ask_opt(call.head)? {
|
|
Ok(map_selection(selection, options, call.head))
|
|
} else {
|
|
Ok(Value::nothing(call.head))
|
|
}
|
|
} else {
|
|
let selection = select.ask(call.head)?;
|
|
|
|
Ok(map_selection(selection, options, call.head))
|
|
}
|
|
}
|
|
}
|
|
|
|
fn map_selection(selection: Vec<usize>, options: Vec<String>, span: Span) -> Value {
|
|
let selected_items = options
|
|
.into_iter()
|
|
.enumerate()
|
|
.filter(|(i, _)| selection.contains(i))
|
|
.map(|(_, val)| Value::string(val, span))
|
|
.collect::<Vec<_>>();
|
|
Value::list(selected_items, span)
|
|
}
|