tuirealm 4.0.0

A tui-rs framework to build tui interfaces, inspired by React and Elm.
Documentation
use termwiz::terminal::Terminal as _;

use super::{TerminalAdapter, TerminalResult};
use crate::ratatui::backend::TermwizBackend;
use crate::ratatui::{Terminal, TerminalOptions};
use crate::terminal::TerminalError;

/// [`TermwizTerminalAdapter`] is the adapter for the [`termwiz`] terminal
///
/// It implements the [`TerminalAdapter`] trait
///
/// # Restore
///
/// `termwiz` automatically restores all modes on Drop.
///
/// ## On Panic
///
/// Due to restoring on `Drop` and [not providing a simple way to do it in a panic](https://github.com/wezterm/wezterm/issues/7552), panic messages may not display correctly:
/// - in alternative screen, messages may get "eaten" / not displayed
/// - in raw mode, messages will not get displayed correctly and may have a lot of padding
pub struct TermwizTerminalAdapter {
    terminal: Terminal<TermwizBackend>,
}

impl TermwizTerminalAdapter {
    /// Create a new termwiz instance with default ratatui Terminal options
    pub fn new() -> TerminalResult<Self> {
        Self::new_with_options(TerminalOptions::default())
    }

    /// Create a new termwiz instance with custom ratatui Terminal options
    pub fn new_with_options(options: TerminalOptions) -> TerminalResult<Self> {
        let backend = TermwizBackend::new().map_err(|_| TerminalError::CannotConnectStdout)?;
        let terminal = Terminal::with_options(backend, options)
            .map_err(|_| TerminalError::CannotConnectStdout)?;

        Ok(Self { terminal })
    }
}

impl TerminalAdapter for TermwizTerminalAdapter {
    type Backend = TermwizBackend;

    fn enable_raw_mode(&mut self) -> TerminalResult<()> {
        self.terminal
            .backend_mut()
            .buffered_terminal_mut()
            .terminal()
            .set_raw_mode()
            .map_err(|_| TerminalError::CannotToggleRawMode)
    }

    /// UNSUPPORTED in termwiz
    fn disable_raw_mode(&mut self) -> TerminalResult<()> {
        Err(TerminalError::Unsupported)
    }

    fn enter_alternate_screen(&mut self) -> TerminalResult<()> {
        self.terminal
            .backend_mut()
            .buffered_terminal_mut()
            .terminal()
            .enter_alternate_screen()
            .map_err(|_| TerminalError::CannotEnterAlternateMode)
    }

    fn leave_alternate_screen(&mut self) -> TerminalResult<()> {
        self.terminal
            .backend_mut()
            .buffered_terminal_mut()
            .terminal()
            .exit_alternate_screen()
            .map_err(|_| TerminalError::CannotLeaveAlternateMode)
    }

    /// UNSUPPORTED in termwiz
    fn enable_mouse_capture(&mut self) -> TerminalResult<()> {
        Err(TerminalError::Unsupported)
    }

    /// UNSUPPORTED in termwiz
    fn disable_mouse_capture(&mut self) -> TerminalResult<()> {
        Err(TerminalError::Unsupported)
    }

    fn raw_mut(&mut self) -> &mut Terminal<TermwizBackend> {
        &mut self.terminal
    }

    fn raw(&self) -> &Terminal<TermwizBackend> {
        &self.terminal
    }
}