From c719ec7a3cb6ca3d2346f48dc11d2e0d5ee10d36 Mon Sep 17 00:00:00 2001 From: rabite Date: Mon, 18 Mar 2019 02:04:07 +0100 Subject: [PATCH] running subshells in the foreground --- src/file_browser.rs | 29 +++++++++++++++++++++++++++++ src/main.rs | 3 ++- src/proclist.rs | 4 +++- src/term.rs | 43 +++++++++++++++++++++++++++++++------------ 4 files changed, 65 insertions(+), 14 deletions(-) diff --git a/src/file_browser.rs b/src/file_browser.rs index abf144f..831f96b 100644 --- a/src/file_browser.rs +++ b/src/file_browser.rs @@ -652,6 +652,34 @@ impl FileBrowser { Ok(()) } + pub fn run_subshell(&mut self) -> HResult<()> { + self.core.get_sender().send(Events::InputEnabled(false))?; + + self.core.screen.cursor_show().log(); + self.core.screen.drop_screen(); + + let shell = std::env::var("SHELL").unwrap_or("bash".into()); + let status = std::process::Command::new(&shell).status(); + + self.core.screen.reset_screen(); + + + self.core.get_sender().send(Events::InputEnabled(true))?; + + match status { + Ok(status) => + self.show_status(&format!("\"{}\" exited with {}", + shell, status)).log(), + Err(err) => + self.show_status(&format!("Can't run this \"{}\": {}", + shell, err)).log() + } + + + + Ok(()) + } + pub fn get_footer(&self) -> HResult { let xsize = self.get_coordinates()?.xsize(); let ypos = self.get_coordinates()?.position().y(); @@ -759,6 +787,7 @@ impl Widget for FileBrowser { Key::Char('m') => { self.add_bookmark()?; }, Key::Char('w') => { self.proc_view.lock()?.popup()?; }, Key::Char('l') => self.log_view.lock()?.popup()?, + Key::Char('z') => self.run_subshell()?, _ => { self.main_widget_mut()?.on_key(key)?; }, } self.update_preview()?; diff --git a/src/main.rs b/src/main.rs index 0659a09..ddf7d4e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,11 +64,12 @@ fn main() -> HResult<()> { // do this early so it might be ready when needed crate::files::load_tags().ok(); - let core = WidgetCore::new().expect("Can't create WidgetCore!"); + let mut core = WidgetCore::new().expect("Can't create WidgetCore!"); match run(core.clone()) { Ok(_) => Ok(()), Err(err) => { + core.screen.drop_screen(); eprintln!("{:?}\n{:?}", err, err.cause()); return Err(err); } diff --git a/src/proclist.rs b/src/proclist.rs index 38b66fc..f05612f 100644 --- a/src/proclist.rs +++ b/src/proclist.rs @@ -114,7 +114,9 @@ impl Listable for ListView> { impl ListView> { fn run_proc(&mut self, cmd: &str) -> HResult<()> { - let handle = std::process::Command::new("sh") + let shell = std::env::var("SHELL").unwrap_or("sh".into()); + + let handle = std::process::Command::new(shell) .arg("-c") .arg(cmd) .stdin(std::process::Stdio::null()) diff --git a/src/term.rs b/src/term.rs index 6b19c1b..94e0c5d 100644 --- a/src/term.rs +++ b/src/term.rs @@ -10,31 +10,47 @@ use parse_ansi::parse_bytes; use crate::fail::HResult; +pub type TermMode = AlternateScreen>>>; + #[derive(Clone)] pub struct Screen { - screen: Arc>>>>> + screen: Arc>> } impl Screen { pub fn new() -> HResult { - let screen = BufWriter::new(std::io::stdout()); - let screen = AlternateScreen::from(screen); - let mut screen = MouseTerminal::from(screen).into_raw_mode()?; + let screen = BufWriter::new(std::io::stdout()).into_raw_mode()?; + let mut screen = MouseTerminal::from(screen); + let mut screen = AlternateScreen::from(screen); + screen.cursor_hide()?; - screen.flush()?; - screen.clear()?; Ok(Screen { - screen: Arc::new(Mutex::new(screen)) + screen: Arc::new(Mutex::new(Some(screen))) }) } + + pub fn drop_screen(&mut self) { + self.cursor_show(); + self.to_main_screen(); + self.screen = Arc::new(Mutex::new(None)); + + // Terminal stays fucked without this. Why? + std::process::Command::new("reset").arg("-I").spawn(); + } + + pub fn reset_screen(&mut self) -> HResult<()> { + let screen = Screen::new()?.screen.lock()?.take()?; + *self.screen.lock()? = Some(screen); + Ok(()) + } } impl Write for Screen { fn write(&mut self, buf: &[u8]) -> std::io::Result { - self.screen.lock().unwrap().write(buf) + self.screen.lock().unwrap().as_mut().unwrap().write(buf) } fn flush(&mut self) -> std::io::Result<()> { - self.screen.lock().unwrap().flush() + self.screen.lock().unwrap().as_mut().unwrap().flush() } } @@ -80,12 +96,15 @@ pub trait ScreenExt: Write { write!(self, "\x1bkhunter: {}\x1b\\", title)?; Ok(()) } + fn to_main_screen(&mut self) -> HResult<()> { + write!(self, "{}", termion::screen::ToMainScreen)?; + self.flush()?; + Ok(()) + } } -impl ScreenExt for AlternateScreen> {} -impl ScreenExt for AlternateScreen {} -impl ScreenExt for AlternateScreen> {} impl ScreenExt for Screen {} +impl ScreenExt for TermMode {} pub fn xsize() -> u16 { let (xsize, _) = termion::terminal_size().unwrap();