Make Plugin::ask take self instead of &mut self
This commit is contained in:
parent
893037fbfe
commit
08353945e5
|
@ -28,6 +28,7 @@ pub use choice::Choice;
|
|||
use choice::{get_sep_str, ChoiceList};
|
||||
use options::Options;
|
||||
pub use plugin::Plugin;
|
||||
use plugin::PluginInteral;
|
||||
use ui::{backend::Backend, error, events::KeyEvent};
|
||||
|
||||
use std::fmt;
|
||||
|
@ -39,7 +40,7 @@ pub struct Question<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Question<'a> {
|
||||
pub(crate) fn new(opts: Options<'a>, kind: QuestionKind<'a>) -> Self {
|
||||
fn new(opts: Options<'a>, kind: QuestionKind<'a>) -> Self {
|
||||
Self { kind, opts }
|
||||
}
|
||||
}
|
||||
|
@ -85,17 +86,18 @@ impl Question<'static> {
|
|||
EditorBuilder::new(name.into())
|
||||
}
|
||||
|
||||
pub fn plugin<'a, N, P>(name: N, plugin: P) -> PluginBuilder<'a>
|
||||
pub fn plugin<'a, N, P, I>(name: N, plugin: I) -> PluginBuilder<'a>
|
||||
where
|
||||
N: Into<String>,
|
||||
P: Into<Box<dyn Plugin + 'a>>,
|
||||
P: Plugin + 'a,
|
||||
I: Into<P>,
|
||||
{
|
||||
PluginBuilder::new(name.into(), plugin.into())
|
||||
PluginBuilder::new(name.into(), Box::new(Some(plugin.into())))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum QuestionKind<'a> {
|
||||
enum QuestionKind<'a> {
|
||||
Input(input::Input<'a>),
|
||||
Int(number::Int<'a>),
|
||||
Float(number::Float<'a>),
|
||||
|
@ -106,8 +108,7 @@ pub(crate) enum QuestionKind<'a> {
|
|||
Checkbox(checkbox::Checkbox<'a>),
|
||||
Password(password::Password<'a>),
|
||||
Editor(editor::Editor<'a>),
|
||||
// random lifetime so that it doesn't have to be static
|
||||
Plugin(Box<dyn Plugin + 'a>),
|
||||
Plugin(Box<dyn PluginInteral + 'a>),
|
||||
}
|
||||
|
||||
impl Question<'_> {
|
||||
|
|
|
@ -4,6 +4,23 @@ use super::{Options, Question, QuestionKind};
|
|||
use crate::{Answer, Answers};
|
||||
|
||||
pub trait Plugin: std::fmt::Debug {
|
||||
fn ask(
|
||||
self,
|
||||
message: String,
|
||||
answers: &Answers,
|
||||
stdout: &mut dyn Backend,
|
||||
events: &mut dyn Iterator<Item = error::Result<events::KeyEvent>>,
|
||||
) -> error::Result<Answer>;
|
||||
}
|
||||
|
||||
/// The same trait as `Plugin`, except it take `&mut self` instead of `self`.
|
||||
///
|
||||
/// This is required since traits with functions that take `self` are not object safe, and so
|
||||
/// implementors of the trait would have to use &mut self even though it will only be called once.
|
||||
///
|
||||
/// Now instead of QuestionKind::Plugin having a `dyn Plugin`, it has a `dyn PluginInteral`, which
|
||||
/// is an `Option<T: Plugin>`.
|
||||
pub(super) trait PluginInteral: std::fmt::Debug {
|
||||
fn ask(
|
||||
&mut self,
|
||||
message: String,
|
||||
|
@ -13,19 +30,33 @@ pub trait Plugin: std::fmt::Debug {
|
|||
) -> error::Result<Answer>;
|
||||
}
|
||||
|
||||
pub struct PluginBuilder<'a> {
|
||||
opts: Options<'a>,
|
||||
plugin: Box<dyn Plugin + 'a>,
|
||||
impl<T: Plugin> PluginInteral for Option<T> {
|
||||
fn ask(
|
||||
&mut self,
|
||||
message: String,
|
||||
answers: &Answers,
|
||||
stdout: &mut dyn Backend,
|
||||
events: &mut dyn Iterator<Item = error::Result<events::KeyEvent>>,
|
||||
) -> error::Result<Answer> {
|
||||
self.take()
|
||||
.expect("Plugin::ask called twice")
|
||||
.ask(message, answers, stdout, events)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Plugin + 'a> From<P> for Box<dyn Plugin + 'a> {
|
||||
pub struct PluginBuilder<'a> {
|
||||
opts: Options<'a>,
|
||||
plugin: Box<dyn PluginInteral + 'a>,
|
||||
}
|
||||
|
||||
impl<'a, P: PluginInteral + 'a> From<P> for Box<dyn PluginInteral + 'a> {
|
||||
fn from(plugin: P) -> Self {
|
||||
Box::new(plugin)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PluginBuilder<'a> {
|
||||
pub(crate) fn new(name: String, plugin: Box<dyn Plugin + 'a>) -> Self {
|
||||
pub(super) fn new(name: String, plugin: Box<dyn PluginInteral + 'a>) -> Self {
|
||||
Self {
|
||||
opts: Options::new(name),
|
||||
plugin,
|
||||
|
|
Loading…
Reference in New Issue
Block a user