git_iblame/extensions/
terminal_raw_mode_scope.rs

1use std::io;
2
3use crossterm::terminal;
4use log::*;
5
6/// Enable or disable the
7/// [terminal raw mode](https://docs.rs/crossterm/latest/crossterm/terminal/index.html#raw-mode)
8/// while its instance is in scope.
9///
10/// While it automatically resets the mode when it's out of scope,
11/// `reset()` should be called at the end
12/// to avoid it being dropped earlier.
13/// # Examples
14/// ```no_run
15/// # fn main() -> std::io::Result<()> {
16/// use git_iblame::TerminalRawModeScope;
17///
18/// let terminal_raw_mode = TerminalRawModeScope::new(true)?;
19/// // Do work.
20/// terminal_raw_mode.reset();
21/// # Ok(())
22/// # }
23/// ```
24pub struct TerminalRawModeScope {
25    is_enabled: bool,
26}
27
28impl TerminalRawModeScope {
29    pub fn new(enable: bool) -> io::Result<Self> {
30        Self::enable(enable)?;
31        Ok(Self { is_enabled: enable })
32    }
33
34    pub fn reset(&self) {
35        if let Err(error) = Self::enable(!self.is_enabled) {
36            warn!("Failed to change terminal raw mode, ignored: {error}");
37        }
38    }
39
40    fn enable(enable: bool) -> io::Result<()> {
41        debug!("TerminalRawModeScope.enable({enable})");
42        if enable {
43            terminal::enable_raw_mode()
44        } else {
45            terminal::disable_raw_mode()
46        }
47    }
48}
49
50impl Drop for TerminalRawModeScope {
51    fn drop(&mut self) {
52        self.reset();
53    }
54}