summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCanop <cano.petrole@gmail.com>2020-06-23 18:19:14 +0200
committerCanop <cano.petrole@gmail.com>2020-06-23 18:19:14 +0200
commited69d7b084788907d015332397cdb4c8e238f30c (patch)
tree359ed0a7ea4d3817df6976d0784af68a0bdb5f96
parent440c136f1f7e029720b68769c2569785fd52d41a (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.md4
-rw-r--r--src/app/app.rs10
-rw-r--r--src/app/panel.rs3
-rw-r--r--src/app/state.rs7
-rw-r--r--src/browser/browser_state.rs6
-rw-r--r--src/conf/default_conf.rs3
-rw-r--r--src/help/help_state.rs1
-rw-r--r--src/launchable.rs26
-rw-r--r--src/main.rs2
-rw-r--r--src/verb/external_execution.rs7
-rw-r--r--website/docs/tricks.md1
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"
```