From ec84c425282c3fd26f5e862b7864ad2ae7ec1e2e Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Tue, 8 Jan 2019 03:16:20 +0000 Subject: Add input dialog boxes This patch implements input dialog boxes. This required some refactoring in the dialog backend to allow additional arguments after the width and the height. --- src/backends/dialog.rs | 85 ++++++++++++++++++++++++++++++++++++-------------- src/backends/mod.rs | 3 ++ 2 files changed, 65 insertions(+), 23 deletions(-) (limited to 'src/backends') diff --git a/src/backends/dialog.rs b/src/backends/dialog.rs index d50be43..8cde8cc 100644 --- a/src/backends/dialog.rs +++ b/src/backends/dialog.rs @@ -5,7 +5,7 @@ use std::io; use std::io::Result; use std::process; -use crate::Message; +use crate::{Input, Message}; /// The `dialog` backend. /// @@ -28,20 +28,6 @@ impl Dialog { } } - fn execute(&self, args: Vec<&str>) -> Result { - let mut args = args; - if let Some(ref backtitle) = self.backtitle { - args.insert(0, "--backtitle"); - args.insert(1, backtitle); - } - println!("{:?}", args); - process::Command::new("dialog") - .args(args) - .stdin(process::Stdio::inherit()) - .stdout(process::Stdio::inherit()) - .output() - } - /// Sets the backtitle for the dialog boxes. /// /// The backtitle is displayed on the backdrop, at the top of the screen. @@ -65,15 +51,31 @@ impl Dialog { self.width = width.to_string(); } - fn show_box(&self, args: Vec<&str>, title: &Option) -> Result { - let mut args = args; + fn execute( + &self, + args: Vec<&str>, + post_args: Vec<&str>, + title: &Option, + ) -> Result { + let mut command = process::Command::new("dialog"); + command.stdin(process::Stdio::inherit()); + command.stdout(process::Stdio::inherit()); + + if let Some(ref backtitle) = self.backtitle { + command.arg("--backtitle"); + command.arg(backtitle); + } if let Some(ref title) = title { - args.insert(0, "--title"); - args.insert(1, title); + command.arg("--title"); + command.arg(title); } - args.push(&self.height); - args.push(&self.width); - self.execute(args) + + command.args(args); + command.arg(&self.height); + command.arg(&self.width); + command.args(post_args); + + command.output() } } @@ -85,10 +87,47 @@ fn require_success(status: process::ExitStatus) -> Result<()> { } } +fn get_stderr(output: process::Output) -> Result> { + if output.status.success() { + String::from_utf8(output.stderr) + .map(|s| Some(s)) + .map_err(|_| { + io::Error::new(io::ErrorKind::Other, "Input contained invalid UTF-8 bytes") + }) + } else { + if let Some(code) = output.status.code() { + match code { + 0 => Ok(None), + 1 => Ok(None), + -1 => Ok(None), + _ => Err(io::Error::new( + io::ErrorKind::Other, + "Could not execute dialog", + )), + } + } else { + Err(io::Error::new( + io::ErrorKind::Other, + "dialog was terminated by a signal", + )) + } + } +} + impl super::Backend for Dialog { + fn show_input(&self, input: &Input) -> Result> { + let args = vec!["--inputbox", &input.text]; + let mut post_args: Vec<&str> = Vec::new(); + if let Some(ref default) = input.default { + post_args.push(default); + } + self.execute(args, post_args, &input.title) + .and_then(get_stderr) + } + fn show_message(&self, message: &Message) -> Result<()> { let args = vec!["--msgbox", &message.text]; - self.show_box(args, &message.title) + self.execute(args, vec![], &message.title) .and_then(|output| require_success(output.status)) .map(|_| ()) } diff --git a/src/backends/mod.rs b/src/backends/mod.rs index c316307..1abb8d1 100644 --- a/src/backends/mod.rs +++ b/src/backends/mod.rs @@ -17,6 +17,9 @@ use std::io::Result; /// [`default_backend`]: ../function.default_backend.html /// [`show_with`]: ../trait.DialogBox.html#method.show_with pub trait Backend { + /// Shows the given input dialog and returns the input. + fn show_input(&self, input: &super::Input) -> Result>; + /// Shows the given message dialog. fn show_message(&self, message: &super::Message) -> Result<()>; } -- cgit v1.2.1