diff --git a/Cargo.toml b/Cargo.toml index 0b18faf..cd4dd5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ anymap2 = "0.13.0" derive_more = "0.99.16" thiserror = "1.0.30" crossterm = "0.17" +libc = "0.2" tui = { version = "0.17", optional = true } xi-rope = "0.3.0" intervaltree = { version = "0.2.6", optional = true } diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index 3c893c1..3462d3e 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -6,8 +6,17 @@ //! //! [tui]: https://docs.rs/tui/latest/tui/ //! -use tui::buffer::Buffer; -use tui::layout::Rect; +use std::io::{stdout, Stdout, Write}; +use std::process; + +use libc; + +use tui::{backend::CrosstermBackend, buffer::Buffer, layout::Rect, Terminal}; + +use crossterm::{ + execute, + terminal::{EnterAlternateScreen, LeaveAlternateScreen}, +}; use crate::input::InputContext; @@ -17,6 +26,7 @@ use crate::editing::base::{ Axis, CloseFlags, Count, + EditInfo, EditResult, MoveDir1D, ScrollStyle, @@ -89,3 +99,36 @@ pub trait WindowContainer { fn window_command(&mut self, action: WindowAction, ctx: &C) -> EditResult; } + +pub trait TerminalExtOps { + type Result; + + fn program_suspend(&mut self) -> Self::Result; +} + +impl TerminalExtOps for Terminal> { + type Result = crossterm::Result>; + + fn program_suspend(&mut self) -> Self::Result { + let mut stdout = stdout(); + + // Restore old terminal state. + crossterm::terminal::disable_raw_mode()?; + execute!(self.backend_mut(), LeaveAlternateScreen)?; + self.show_cursor()?; + + // Send SIGTSTP to process. + let pid = process::id(); + + unsafe { + libc::kill(pid as i32, libc::SIGTSTP); + } + + // Restore application terminal state. + crossterm::terminal::enable_raw_mode()?; + crossterm::execute!(stdout, EnterAlternateScreen)?; + self.clear()?; + + Ok(None) + } +}