summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDLFW <daniel@llin.info>2022-01-14 02:18:51 +0100
committerGitHub <noreply@github.com>2022-01-13 20:18:51 -0500
commitc6e477cae753fe2ec3453a59e12fc2c5c95462a6 (patch)
tree531ee419a9d2f8971dd3d73869cd92858f22c027
parentfd06ae874291679b7ca0a1e8ac3611106b410840 (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
-rw-r--r--src/commands/help.rs2
-rw-r--r--src/context/app_context.rs89
-rw-r--r--src/run.rs53
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);
diff --git a/src/run.rs b/src/run.rs
index 2430e3b..c344814 100644
--- a/src/run.rs
+++ b/src/run.rs
@@ -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
-}