Add select prompt
parent
215c235f4b
commit
9cf4d225d7
@ -0,0 +1,69 @@
|
|||||||
|
use dialoguer::{theme::Theme, FuzzySelect, Select};
|
||||||
|
|
||||||
|
use super::{create_labeled_error, UserPrompt};
|
||||||
|
|
||||||
|
pub enum GenericSelect<'a> {
|
||||||
|
Fuzzy(FuzzySelect<'a>),
|
||||||
|
Normal(Select<'a>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> GenericSelect<'a> {
|
||||||
|
pub fn fuzzy(theme: &'a dyn Theme) -> Self {
|
||||||
|
Self::Fuzzy(FuzzySelect::with_theme(theme))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn normal(theme: &'a dyn Theme) -> Self {
|
||||||
|
Self::Normal(Select::with_theme(theme))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn items<T: ToString>(&mut self, items: &[T]) -> &mut Self {
|
||||||
|
match self {
|
||||||
|
GenericSelect::Fuzzy(f) => f.items(items).nop(),
|
||||||
|
GenericSelect::Normal(n) => n.items(items).nop(),
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default(&mut self, val: usize) -> &mut Self {
|
||||||
|
match self {
|
||||||
|
GenericSelect::Fuzzy(f) => f.default(val).nop(),
|
||||||
|
GenericSelect::Normal(n) => n.default(val).nop(),
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_prompt<S: Into<String>>(&mut self, prompt: S) -> &mut Self {
|
||||||
|
match self {
|
||||||
|
GenericSelect::Fuzzy(f) => f.with_prompt(prompt).nop(),
|
||||||
|
GenericSelect::Normal(n) => n.with_prompt(prompt).nop(),
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> UserPrompt for GenericSelect<'a> {
|
||||||
|
type Output = usize;
|
||||||
|
|
||||||
|
fn prompt(&self) -> Result<Self::Output, nu_plugin::LabeledError> {
|
||||||
|
match self {
|
||||||
|
GenericSelect::Fuzzy(f) => f.interact(),
|
||||||
|
GenericSelect::Normal(n) => n.interact(),
|
||||||
|
}
|
||||||
|
.map_err(create_labeled_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prompt_opt(&self) -> Result<Option<Self::Output>, nu_plugin::LabeledError> {
|
||||||
|
match self {
|
||||||
|
GenericSelect::Fuzzy(f) => f.interact_opt(),
|
||||||
|
GenericSelect::Normal(n) => n.interact_opt(),
|
||||||
|
}
|
||||||
|
.map_err(create_labeled_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Nop {
|
||||||
|
fn nop(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Nop for Select<'a> {}
|
||||||
|
impl<'a> Nop for FuzzySelect<'a> {}
|
@ -0,0 +1,33 @@
|
|||||||
|
use std::io;
|
||||||
|
|
||||||
|
use nu_plugin::LabeledError;
|
||||||
|
mod generic_select;
|
||||||
|
pub use generic_select::GenericSelect;
|
||||||
|
|
||||||
|
pub trait UserPrompt {
|
||||||
|
type Output;
|
||||||
|
|
||||||
|
fn prompt(&self) -> Result<Self::Output, LabeledError>;
|
||||||
|
|
||||||
|
fn prompt_opt(&self) -> Result<Option<Self::Output>, LabeledError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> UserPrompt for dialoguer::Confirm<'a> {
|
||||||
|
type Output = bool;
|
||||||
|
|
||||||
|
fn prompt(&self) -> Result<Self::Output, LabeledError> {
|
||||||
|
self.interact().map_err(create_labeled_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prompt_opt(&self) -> Result<Option<Self::Output>, LabeledError> {
|
||||||
|
self.interact_opt().map_err(create_labeled_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_labeled_error(e: io::Error) -> LabeledError {
|
||||||
|
LabeledError {
|
||||||
|
label: "Failed to prompt user".into(),
|
||||||
|
msg: e.to_string(),
|
||||||
|
span: None,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
use nu_plugin::{EvaluatedCall, LabeledError};
|
||||||
|
use nu_protocol::Value;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
prompt::{GenericSelect, UserPrompt},
|
||||||
|
DialogPlugin,
|
||||||
|
};
|
||||||
|
|
||||||
|
impl DialogPlugin {
|
||||||
|
pub(crate) fn select(
|
||||||
|
&self,
|
||||||
|
call: &EvaluatedCall,
|
||||||
|
_input: &Value,
|
||||||
|
) -> Result<Value, LabeledError> {
|
||||||
|
let mut options: Vec<String> = call.req(0)?;
|
||||||
|
|
||||||
|
let mut select = if call.has_flag("fuzzy") {
|
||||||
|
GenericSelect::fuzzy(&*self.theme)
|
||||||
|
} else {
|
||||||
|
GenericSelect::normal(&*self.theme)
|
||||||
|
};
|
||||||
|
select.items(&options);
|
||||||
|
|
||||||
|
if let Some(prompt) = call.get_flag::<String>("prompt")? {
|
||||||
|
select.with_prompt(prompt);
|
||||||
|
}
|
||||||
|
if let Some(def) = call.get_flag::<usize>("default")? {
|
||||||
|
select.default(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
let selection = select.prompt()?;
|
||||||
|
let selected_item = options.remove(selection);
|
||||||
|
|
||||||
|
Ok(Value::String {
|
||||||
|
val: selected_item,
|
||||||
|
span: call.head,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue