diff options
author | Canop <cano.petrole@gmail.com> | 2021-06-13 16:45:44 +0200 |
---|---|---|
committer | Canop <cano.petrole@gmail.com> | 2021-06-13 16:45:44 +0200 |
commit | dec7324fd505e41decf152492ae4942ffed36db0 (patch) | |
tree | 0caf0e1e5ce0f0a0191914527a3b5307850a976a /src | |
parent | 442e304c3f3ca867d09103301efee42da7ea969f (diff) |
`{root}` verb argument
Fix #395
Diffstat (limited to 'src')
-rw-r--r-- | src/app/app.rs | 31 | ||||
-rw-r--r-- | src/app/app_state.rs | 11 | ||||
-rw-r--r-- | src/app/cmd_context.rs | 2 | ||||
-rw-r--r-- | src/app/panel.rs | 2 | ||||
-rw-r--r-- | src/app/panel_state.rs | 22 | ||||
-rw-r--r-- | src/browser/browser_state.rs | 4 | ||||
-rw-r--r-- | src/command/panel_input.rs | 5 | ||||
-rw-r--r-- | src/conf/verb_conf.rs | 3 | ||||
-rw-r--r-- | src/verb/execution_builder.rs | 29 | ||||
-rw-r--r-- | src/verb/verb.rs | 6 |
10 files changed, 75 insertions, 40 deletions
diff --git a/src/app/app.rs b/src/app/app.rs index f9ea5b7..44217e2 100644 --- a/src/app/app.rs +++ b/src/app/app.rs @@ -10,6 +10,7 @@ use { launchable::Launchable, path::closest_dir, skin::*, + stage::Stage, task_sync::{Dam, Either}, verb::Internal, }, @@ -54,10 +55,6 @@ pub struct App { stage_panel: Option<PanelId>, - /// the current root, updated when a panel with this concept - /// becomes active - root: PathBuf, - /// an optional copy of the root for the --server shared_root: Option<Arc<Mutex<PathBuf>>>, @@ -99,7 +96,6 @@ impl App { created_panels_count: 1, preview_panel: None, stage_panel: None, - root: con.launch_args.root.clone(), shared_root: None, tx_seqs, rx_seqs, @@ -271,7 +267,6 @@ impl App { let mut error: Option<String> = None; let is_input_invocation = cmd.is_verb_invocated_from_input(); let app_cmd_context = AppCmdContext { - other_path: self.get_other_panel_path(), panel_skin, preview_panel: self.preview_panel, stage_panel: self.stage_panel, @@ -325,7 +320,6 @@ impl App { let new_input = self.panel().get_input_content(); let cmd = Command::from_raw(new_input, false); let app_cmd_context = AppCmdContext { - other_path: self.get_other_panel_path(), panel_skin, preview_panel: self.preview_panel, stage_panel: self.stage_panel, @@ -373,7 +367,6 @@ impl App { } self.active_panel_idx = idx; let app_cmd_context = AppCmdContext { - other_path: self.get_other_panel_path(), panel_skin, preview_panel: self.preview_panel, stage_panel: self.stage_panel, @@ -476,7 +469,6 @@ impl App { } if self.remove_state() { let app_cmd_context = AppCmdContext { - other_path: self.get_other_panel_path(), panel_skin, preview_panel: self.preview_panel, stage_panel: self.stage_panel, @@ -507,19 +499,21 @@ impl App { if let Some(text) = error { self.mut_panel().set_error(text); } - self.update_preview(con); - - if let Some(path) = self.state().selected_path() { - self.root = path.to_path_buf(); + app_state.other_panel_path = self.get_other_panel_path(); + if let Some(path) = self.state().tree_root() { + app_state.root = path.to_path_buf(); } + if let Some(shared_root) = &mut self.shared_root { if let Ok(mut root) = shared_root.lock() { - *root = self.root.clone(); + *root = app_state.root.clone(); } } + self.update_preview(con); + Ok(()) } @@ -616,7 +610,6 @@ impl App { if self.do_pending_task(app_state, con, dam) { self.update_preview(con); // the selection may have changed let app_cmd_context = AppCmdContext { - other_path: self.get_other_panel_path(), panel_skin: &skin.focused, preview_panel: self.preview_panel, stage_panel: self.stage_panel, @@ -676,7 +669,11 @@ impl App { let rx_events = event_source.receiver(); let mut dam = Dam::from(rx_events); let skin = AppSkin::new(conf, con.launch_args.no_style); - let mut app_state = AppState::default(); + let mut app_state = AppState { + stage: Stage::default(), + root: con.launch_args.root.clone(), + other_panel_path: None, + }; self.screen.clear_bottom_right_char(w, &skin.focused)?; @@ -689,7 +686,7 @@ impl App { #[cfg(unix)] let _server = con.launch_args.listen.as_ref() .map(|server_name| { - let shared_root = Arc::new(Mutex::new(self.root.clone())); + let shared_root = Arc::new(Mutex::new(app_state.root.clone())); let server = crate::net::Server::new( &server_name, self.tx_seqs.clone(), diff --git a/src/app/app_state.rs b/src/app/app_state.rs index 474aa00..4b20376 100644 --- a/src/app/app_state.rs +++ b/src/app/app_state.rs @@ -2,13 +2,22 @@ use { crate::{ stage::Stage, }, + std::path::PathBuf, }; /// global mutable state -#[derive(Debug, Default)] +#[derive(Debug)] pub struct AppState { pub stage: Stage, + + /// the current root, updated when a panel with this concept + /// becomes active or changes its root + pub root: PathBuf, + + /// the selected path in another panel than the currently + /// active one, if any + pub other_panel_path: Option<PathBuf>, } impl AppState { diff --git a/src/app/cmd_context.rs b/src/app/cmd_context.rs index f6a03d8..f5a955a 100644 --- a/src/app/cmd_context.rs +++ b/src/app/cmd_context.rs @@ -5,7 +5,6 @@ use { display::{Areas, Screen}, skin::PanelSkin, }, - std::path::PathBuf, }; /// short lived wrapping of a few things which are needed for the handling @@ -18,7 +17,6 @@ pub struct CmdContext<'c> { /// the part of the immutable command execution context which comes from the app pub struct AppCmdContext<'c> { - pub other_path: Option<PathBuf>, pub panel_skin: &'c PanelSkin, pub preview_panel: Option<PanelId>, // id of the app's preview panel pub stage_panel: Option<PanelId>, // id of the app's preview panel diff --git a/src/app/panel.rs b/src/app/panel.rs index 61cea36..6a2f97c 100644 --- a/src/app/panel.rs +++ b/src/app/panel.rs @@ -129,7 +129,7 @@ impl Panel { con: &AppContext, ) -> Result<Command, ProgramError> { let sel_info = self.states[self.states.len() - 1].sel_info(&app_state); - self.input.on_event(w, event, con, sel_info, self.state().get_mode()) + self.input.on_event(w, event, con, sel_info, app_state, self.state().get_mode()) } pub fn push_state(&mut self, new_state: Box<dyn PanelState>) { diff --git a/src/app/panel_state.rs b/src/app/panel_state.rs index fba66c4..94d45af 100644 --- a/src/app/panel_state.rs +++ b/src/app/panel_state.rs @@ -433,7 +433,7 @@ pub trait PanelState { if verb.needs_selection && !self.has_at_least_one_selection(app_state) { return Ok(CmdResult::error("This verb needs a selection")); } - if verb.needs_another_panel && cc.app.other_path.is_none() { + if verb.needs_another_panel && app_state.other_panel_path.is_none() { return Ok(CmdResult::error("This verb needs another panel")); } match &verb.execution { @@ -461,7 +461,7 @@ pub trait PanelState { let exec_builder = ExecutionStringBuilder::with_invocation( &verb.invocation_parser, self.sel_info(app_state), - &cc.app.other_path, + app_state, if let Some(inv) = invocation { &inv.args } else { @@ -478,7 +478,7 @@ pub trait PanelState { seq_ex: &SequenceExecution, invocation: Option<&VerbInvocation>, app_state: &mut AppState, - cc: &CmdContext, + _cc: &CmdContext, ) -> Result<CmdResult, ProgramError> { let sel_info = self.sel_info(app_state); if matches!(sel_info, SelInfo::More(_)) { @@ -490,7 +490,7 @@ pub trait PanelState { let exec_builder = ExecutionStringBuilder::with_invocation( &verb.invocation_parser, sel_info, - &cc.app.other_path, + app_state, if let Some(inv) = invocation { &inv.args } else { @@ -618,6 +618,11 @@ pub trait PanelState { } } + /// must return None if the state doesn't display a file tree + fn tree_root(&self) -> Option<&Path> { + None + } + fn selected_path(&self) -> Option<&Path>; fn selection(&self) -> Option<Selection<'_>>; @@ -719,7 +724,7 @@ pub trait PanelState { Status::new("No matching verb (*?* for the list of verbs)", true) } PrefixSearchResult::Match(_, verb) => { - self.get_verb_status(verb, invocation, sel_info, cc) + self.get_verb_status(verb, invocation, sel_info, cc, app_state) } PrefixSearchResult::Matches(completions) => Status::new( format!( @@ -744,7 +749,8 @@ pub trait PanelState { verb: &Verb, invocation: &VerbInvocation, sel_info: SelInfo<'_>, - cc: &CmdContext, + _cc: &CmdContext, + app_state: &AppState, ) -> Status { if sel_info.count_paths() > 1 { if let VerbExecution::External(external) = &verb.execution { @@ -757,13 +763,13 @@ pub trait PanelState { } // right now there's no check for sequences but they're inherently dangereous } - if let Some(err) = verb.check_args(&sel_info, invocation, &cc.app.other_path) { + if let Some(err) = verb.check_args(&sel_info, invocation, &app_state.other_panel_path) { Status::new(err, true) } else { Status::new( verb.get_status_markdown( sel_info, - &cc.app.other_path, + app_state, invocation, ), false, diff --git a/src/browser/browser_state.rs b/src/browser/browser_state.rs index 772ad3c..70d8eec 100644 --- a/src/browser/browser_state.rs +++ b/src/browser/browser_state.rs @@ -147,6 +147,10 @@ impl BrowserState { impl PanelState for BrowserState { + fn tree_root(&self) -> Option<&Path> { + Some(self.root()) + } + fn get_type(&self) -> PanelStateType { PanelStateType::Tree } diff --git a/src/command/panel_input.rs b/src/command/panel_input.rs index 462ed80..ff0c9cd 100644 --- a/src/command/panel_input.rs +++ b/src/command/panel_input.rs @@ -73,9 +73,10 @@ impl PanelInput { event: Event, con: &AppContext, sel_info: SelInfo<'_>, + app_state: &AppState, mode: Mode, ) -> Result<Command, ProgramError> { - let cmd = self.get_command(event, con, sel_info, mode); + let cmd = self.get_command(event, con, sel_info, app_state, mode); self.input_field.display_on(w)?; Ok(cmd) } @@ -161,6 +162,7 @@ impl PanelInput { event: Event, con: &AppContext, sel_info: SelInfo<'_>, + app_state: &AppState, mode: Mode, ) -> Command { match event { @@ -294,6 +296,7 @@ impl PanelInput { if let Some(invocation_parser) = &verb.invocation_parser { let exec_builder = ExecutionStringBuilder::without_invocation( sel_info, + app_state, ); let verb_invocation = exec_builder.invocation_with_default( &invocation_parser.invocation_pattern diff --git a/src/conf/verb_conf.rs b/src/conf/verb_conf.rs index 5923b9b..dc269e1 100644 --- a/src/conf/verb_conf.rs +++ b/src/conf/verb_conf.rs @@ -69,7 +69,8 @@ impl TryFrom<&VerbConf> for Verb { let working_dir = match (vc.set_working_dir, &vc.working_dir) { (Some(false), _) => None, (_, Some(s)) => Some(s.clone()), - (_, None) => Some("{directory}".to_owned()), + (Some(true), None) => Some("{directory}".to_owned()), + (None, None) => None, }; ExternalExecution::new( s, diff --git a/src/verb/execution_builder.rs b/src/verb/execution_builder.rs index 24fdf64..2d56e9a 100644 --- a/src/verb/execution_builder.rs +++ b/src/verb/execution_builder.rs @@ -1,7 +1,7 @@ use { super::*, crate::{ - app::{Selection, SelInfo, SelectionType}, + app::*, path, }, ahash::AHashMap, @@ -16,6 +16,9 @@ pub struct ExecutionStringBuilder<'b> { /// the current file selection pub sel_info: SelInfo<'b>, + /// the current root of the app + root: &'b Path, + /// the selection in the other panel, when there are exactly two other_file: Option<&'b PathBuf>, @@ -29,17 +32,19 @@ impl<'b> ExecutionStringBuilder<'b> { /// when a verb is triggered from a key shortcut) pub fn without_invocation( sel_info: SelInfo<'b>, + app_state: &'b AppState, ) -> Self { Self { sel_info, - other_file: None, + root: &app_state.root, + other_file: app_state.other_panel_path.as_ref(), invocation_values: None, } } pub fn with_invocation( invocation_parser: &Option<InvocationParser>, sel_info: SelInfo<'b>, - other_file: &'b Option<PathBuf>, + app_state: &'b AppState, invocation_args: &Option<String>, ) -> Self { let invocation_values = invocation_parser @@ -48,7 +53,8 @@ impl<'b> ExecutionStringBuilder<'b> { .and_then(|(parser, args)| parser.parse(args)); Self { sel_info, - other_file: other_file.as_ref(), + root: &app_state.root, + other_file: app_state.other_panel_path.as_ref(), invocation_values, } } @@ -96,6 +102,7 @@ impl<'b> ExecutionStringBuilder<'b> { ) -> Option<String> { debug!("repl name : {:?}", name); match name { + "root" => Some(path_to_string(self.root)), "line" => sel.map(|s| s.line.to_string()), "file" => sel.map(|s| s.path) .map(path_to_string), @@ -313,7 +320,9 @@ mod execution_builder_test { use { super::*, - crate::app::SelectionType, + crate::{ + stage::*, + }, }; fn check_build_execution_from_sel( @@ -329,7 +338,15 @@ mod execution_builder_test { stype: SelectionType::File, is_exe: false, }; - let mut builder = ExecutionStringBuilder::from_sel_info(SelInfo::One(sel)); + let app_state = AppState { + stage: Stage::default(), + root: PathBuf::from("/".to_owned()), + other_panel_path: None, + }; + let mut builder = ExecutionStringBuilder::without_invocation( + SelInfo::One(sel), + &app_state, + ); let mut map = AHashMap::default(); for (k, v) in replacements { map.insert(k.to_owned(), v.to_owned()); diff --git a/src/verb/verb.rs b/src/verb/verb.rs index df99941..99ec5bc 100644 --- a/src/verb/verb.rs +++ b/src/verb/verb.rs @@ -1,7 +1,7 @@ use { super::*, crate::{ - app::{Selection, SelInfo, SelectionType}, + app::*, errors::ConfError, keys, path::{self, PathAnchor}, @@ -219,7 +219,7 @@ impl Verb { pub fn get_status_markdown( &self, sel_info: SelInfo<'_>, - other_path: &Option<PathBuf>, + app_state: &AppState, invocation: &VerbInvocation, ) -> String { let name = self.names.get(0).unwrap_or(&invocation.name); @@ -252,7 +252,7 @@ impl Verb { ExecutionStringBuilder::with_invocation( &self.invocation_parser, sel_info, - other_path, + app_state, &invocation.args, ) }; |