#![cfg_attr(feature = "nightly", feature(specialization))]
use rustyline::completion::{Completer, Pair};
use rustyline::{Editor, Helper};
pub use rustyline::error::ReadlineError;
type Result<T> = std::result::Result<T, ReadlineError>;
#[cfg(feature = "nightly")]
use std::fmt::Display;
mod from_str;
mod path;
mod yes_no;
pub fn prompt<T, S>(msg: S) -> Result<T>
where
T: Promptable,
S: AsRef<str>,
{
T::prompt(msg)
}
pub fn prompt_opt<T, S>(msg: S) -> Result<Option<T>>
where
T: Promptable,
S: AsRef<str>,
{
T::prompt_opt(msg)
}
pub fn prompt_default<T, S>(msg: S, default: T) -> Result<T>
where
T: Promptable,
S: AsRef<str>,
{
T::prompt_default(msg, default)
}
pub trait Promptable: Sized {
fn prompt<S: AsRef<str>>(msg: S) -> Result<Self>;
fn prompt_opt<S: AsRef<str>>(msg: S) -> Result<Option<Self>>;
fn prompt_default<S: AsRef<str>>(msg: S, default: Self) -> Result<Self>;
}
struct Prompter<H: Helper> {
editor: Editor<H>,
}
impl Prompter<()> {
pub fn new() -> Prompter<()> {
Prompter::default()
}
}
impl Default for Prompter<()> {
fn default() -> Self {
Prompter {
editor: Editor::new(),
}
}
}
impl<H> Prompter<H>
where
H: Helper,
{
pub fn with_helper(helper: H) -> Prompter<H> {
let mut editor = Editor::new();
editor.set_helper(Some(helper));
Prompter { editor }
}
pub fn prompt_once<S: AsRef<str>>(&mut self, msg: S) -> Result<String> {
self.editor
.readline(&format!("{}: ", msg.as_ref()))
.map(|line| line.trim().to_owned())
}
pub fn prompt_opt<S: AsRef<str>>(&mut self, msg: S) -> Result<Option<String>> {
let val = self.prompt_once(msg)?;
if val.is_empty() {
return Ok(None);
}
Ok(Some(val))
}
pub fn prompt_nonempty<S: AsRef<str>>(&mut self, msg: S) -> Result<String> {
let mut val = self.prompt_opt(&msg)?;
while val.is_none() {
eprintln!("Value is required.");
val = self.prompt_opt(&msg)?;
}
Ok(val.unwrap())
}
pub fn prompt_then<S, F, U>(&mut self, msg: S, handler: F) -> Result<U>
where
S: AsRef<str>,
F: Fn(String) -> ::std::result::Result<U, String>,
{
let mut val = handler(self.prompt_once(&msg)?);
while let Err(e) = val {
eprintln!("{}", e);
val = handler(self.prompt_once(&msg)?);
}
Ok(val.unwrap())
}
}