diff --git a/examples/list.rs b/examples/list.rs index 296ee2b..b342f8c 100644 --- a/examples/list.rs +++ b/examples/list.rs @@ -65,5 +65,6 @@ fn main() { .item("Twizzlers") .item("Milk Duds") .filterable(true) - .run(); + .run() + .expect("error running list"); } diff --git a/src/confirm.rs b/src/confirm.rs index 60bd700..e6275f7 100644 --- a/src/confirm.rs +++ b/src/confirm.rs @@ -81,6 +81,9 @@ impl<'a> Confirm<'a> { } /// Displays the dialog to the user and returns their response + /// + /// This function will block until the user submits the input. If the user cancels the input, + /// an error of type `io::ErrorKind::Interrupted` is returned. pub fn run(mut self) -> io::Result { let affirmative_char = self.affirmative.to_lowercase().chars().next().unwrap(); let negative_char = self.negative.to_lowercase().chars().next().unwrap(); @@ -96,24 +99,25 @@ impl<'a> Confirm<'a> { Key::ArrowRight | Key::Char('l') => self.handle_right(), Key::Char(c) if c == affirmative_char => { self.selected = true; - self.term.clear_to_end_of_screen()?; return self.handle_submit(); } Key::Char(c) if c == negative_char => { self.selected = false; - self.term.clear_to_end_of_screen()?; return self.handle_submit(); } Key::Enter => { - self.term.clear_to_end_of_screen()?; return self.handle_submit(); } + Key::Escape => { + return Err(io::Error::new(io::ErrorKind::Interrupted, "user cancelled")) + } _ => {} } } } fn handle_submit(mut self) -> io::Result { + self.term.clear_to_end_of_screen()?; self.clear()?; let output = self.render_success()?; self.term.write_all(output.as_bytes())?; diff --git a/src/dialog.rs b/src/dialog.rs index d1ef267..7e63443 100644 --- a/src/dialog.rs +++ b/src/dialog.rs @@ -118,7 +118,8 @@ impl<'a> Dialog<'a> { /// /// The response will be the label of the selected button. /// - /// This will block until the user selects a button or presses one of the submit keys. + /// This function will block until the user submits the input. If the user cancels the input, + /// an error of type `io::ErrorKind::Interrupted` is returned. pub fn run(mut self) -> io::Result { loop { self.clear()?; @@ -137,6 +138,9 @@ impl<'a> Dialog<'a> { Key::Enter => { return self.handle_submit(); } + Key::Escape => { + return Err(io::Error::new(io::ErrorKind::Interrupted, "user cancelled")) + } _ => {} } } diff --git a/src/input.rs b/src/input.rs index 8744628..636e0a1 100644 --- a/src/input.rs +++ b/src/input.rs @@ -139,6 +139,9 @@ impl<'a> Input<'a> { } /// Displays the input to the user and returns the response + /// + /// This function will block until the user submits the input. If the user cancels the input, + /// an error of type `io::ErrorKind::Interrupted` is returned. pub fn run(mut self) -> io::Result { self.term.hide_cursor()?; loop { @@ -170,6 +173,9 @@ impl<'a> Input<'a> { } } Key::Tab => self.handle_tab()?, + Key::Escape => { + return Err(io::Error::new(io::ErrorKind::Interrupted, "user cancelled")); + } _ => {} } if key != Key::Enter { diff --git a/src/list.rs b/src/list.rs index 773a402..dc12c6f 100644 --- a/src/list.rs +++ b/src/list.rs @@ -91,6 +91,9 @@ impl<'a> List<'a> { } /// Displays the input to the user and returns the response + /// + /// This function will block until the user submits the input. If the user cancels the input, + /// an error of type `io::ErrorKind::Interrupted` is returned. pub fn run(mut self) -> Result<(), io::Error> { loop { self.clear()?; @@ -99,7 +102,6 @@ impl<'a> List<'a> { self.term.flush()?; self.height = output.lines().count() - 1; if self.filtering { - // self.term.show_cursor()?; match self.term.read_key()? { Key::Enter => self.handle_stop_filtering(true)?, Key::Escape => self.handle_stop_filtering(false)?, @@ -115,7 +117,9 @@ impl<'a> List<'a> { Key::ArrowLeft | Key::Char('h') => self.handle_left()?, Key::ArrowRight | Key::Char('l') => self.handle_right()?, Key::Char('/') if self.filterable => self.handle_start_filtering(), - Key::Escape => self.handle_stop_filtering(false)?, + Key::Escape => { + return Err(io::Error::new(io::ErrorKind::Interrupted, "user cancelled")); + } Key::Enter => { self.clear()?; self.term.show_cursor()?; diff --git a/src/multiselect.rs b/src/multiselect.rs index 9b2cd38..863e44a 100644 --- a/src/multiselect.rs +++ b/src/multiselect.rs @@ -127,6 +127,9 @@ impl<'a, T> MultiSelect<'a, T> { } /// Displays the selector to the user and returns their selected options + /// + /// This function will block until the user submits the input. If the user cancels the input, + /// an error of type `io::ErrorKind::Interrupted` is returned. pub fn run(mut self) -> io::Result> { self.max = self.max.min(self.options.len()); self.min = self.min.min(self.max); @@ -155,7 +158,15 @@ impl<'a, T> MultiSelect<'a, T> { Key::Char('x') | Key::Char(' ') => self.handle_toggle(), Key::Char('a') => self.handle_toggle_all(), Key::Char('/') if self.filterable => self.handle_start_filtering(), - Key::Escape => self.handle_stop_filtering(false)?, + Key::Escape => { + if self.filter.is_empty() { + return Err(io::Error::new( + io::ErrorKind::Interrupted, + "user cancelled", + )); + } + self.handle_stop_filtering(false)? + } Key::Enter => { let selected = self .options diff --git a/src/select.rs b/src/select.rs index 23afda8..525c54a 100644 --- a/src/select.rs +++ b/src/select.rs @@ -105,6 +105,9 @@ impl<'a, T> Select<'a, T> { } /// Displays the selector to the user and returns their selected options + /// + /// This function will block until the user submits the input. If the user cancels the input, + /// an error of type `io::ErrorKind::Interrupted` is returned. pub fn run(mut self) -> io::Result { loop { self.clear()?; @@ -128,7 +131,15 @@ impl<'a, T> Select<'a, T> { Key::ArrowLeft | Key::Char('h') => self.handle_left()?, Key::ArrowRight | Key::Char('l') => self.handle_right()?, Key::Char('/') if self.filterable => self.handle_start_filtering(), - Key::Escape => self.handle_stop_filtering(false)?, + Key::Escape => { + if self.filter.is_empty() { + return Err(io::Error::new( + io::ErrorKind::Interrupted, + "user cancelled", + )); + } + self.handle_stop_filtering(false)?; + } Key::Enter => { self.clear()?; self.term.show_cursor()?; diff --git a/src/spinner.rs b/src/spinner.rs index 6a51469..db2782e 100644 --- a/src/spinner.rs +++ b/src/spinner.rs @@ -44,7 +44,7 @@ impl<'spinner> SpinnerActionRunner<'spinner> { &mut self, // with just this the compiler assumes that theme might be stored in self so it wont let u mutate it after this fn call theme: &'spinner Theme, ) -> Result<(), std::sync::mpsc::SendError> { - let theme = unsafe { std::mem::transmute(theme) }; + let theme = unsafe { std::mem::transmute::<&Theme, &Theme>(theme) }; self.sender.send(SpinnerAction::Theme(theme)) } @@ -54,7 +54,7 @@ impl<'spinner> SpinnerActionRunner<'spinner> { &mut self, // with just this the compiler assumes that theme might be stored in self so it wont let u mutate it after this fn call style: &'spinner SpinnerStyle, ) -> Result<(), std::sync::mpsc::SendError> { - let style = unsafe { std::mem::transmute(style) }; + let style = unsafe { std::mem::transmute::<&SpinnerStyle, &SpinnerStyle>(style) }; self.sender.send(SpinnerAction::Style(style)) }