mirror of
https://github.com/alexpasmantier/television.git
synced 2025-06-11 22:07:11 +00:00
110 lines
2.3 KiB
Rust
110 lines
2.3 KiB
Rust
use std::{
|
|
io::{stderr, LineWriter, Write},
|
|
ops::{Deref, DerefMut},
|
|
};
|
|
|
|
use anyhow::Result;
|
|
use crossterm::{
|
|
cursor,
|
|
event::DisableMouseCapture,
|
|
execute,
|
|
terminal::{
|
|
disable_raw_mode, enable_raw_mode, is_raw_mode_enabled,
|
|
EnterAlternateScreen, LeaveAlternateScreen,
|
|
},
|
|
};
|
|
use ratatui::{backend::CrosstermBackend, layout::Size};
|
|
use tracing::debug;
|
|
|
|
#[allow(dead_code)]
|
|
pub struct Tui<W>
|
|
where
|
|
W: Write,
|
|
{
|
|
pub terminal: ratatui::Terminal<CrosstermBackend<W>>,
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
impl<W> Tui<W>
|
|
where
|
|
W: Write,
|
|
{
|
|
pub fn new(writer: W) -> Result<Self> {
|
|
Ok(Self {
|
|
terminal: ratatui::Terminal::new(CrosstermBackend::new(writer))?,
|
|
})
|
|
}
|
|
|
|
pub fn size(&self) -> Result<Size> {
|
|
Ok(self.terminal.size()?)
|
|
}
|
|
|
|
pub fn enter(&mut self) -> Result<()> {
|
|
enable_raw_mode()?;
|
|
let mut buffered_stderr = LineWriter::new(stderr());
|
|
execute!(buffered_stderr, EnterAlternateScreen)?;
|
|
self.terminal.clear()?;
|
|
if cfg!(not(windows)) {
|
|
execute!(buffered_stderr, DisableMouseCapture)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub fn exit(&mut self) -> Result<()> {
|
|
if is_raw_mode_enabled()? {
|
|
debug!("Exiting terminal");
|
|
|
|
disable_raw_mode()?;
|
|
let mut buffered_stderr = LineWriter::new(stderr());
|
|
execute!(buffered_stderr, cursor::Show)?;
|
|
execute!(buffered_stderr, LeaveAlternateScreen)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn suspend(&mut self) -> Result<()> {
|
|
self.exit()?;
|
|
#[cfg(not(windows))]
|
|
signal_hook::low_level::raise(signal_hook::consts::signal::SIGTSTP)?;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn resume(&mut self) -> Result<()> {
|
|
self.enter()?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl<W> Deref for Tui<W>
|
|
where
|
|
W: Write,
|
|
{
|
|
type Target = ratatui::Terminal<CrosstermBackend<W>>;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.terminal
|
|
}
|
|
}
|
|
|
|
impl<W> DerefMut for Tui<W>
|
|
where
|
|
W: Write,
|
|
{
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
&mut self.terminal
|
|
}
|
|
}
|
|
|
|
impl<W> Drop for Tui<W>
|
|
where
|
|
W: Write,
|
|
{
|
|
fn drop(&mut self) {
|
|
match self.exit() {
|
|
Ok(()) => debug!("Successfully exited terminal"),
|
|
Err(e) => debug!("Failed to exit terminal: {:?}", e),
|
|
}
|
|
}
|
|
}
|