diff options
Diffstat (limited to 'src/blocking')
-rw-r--r-- | src/blocking/input.rs | 58 | ||||
-rw-r--r-- | src/blocking/output.rs | 24 |
2 files changed, 76 insertions, 6 deletions
diff --git a/src/blocking/input.rs b/src/blocking/input.rs index 7a35f25..c668857 100644 --- a/src/blocking/input.rs +++ b/src/blocking/input.rs @@ -5,12 +5,16 @@ use std::os::unix::io::AsRawFd as _; use crate::private::Input as _; +/// Switches the terminal on `stdin` to raw mode, and restores it when this +/// object goes out of scope. pub struct RawGuard { termios: Option<nix::sys::termios::Termios>, } impl RawGuard { - #[allow(clippy::new_without_default)] + /// Switches the terminal on `stdin` to raw mode and returns a guard + /// object. This is typically called as part of + /// [`Input::new`](Input::new). pub fn new() -> Result<Self> { let stdin = std::io::stdin().as_raw_fd(); let termios = @@ -28,6 +32,7 @@ impl RawGuard { }) } + /// Switch back from raw mode early. pub fn cleanup(&mut self) -> Result<()> { if let Some(termios) = self.termios.take() { let stdin = std::io::stdin().as_raw_fd(); @@ -44,11 +49,18 @@ impl RawGuard { } impl Drop for RawGuard { + /// Calls `cleanup`. fn drop(&mut self) { let _ = self.cleanup(); } } +/// Manages handling terminal input from `stdin`. +/// +/// The primary interface provided is [`read_key`](Input::read_key). You can +/// additionally configure the types of keypresses you are interested in +/// through the `parse_*` methods. This configuration can be changed between +/// any two calls to [`read_key`](Input::read_key). pub struct Input { raw: Option<RawGuard>, @@ -112,14 +124,17 @@ impl crate::private::Input for Input { } } -#[allow(clippy::new_without_default)] impl Input { + /// Creates a new `Input` instance containing a [`RawGuard`](RawGuard) + /// instance. pub fn new() -> Result<Self> { let mut self_ = Self::new_without_raw(); self_.raw = Some(RawGuard::new()?); Ok(self_) } + /// Creates a new `Input` instance without creating a + /// [`RawGuard`](RawGuard) instance. pub fn new_without_raw() -> Self { Self { raw: None, @@ -133,30 +148,61 @@ impl Input { } } + /// Removes the [`RawGuard`](RawGuard) instance stored in this `Input` + /// instance and returns it. This can be useful if you need to manage the + /// lifetime of the [`RawGuard`](RawGuard) instance separately. + pub fn take_raw_guard(&mut self) -> Option<RawGuard> { + self.raw.take() + } + + /// Sets whether `read_key` should try to produce + /// [`String`](crate::Key::String) or [`Char`](crate::Key::Char) keys when + /// possible, rather than [`Bytes`](crate::Key::Bytes) or + /// [`Byte`](crate::Key::Byte) keys. Note that + /// [`Bytes`](crate::Key::Bytes) or [`Byte`](crate::Key::Byte) keys may + /// still be produced if the input fails to be parsed as UTF-8. Defaults + /// to true. pub fn parse_utf8(&mut self, parse: bool) { self.parse_utf8 = parse; } + /// Sets whether `read_key` should produce [`Ctrl`](crate::Key::Ctrl) keys + /// when possible, rather than [`Bytes`](crate::Key::Bytes) or + /// [`Byte`](crate::Key::Byte) keys. Defaults to true. pub fn parse_ctrl(&mut self, parse: bool) { self.parse_ctrl = parse; } + /// Sets whether `read_key` should produce [`Meta`](crate::Key::Meta) keys + /// when possible, rather than producing the + /// [`Escape`](crate::Key::Escape) key separately. Defaults to true. pub fn parse_meta(&mut self, parse: bool) { self.parse_meta = parse; } + /// Sets whether `read_key` should produce keys other than + /// [`String`](crate::Key::String), [`Char`](crate::Key::Char), + /// [`Bytes`](crate::Key::Bytes), [`Byte`](crate::Key::Byte), + /// [`Ctrl`](crate::Key::Ctrl), or [`Meta`](crate::Key::Meta). Defaults to + /// true. pub fn parse_special_keys(&mut self, parse: bool) { self.parse_special_keys = parse; } + /// Sets whether `read_key` should produce individual + /// [`Char`](crate::Key::Char) or [`Byte`](crate::Key::Byte) keys, rather + /// than combining them into [`String`](crate::Key::String) or + /// [`Bytes`](crate::Key::Bytes) keys when possible. When this is true, + /// [`String`](crate::Key::String) and [`Bytes`](crate::Key::Bytes) will + /// never be returned, and when this is false, [`Char`](crate::Key::Char) + /// and [`Byte`](crate::Key::Byte) will never be returned. Defaults to + /// true. pub fn parse_single(&mut self, parse: bool) { self.parse_single = parse; } - pub fn take_raw_guard(&mut self) -> Option<RawGuard> { - self.raw.take() - } - + /// Reads a keypress from the terminal on `stdin`. Returns `Ok(None)` on + /// EOF. pub fn read_key(&mut self) -> Result<Option<crate::Key>> { self.fill_buf()?; diff --git a/src/blocking/output.rs b/src/blocking/output.rs index 83466f8..77e13d2 100644 --- a/src/blocking/output.rs +++ b/src/blocking/output.rs @@ -4,16 +4,22 @@ use std::io::Write as _; use crate::private::Output as _; +/// Switches the terminal on `stdout` to alternate screen mode, and restores +/// it when this object goes out of scope. pub struct ScreenGuard { cleaned_up: bool, } impl ScreenGuard { + /// Switches the terminal on `stdout` to alternate screen mode and returns + /// a guard object. This is typically called as part of + /// [`Output::new`](Output::new). pub fn new() -> Result<Self> { write_stdout(crate::INIT)?; Ok(Self { cleaned_up: false }) } + /// Switch back from alternate screen mode early. pub fn cleanup(&mut self) -> Result<()> { if self.cleaned_up { return Ok(()); @@ -24,11 +30,18 @@ impl ScreenGuard { } impl Drop for ScreenGuard { + /// Calls `cleanup`. fn drop(&mut self) { let _ = self.cleanup(); } } +/// Manages drawing to the terminal on `stdout`. +/// +/// Most functionality is provided by the [`Textmode`](crate::Textmode) trait. +/// You should call those trait methods to draw to the in-memory screen, and +/// then call [`refresh`](Output::refresh) when you want to update the +/// terminal on `stdout`. pub struct Output { screen: Option<ScreenGuard>, @@ -57,12 +70,16 @@ impl crate::private::Output for Output { impl crate::Textmode for Output {} impl Output { + /// Creates a new `Output` instance containing a + /// [`ScreenGuard`](ScreenGuard) instance. pub fn new() -> Result<Self> { let mut self_ = Self::new_without_screen(); self_.screen = Some(ScreenGuard::new()?); Ok(self_) } + /// Creates a new `Output` instance without creating a + /// [`ScreenGuard`](ScreenGuard) instance. pub fn new_without_screen() -> Self { let (rows, cols) = match terminal_size::terminal_size() { Some((terminal_size::Width(w), terminal_size::Height(h))) => { @@ -80,10 +97,17 @@ impl Output { } } + /// Removes the [`ScreenGuard`](ScreenGuard) instance stored in this + /// `Output` instance and returns it. This can be useful if you need to + /// manage the lifetime of the [`ScreenGuard`](ScreenGuard) instance + /// separately. pub fn take_screen_guard(&mut self) -> Option<ScreenGuard> { self.screen.take() } + /// Draws the in-memory screen to the terminal on `stdout`. This is done + /// using a diff mechanism to only update the parts of the terminal which + /// are different from the in-memory screen. pub fn refresh(&mut self) -> Result<()> { let diff = self.next().screen().state_diff(self.cur().screen()); write_stdout(&diff)?; |