diff options
| author | Robin Krahl <robin.krahl@ireas.org> | 2019-01-11 02:31:29 +0000 | 
|---|---|---|
| committer | Robin Krahl <robin.krahl@ireas.org> | 2019-01-11 03:32:45 +0100 | 
| commit | 84bfea7add93a98f83ad958151cca718c33bc0a4 (patch) | |
| tree | cd860c19962398c06b17f383931441787a6e786e /src/backends | |
| parent | dc754cbc9763b3ea6979ed55bd4e8030fe073078 (diff) | |
| download | dialog-rs-84bfea7add93a98f83ad958151cca718c33bc0a4.tar.gz dialog-rs-84bfea7add93a98f83ad958151cca718c33bc0a4.tar.bz2  | |
Add the stdio backend
This patch adds the stdio backend which acts as a fallback backend and
uses standard input and output.  For password queries, the rpassword
crate is used to suppress output.  Also, default_backend is changed to
return Stdio if Dialog is not available.
Diffstat (limited to 'src/backends')
| -rw-r--r-- | src/backends/dialog.rs | 4 | ||||
| -rw-r--r-- | src/backends/mod.rs | 3 | ||||
| -rw-r--r-- | src/backends/stdio.rs | 89 | 
3 files changed, 96 insertions, 0 deletions
diff --git a/src/backends/dialog.rs b/src/backends/dialog.rs index 6f078e6..e681caf 100644 --- a/src/backends/dialog.rs +++ b/src/backends/dialog.rs @@ -49,6 +49,10 @@ impl Dialog {          self.width = width.to_string();      } +    pub(crate) fn is_available() -> bool { +        super::is_available("dialog") +    } +      fn execute(          &self,          args: Vec<&str>, diff --git a/src/backends/mod.rs b/src/backends/mod.rs index f5af7ef..5ae3cef 100644 --- a/src/backends/mod.rs +++ b/src/backends/mod.rs @@ -2,9 +2,11 @@  // SPDX-License-Identifier: MIT  mod dialog; +mod stdio;  mod zenity;  pub use crate::backends::dialog::Dialog; +pub use crate::backends::stdio::Stdio;  pub use crate::backends::zenity::Zenity;  use std::env; @@ -49,6 +51,7 @@ pub(crate) fn is_available(name: &str) -> bool {  pub(crate) fn from_str(s: &str) -> Option<Box<dyn Backend>> {      match s.to_lowercase().as_ref() {          "dialog" => Some(Box::new(Dialog::new())), +        "stdio" => Some(Box::new(Stdio::new())),          "zenity" => Some(Box::new(Zenity::new())),          _ => None,      } diff --git a/src/backends/stdio.rs b/src/backends/stdio.rs new file mode 100644 index 0000000..6838ef1 --- /dev/null +++ b/src/backends/stdio.rs @@ -0,0 +1,89 @@ +// Copyright (C) 2019 Robin Krahl <robin.krahl@ireas.org> +// SPDX-License-Identifier: MIT + +use std::io::{self, Write}; + +use crate::{Choice, Input, Message, Password, Question, Result}; + +/// The fallback backend using standard input and output. +/// +/// This backend is intended as a fallback backend to use if no other backend is available.  The +/// dialogs are printed to the standard output and user input is read from the standard input. +#[derive(Debug)] +pub struct Stdio {} + +impl Stdio { +    /// Creates a new `Stdio` instance. +    pub fn new() -> Stdio { +        Stdio {} +    } +} + +impl AsRef<Stdio> for Stdio { +    fn as_ref(&self) -> &Self { +        self +    } +} + +fn print_title(title: &Option<String>) { +    if let Some(ref title) = title { +        println!("{}", title); +        println!("{}", "=".repeat(title.len())); +    } +} + +fn read_input() -> Result<String> { +    let mut input = String::new(); +    io::stdin().read_line(&mut input)?; +    Ok(input.trim_end_matches("\n").to_string()) +} + +fn parse_choice(input: &str) -> Choice { +    match input.to_lowercase().as_ref() { +        "y" => Choice::Yes, +        "yes" => Choice::Yes, +        "n" => Choice::No, +        "no" => Choice::No, +        _ => Choice::Cancel, +    } +} + +impl super::Backend for Stdio { +    fn show_input(&self, input: &Input) -> Result<Option<String>> { +        print_title(&input.title); +        if let Some(ref default) = input.default { +            print!("{} [default: {}]: ", input.text, default); +        } else { +            print!("{}: ", input.text); +        } +        io::stdout().flush()?; + +        let user_input = read_input()?; +        if user_input.is_empty() { +            if let Some(ref default) = input.default { +                return Ok(Some(default.to_string())); +            } +        } +        Ok(Some(user_input)) +    } + +    fn show_message(&self, message: &Message) -> Result<()> { +        print_title(&message.title); +        println!("{}", message.text); +        Ok(()) +    } + +    fn show_password(&self, password: &Password) -> Result<Option<String>> { +        print_title(&password.title); +        print!("{}: ", password.text); +        io::stdout().flush()?; +        Ok(Some(rpassword::read_password()?)) +    } + +    fn show_question(&self, question: &Question) -> Result<Choice> { +        print_title(&question.title); +        print!("{} [y/n]: ", question.text); +        io::stdout().flush()?; +        Ok(parse_choice(&read_input()?)) +    } +}  | 
