diff options
author | Canop <cano.petrole@gmail.com> | 2020-06-23 18:19:14 +0200 |
---|---|---|
committer | Canop <cano.petrole@gmail.com> | 2020-06-23 18:19:14 +0200 |
commit | ed69d7b084788907d015332397cdb4c8e238f30c (patch) | |
tree | 359ed0a7ea4d3817df6976d0784af68a0bdb5f96 | |
parent | 440c136f1f7e029720b68769c2569785fd52d41a (diff) |
restore broot on return from an application launched in terminal
This might
fix #38
fix #144
fix #158
but more tests would be needed and some applications might have
problems.
I mostly tested by launching vi from broot with
`leave_broot = false`: vi runs correctly and broot is OK when
I quit broot.
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | src/app/app.rs | 10 | ||||
-rw-r--r-- | src/app/panel.rs | 3 | ||||
-rw-r--r-- | src/app/state.rs | 7 | ||||
-rw-r--r-- | src/browser/browser_state.rs | 6 | ||||
-rw-r--r-- | src/conf/default_conf.rs | 3 | ||||
-rw-r--r-- | src/help/help_state.rs | 1 | ||||
-rw-r--r-- | src/launchable.rs | 26 | ||||
-rw-r--r-- | src/main.rs | 2 | ||||
-rw-r--r-- | src/verb/external_execution.rs | 7 | ||||
-rw-r--r-- | website/docs/tricks.md | 1 |
11 files changed, 57 insertions, 13 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index b12e2b2..bc2c75c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ ### next version +#### Major feature: keep broot open behind terminal editors +If you now open vi or emacs from broot with `leave_broot = false` you should +be back in broot after you quit the editor. Fix +#### Minor changes: - it's possible to define input edition shortcuts - Fix #235 - MacOS: config directory for new install is ~/.config/broot - Fix #103 diff --git a/src/app/app.rs b/src/app/app.rs index ada3664..f9efa32 100644 --- a/src/app/app.rs +++ b/src/app/app.rs @@ -122,6 +122,7 @@ impl App { /// or a new one. fn apply_command( &mut self, + w: &mut W, cmd: Command, screen: &mut Screen, panel_skin: &PanelSkin, @@ -132,6 +133,7 @@ impl App { let is_input_invocation = cmd.is_verb_invocated_from_input(); let other_path = self.get_other_panel_path(); match self.mut_panel().apply_command( + w, &cmd, &other_path, screen, @@ -153,7 +155,7 @@ impl App { self.mut_panel().set_input_arg(new_arg); let new_input = self.panel().get_input_content(); let cmd = Command::from_raw(new_input, false); - self.mut_panel().apply_command(&cmd, &other_path, screen, panel_skin, con)?; + self.mut_panel().apply_command(w, &cmd, &other_path, screen, panel_skin, con)?; } } else { self.quitting = true; @@ -215,7 +217,7 @@ impl App { self.mut_panel().clear_input(); } if self.remove_state(screen) { - self.mut_panel().apply_command(&cmd, &other_path, screen, panel_skin, con)?; + self.mut_panel().apply_command(w, &cmd, &other_path, screen, panel_skin, con)?; } else if ESCAPE_TO_QUIT { self.quitting = true; } @@ -306,7 +308,7 @@ impl App { if let Some(unparsed_commands) = &con.launch_args.commands { for (input, arg_cmd) in parse_command_sequence(unparsed_commands, con)? { self.mut_panel().set_input_content(input); - self.apply_command(arg_cmd, screen, &skin.focused, con)?; + self.apply_command(w, arg_cmd, screen, &skin.focused, con)?; self.display_panels(w, screen, &skin, con)?; w.flush()?; self.do_pending_tasks(screen, con, &mut dam)?; @@ -356,7 +358,7 @@ impl App { // event handled by the panel let cmd = self.mut_panel().add_event(w, event, con)?; debug!("command after add_event: {:?}", &cmd); - self.apply_command(cmd, screen, &skin.focused, con)?; + self.apply_command(w, cmd, screen, &skin.focused, con)?; } } self.display_panels(w, screen, &skin, con)?; diff --git a/src/app/panel.rs b/src/app/panel.rs index 52a756a..397908e 100644 --- a/src/app/panel.rs +++ b/src/app/panel.rs @@ -49,6 +49,7 @@ impl Panel { pub fn apply_command( &mut self, + w: &mut W, cmd: &Command, other_path: &Option<PathBuf>, screen: &mut Screen, @@ -64,7 +65,7 @@ impl Panel { areas: &self.areas, panel_purpose: self.purpose, }; - let result = self.states[state_idx].on_command(&cc, screen); + let result = self.states[state_idx].on_command(w, &cc, screen); self.status = Some(self.state().get_status(cmd, other_path, con)); debug!("result in panel {:?}: {:?}", &self.id, &result); result diff --git a/src/app/state.rs b/src/app/state.rs index b3e8300..a60ce5e 100644 --- a/src/app/state.rs +++ b/src/app/state.rs @@ -56,6 +56,7 @@ pub trait AppState { /// by a key shorctut) fn on_internal( &mut self, + w: &mut W, internal_exec: &InternalExecution, input_invocation: Option<&VerbInvocation>, trigger_type: TriggerType, @@ -66,6 +67,7 @@ pub trait AppState { /// change the state, does no rendering fn on_command( &mut self, + w: &mut W, cc: &CmdContext, screen: &mut Screen, ) -> Result<AppStateCmdResult, ProgramError> { @@ -87,6 +89,7 @@ pub trait AppState { let verb = &con.verb_store.verbs[*index]; match &verb.execution { VerbExecution::Internal(internal_exec) => self.on_internal( + w, internal_exec, input_invocation.as_ref(), TriggerType::Other, @@ -94,6 +97,7 @@ pub trait AppState { screen, ), VerbExecution::External(external) => external.to_cmd_result( + w, self.selected_path(), &cc.other_path, if let Some(inv) = &input_invocation { @@ -109,6 +113,7 @@ pub trait AppState { internal, input_invocation, } => self.on_internal( + w, &InternalExecution::from_internal(*internal), input_invocation.as_ref(), TriggerType::Other, @@ -122,6 +127,7 @@ pub trait AppState { } else { match &verb.execution { VerbExecution::Internal(internal_exec) => self.on_internal( + w, internal_exec, Some(invocation), TriggerType::Input, @@ -130,6 +136,7 @@ pub trait AppState { ), VerbExecution::External(external) => { external.to_cmd_result( + w, self.selected_path(), &cc.other_path, &invocation.args, diff --git a/src/browser/browser_state.rs b/src/browser/browser_state.rs index 9fedacd..d46b8e9 100644 --- a/src/browser/browser_state.rs +++ b/src/browser/browser_state.rs @@ -156,6 +156,7 @@ impl BrowserState { pub fn open_selection_quit_broot( &mut self, + w: &mut W, con: &AppContext, ) -> Result<AppStateCmdResult, ProgramError> { let tree = self.displayed_tree(); @@ -164,7 +165,7 @@ impl BrowserState { TreeLineType::File => make_opener(line.path.clone(), line.is_exe(), con), TreeLineType::Dir | TreeLineType::SymLinkToDir(_) => { Ok(if con.launch_args.cmd_export_path.is_some() { - CD.to_cmd_result(&line.target(), &None, &None, con)? + CD.to_cmd_result(w, &line.target(), &None, &None, con)? } else { AppStateCmdResult::DisplayError( "This feature needs broot to be launched with the `br` script".to_owned(), @@ -368,6 +369,7 @@ impl AppState for BrowserState { fn on_internal( &mut self, + w: &mut W, internal_exec: &InternalExecution, input_invocation: Option<&VerbInvocation>, trigger_type: TriggerType, @@ -429,7 +431,7 @@ impl AppState for BrowserState { } Internal::open_stay => self.open_selection_stay_in_broot(screen, con, bang, false)?, Internal::open_stay_filter => self.open_selection_stay_in_broot(screen, con, bang, true)?, - Internal::open_leave => self.open_selection_quit_broot(con)?, + Internal::open_leave => self.open_selection_quit_broot(w, con)?, Internal::line_down => { self.displayed_tree_mut().move_selection(1, page_height); AppStateCmdResult::Keep diff --git a/src/conf/default_conf.rs b/src/conf/default_conf.rs index a9c5083..27cc312 100644 --- a/src/conf/default_conf.rs +++ b/src/conf/default_conf.rs @@ -75,10 +75,12 @@ invocation = "edit" key = "F2" shortcut = "e" execution = "$EDITOR {file}" +leave_broot = false [[verbs]] invocation = "create {subpath}" execution = "$EDITOR {directory}/{subpath}" +leave_broot = false [[verbs]] invocation = "git_diff" @@ -95,6 +97,7 @@ execution = "git diff {file}" name = "view" invocation = "view" execution = "$PAGER {file}" +leave_broot = false # A popular set of shorctuts for going up and down: # diff --git a/src/help/help_state.rs b/src/help/help_state.rs index 59408df..9966472 100644 --- a/src/help/help_state.rs +++ b/src/help/help_state.rs @@ -130,6 +130,7 @@ impl AppState for HelpState { fn on_internal( &mut self, + _w: &mut W, internal_exec: &InternalExecution, input_invocation: Option<&VerbInvocation>, _trigger_type: TriggerType, diff --git a/src/launchable.rs b/src/launchable.rs index 80031ef..6c99796 100644 --- a/src/launchable.rs +++ b/src/launchable.rs @@ -1,12 +1,21 @@ use { crate::{ - display::{DisplayableTree, Screen}, + display::{DisplayableTree, Screen, W}, errors::ProgramError, skin::StyleMap, tree::Tree, }, + crossterm::{ + terminal::{EnterAlternateScreen, LeaveAlternateScreen}, + QueueableCommand, + }, open, - std::{env, io, path::PathBuf, process::Command}, + std::{ + env, + io::{self, Write}, + path::PathBuf, + process::Command, + }, }; /// description of a possible launch of an external program @@ -80,7 +89,7 @@ impl Launchable { } } - pub fn execute(&self) -> Result<(), ProgramError> { + pub fn execute(&self, mut w: Option<&mut W>) -> Result<(), ProgramError> { match self { Launchable::Printer { to_print } => { println!("{}", to_print); @@ -91,6 +100,13 @@ impl Launchable { dp.write_on(&mut std::io::stdout()) } Launchable::Program { exe, args } => { + // we restore the normal terminal in case the executable + // is a terminal application, and we'll switch back to + // broot's alternate terminal when we're back to broot + if let Some(ref mut w) = &mut w { + w.queue(LeaveAlternateScreen).unwrap(); + w.flush().unwrap(); + } Command::new(&exe) .args(args.iter()) .spawn() @@ -99,6 +115,10 @@ impl Launchable { program: exe.clone(), source, })?; + if let Some(ref mut w) = &mut w { + w.queue(EnterAlternateScreen).unwrap(); + w.flush().unwrap(); + } Ok(()) } Launchable::SystemOpen { path } => { diff --git a/src/main.rs b/src/main.rs index c137e46..2fb741d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,7 +44,7 @@ fn main() { configure_log(); match cli::run() { Ok(Some(launchable)) => { - if let Err(e) = launchable.execute() { + if let Err(e) = launchable.execute(None) { warn!("Failed to launch {:?}", &launchable); warn!("Error: {:?}", e); eprintln!("{}", e); diff --git a/src/verb/external_execution.rs b/src/verb/external_execution.rs index b37e4b2..2e5cce4 100644 --- a/src/verb/external_execution.rs +++ b/src/verb/external_execution.rs @@ -10,6 +10,7 @@ use { super::{ExternalExecutionMode, VerbInvocation}, crate::{ app::*, + display::W, errors::{ConfError, ProgramError}, launchable::Launchable, path, @@ -204,6 +205,7 @@ impl ExternalExecution { pub fn to_cmd_result( &self, + w: &mut W, file: &Path, other_file: &Option<PathBuf>, args: &Option<String>, @@ -212,7 +214,7 @@ impl ExternalExecution { if self.exec_mode.is_from_shell() { self.exec_from_shell_cmd_result(file, other_file, args, con) } else { - self.exec_cmd_result(file, other_file, args) + self.exec_cmd_result(w, file, other_file, args) } } @@ -248,6 +250,7 @@ impl ExternalExecution { /// launched by broot fn exec_cmd_result( &self, + w: &mut W, file: &Path, other_file: &Option<PathBuf>, args: &Option<String>, @@ -257,7 +260,7 @@ impl ExternalExecution { Ok(AppStateCmdResult::from(launchable)) } else { info!("Executing not leaving, launchable {:?}", launchable); - let execution = launchable.execute(); + let execution = launchable.execute(Some(w)); match execution { Ok(()) => { debug!("ok"); diff --git a/website/docs/tricks.md b/website/docs/tricks.md index db28b23..3fe923f 100644 --- a/website/docs/tricks.md +++ b/website/docs/tricks.md @@ -49,6 +49,7 @@ Here's an example of configuration changing the behaviour on open: invocation = "edit" key = "enter" execution = "$EDITOR {file}" +leave_broot = false apply_to = "file" ``` |