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 | |
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')
-rw-r--r-- | src/commands/help.rs | 2 | ||||
-rw-r--r-- | src/context/app_context.rs | 89 | ||||
-rw-r--r-- | src/run.rs | 53 |
3 files changed, 92 insertions, 52 deletions
diff --git a/src/commands/help.rs b/src/commands/help.rs index a30235f..d47a0f4 100644 --- a/src/commands/help.rs +++ b/src/commands/help.rs @@ -27,6 +27,8 @@ pub fn help_loop( } else { widgets::get_keymap_table(keymap_t, &search_query[1..], sort_by) }; + + context.remove_external_preview(); backend.render(TuiHelp::new(&keymap, &mut offset, &search_query)); let event = match context.poll_event() { 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); @@ -8,12 +8,9 @@ use crate::tab::JoshutoTab; use crate::ui; use crate::ui::views; use crate::ui::views::TuiView; -use crate::ui::PreviewArea; use crate::util::input; use crate::util::to_string::ToString; -use std::process; -use std::thread; use termion::event::{Event, Key}; use tui::layout::Rect; @@ -36,8 +33,6 @@ pub fn run( preview_default::load_preview(context, backend); } - let mut preview_area: Option<PreviewArea> = None; - while context.quit == QuitType::DoNot { // do the ui if let Ok(area) = backend.terminal_ref().size() { @@ -48,7 +43,7 @@ pub fn run( backend.render(TuiView::new(context)); // invoke preview hooks, if appropriate - preview_area = process_preview_on_change(&context, preview_area); + context.update_external_preview(); } // wait for an event and pop it @@ -132,49 +127,3 @@ fn calculate_ui_context(context: &mut AppContext, area: Rect) { }; context.ui_context_mut().layout = layout; } - -fn process_preview_on_change( - context: &AppContext, - old_preview_area: Option<PreviewArea>, -) -> Option<PreviewArea> { - let config = context.config_ref(); - let preview_options = config.preview_options_ref(); - - let preview_shown_hook_script = preview_options.preview_shown_hook_script.as_ref(); - let preview_removed_hook_script = preview_options.preview_removed_hook_script.as_ref(); - let layout = &context.ui_context_ref().layout; - let new_preview_area = views::calculate_preview(&context, layout[2]); - match new_preview_area.as_ref() { - Some(new) => { - let should_preview = if let Some(old) = old_preview_area { - new.file_preview_path != old.file_preview_path - } else { - true - }; - if should_preview { - if let Some(hook_script) = preview_shown_hook_script { - let hook_script = hook_script.to_path_buf(); - let new2 = new.clone(); - let _ = thread::spawn(move || { - let _ = process::Command::new(hook_script.as_path()) - .arg(new2.file_preview_path.as_path()) - .arg(new2.preview_area.x.to_string()) - .arg(new2.preview_area.y.to_string()) - .arg(new2.preview_area.width.to_string()) - .arg(new2.preview_area.height.to_string()) - .status(); - }); - } - } - } - None => { - 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(); - }); - } - } - } - new_preview_area -} |