diff options
author | DLFW <daniel@llin.info> | 2022-01-14 02:18:51 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-13 20:18:51 -0500 |
commit | c6e477cae753fe2ec3453a59e12fc2c5c95462a6 (patch) | |
tree | 531ee419a9d2f8971dd3d73869cd92858f22c027 /src/context | |
parent | fd06ae874291679b7ca0a1e8ac3611106b410840 (diff) |
Calling preview removed hook when help page shown (#125)
* Calling preview removed hook when help page shown
* Better function names and documentation
* syntax fix
Diffstat (limited to 'src/context')
-rw-r--r-- | src/context/app_context.rs | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/context/app_context.rs b/src/context/app_context.rs index 0bdcf28..57178ee 100644 --- a/src/context/app_context.rs +++ b/src/context/app_context.rs @@ -1,5 +1,7 @@ use std::collections::HashSet; +use std::process; use std::sync::mpsc; +use std::thread; use tui::layout::Rect; use crate::config; @@ -7,6 +9,8 @@ use crate::context::{ CommandLineContext, LocalStateContext, MessageQueue, PreviewContext, TabContext, WorkerContext, }; use crate::event::{AppEvent, Events}; +use crate::ui::views; +use crate::ui::PreviewArea; use crate::util::search::SearchPattern; use crate::Args; use notify::{RecursiveMode, Watcher}; @@ -59,6 +63,9 @@ pub struct AppContext { watcher: notify::NullWatcher, // list of watched paths; seems not to be possible to get them from a notify::Watcher watched_paths: HashSet<path::PathBuf>, + // the last preview area (or None if now preview shown) to check if a preview hook script needs + // to be called + preview_area: Option<PreviewArea>, } impl AppContext { @@ -94,9 +101,91 @@ impl AppContext { config, watcher, watched_paths, + preview_area: None, } } + /// Calls the "preview shown hook script" if it's configured. + /// + /// This method takes the current preview area as argument to check for both, the path of the + /// currently previewed file and the geometry of the preview area. + fn call_preview_shown_hook(&self, preview_area: PreviewArea) { + let preview_options = self.config_ref().preview_options_ref(); + let preview_shown_hook_script = preview_options.preview_shown_hook_script.as_ref(); + if let Some(hook_script) = preview_shown_hook_script { + let hook_script = hook_script.to_path_buf(); + let _ = thread::spawn(move || { + let _ = process::Command::new(hook_script.as_path()) + .arg(preview_area.file_preview_path.as_path()) + .arg(preview_area.preview_area.x.to_string()) + .arg(preview_area.preview_area.y.to_string()) + .arg(preview_area.preview_area.width.to_string()) + .arg(preview_area.preview_area.height.to_string()) + .status(); + }); + } + } + + /// Calls the "preview removed hook script" if it's configured. + fn call_preview_removed_hook(&self) { + let preview_options = self.config_ref().preview_options_ref(); + let preview_removed_hook_script = preview_options.preview_removed_hook_script.as_ref(); + if let Some(hook_script) = preview_removed_hook_script { + let hook_script = hook_script.to_path_buf(); + let _ = thread::spawn(|| { + let _ = process::Command::new(hook_script).status(); + }); + } + } + + /// Updates the external preview to the current preview in Joshuto. + /// + /// The function checks if the current preview content is the same as the preview content which + /// has been last communicated to an external preview logic with the preview hook scripts. + /// If the preview content has changed, one of the hook scripts is called. Either the "preview + /// shown hook", if a preview is shown in Joshuto, or the "preview removed hook", if Joshuto has + /// changed from an entry with preview to an entry without a preview. + /// + /// This function shall be called each time a change of Joshuto's preview can be expected. + /// (As of now, it's called in each cycle of the main loop.) + pub fn update_external_preview(&mut self) { + let layout = &self.ui_context_ref().layout; + let new_preview_area = views::calculate_preview(self, layout[2]); + match new_preview_area.as_ref() { + Some(new) => { + let should_preview = if let Some(old) = &self.preview_area { + new.file_preview_path != old.file_preview_path + } else { + true + }; + if should_preview { + self.call_preview_shown_hook(new.clone()) + } + } + None => self.call_preview_removed_hook(), + } + self.preview_area = new_preview_area + } + + /// Remove the external preview, if any is present. + /// + /// If the last preview hook script called was the "preview shown hook", this function will + /// call the "preview removed hook" to remove any external preview. + /// Otherwise it won't do anything. + /// + /// To restore the external preview, `update_external_preview` is called which will detect the + /// difference and call the "preview shown hook" again for the current preview (if any). + /// + /// This function can be called if an external preview shall be temporarily removed, for example + /// when entering the help screen. + pub fn remove_external_preview(&mut self) { + if let Some(_) = &self.preview_area { + self.call_preview_removed_hook(); + self.preview_area = None; + } + } + + /// Updates the file system supervision with the currently shown directories. pub fn update_watcher(&mut self) { // collect the paths that shall be watched... let mut new_paths_to_watch: HashSet<path::PathBuf> = HashSet::with_capacity(3); |