Allow support for using custom prompts
Due to [object safety](https://doc.rust-lang.org/reference/items/traits.html#object-safety), unlike in built prompts, the plugins can only take `&mut self` and be given a `&mut dyn Write`.
This commit is contained in:
parent
dd4a077bdf
commit
4148198cb7
15
src/lib.rs
15
src/lib.rs
|
@ -2,9 +2,15 @@ mod answer;
|
|||
mod error;
|
||||
mod question;
|
||||
|
||||
pub use answer::{Answer, Answers, ExpandItem, ListItem};
|
||||
use crossterm::tty::IsTty;
|
||||
pub use question::{Choice::Choice, Choice::Separator, Question};
|
||||
|
||||
pub use answer::{Answer, Answers, ExpandItem, ListItem};
|
||||
pub use question::{Choice::Choice, Choice::Separator, Plugin, Question};
|
||||
|
||||
pub mod plugin {
|
||||
pub use crate::Plugin;
|
||||
pub use ui;
|
||||
}
|
||||
|
||||
pub struct PromptModule<Q> {
|
||||
questions: Q,
|
||||
|
@ -71,7 +77,10 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub fn prompt(questions: Vec<Question>) -> error::Result<Answers> {
|
||||
pub fn prompt<'m, 'w, 'f, 'v, 't, Q>(questions: Q) -> error::Result<Answers>
|
||||
where
|
||||
Q: IntoIterator<Item = Question<'m, 'w, 'f, 'v, 't>>,
|
||||
{
|
||||
PromptModule::new(questions).prompt_all()
|
||||
}
|
||||
|
||||
|
|
|
@ -9,12 +9,14 @@ mod number;
|
|||
#[macro_use]
|
||||
mod options;
|
||||
mod password;
|
||||
mod plugin;
|
||||
mod rawlist;
|
||||
|
||||
use crate::{error, Answer, Answers};
|
||||
pub use choice::Choice;
|
||||
use choice::{get_sep_str, ChoiceList};
|
||||
use options::Options;
|
||||
pub use plugin::Plugin;
|
||||
|
||||
use std::io::prelude::*;
|
||||
|
||||
|
@ -56,11 +58,13 @@ enum QuestionKind<'f, 'v, 't> {
|
|||
Checkbox(checkbox::Checkbox<'f, 'v, 't>),
|
||||
Password(password::Password<'f, 'v, 't>),
|
||||
Editor(editor::Editor<'f, 'v, 't>),
|
||||
// random lifetime so that it doesn't have to be static
|
||||
Plugin(Box<dyn Plugin + 'f>),
|
||||
}
|
||||
|
||||
impl Question<'_, '_, '_, '_, '_> {
|
||||
pub fn ask<W: Write>(
|
||||
self,
|
||||
mut self,
|
||||
answers: &Answers,
|
||||
w: &mut W,
|
||||
) -> error::Result<Option<(String, Answer)>> {
|
||||
|
@ -88,6 +92,7 @@ impl Question<'_, '_, '_, '_, '_> {
|
|||
QuestionKind::Checkbox(c) => c.ask(message, answers, w)?,
|
||||
QuestionKind::Password(p) => p.ask(message, answers, w)?,
|
||||
QuestionKind::Editor(e) => e.ask(message, answers, w)?,
|
||||
QuestionKind::Plugin(ref mut o) => o.ask(message, answers, w)?,
|
||||
};
|
||||
|
||||
Ok(Some((name, res)))
|
||||
|
|
55
src/question/plugin.rs
Normal file
55
src/question/plugin.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
use crate::{error, Answer, Answers};
|
||||
|
||||
use super::{Options, Question};
|
||||
|
||||
pub trait Plugin: std::fmt::Debug {
|
||||
fn ask(
|
||||
&mut self,
|
||||
message: String,
|
||||
answers: &Answers,
|
||||
stdout: &mut dyn std::io::Write,
|
||||
) -> error::Result<Answer>;
|
||||
}
|
||||
|
||||
pub struct PluginBuilder<'m, 'w, 'p> {
|
||||
opts: Options<'m, 'w>,
|
||||
plugin: Box<dyn Plugin + 'p>,
|
||||
}
|
||||
|
||||
impl<'p, P: Plugin + 'p> From<P> for Box<dyn Plugin + 'p> {
|
||||
fn from(plugin: P) -> Self {
|
||||
Box::new(plugin)
|
||||
}
|
||||
}
|
||||
|
||||
impl Question<'static, 'static, 'static, 'static, 'static> {
|
||||
pub fn plugin<'a, N, P>(name: N, plugin: P) -> PluginBuilder<'static, 'static, 'a>
|
||||
where
|
||||
N: Into<String>,
|
||||
P: Into<Box<dyn Plugin + 'a>>,
|
||||
{
|
||||
PluginBuilder {
|
||||
opts: Options::new(name.into()),
|
||||
plugin: plugin.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
crate::impl_options_builder!(PluginBuilder<'q>; (this, opts) => {
|
||||
PluginBuilder {
|
||||
opts,
|
||||
plugin: this.plugin,
|
||||
}
|
||||
});
|
||||
|
||||
impl<'m, 'w, 'q> PluginBuilder<'m, 'w, 'q> {
|
||||
pub fn build(self) -> Question<'m, 'w, 'q, 'static, 'static> {
|
||||
Question::new(self.opts, super::QuestionKind::Plugin(self.plugin))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'m, 'w, 'q> From<PluginBuilder<'m, 'w, 'q>> for Question<'m, 'w, 'q, 'static, 'static> {
|
||||
fn from(builder: PluginBuilder<'m, 'w, 'q>) -> Self {
|
||||
builder.build()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user