summaryrefslogtreecommitdiffstats
path: root/src/preview
diff options
context:
space:
mode:
authorJeff Zhao <jeff.no.zhao@gmail.com>2021-06-22 22:34:42 -0400
committerJeff Zhao <jeff.no.zhao@gmail.com>2021-06-22 22:34:42 -0400
commita11ed197df4fc3830387931c684346975333baf3 (patch)
treec11b81c58ff0ac52415684e1e383ebac92b94696 /src/preview
parent72aaf0c5d10db0004d48e27c58d18d8f2c568f8f (diff)
rudimentary file preview support
- this currently has only been tested with text files - no line formatting is done yet - only prints the preview as a single line - folder previews can now be pushed onto a separate thread if needed
Diffstat (limited to 'src/preview')
-rw-r--r--src/preview/preview_default.rs2
-rw-r--r--src/preview/preview_dir.rs60
-rw-r--r--src/preview/preview_file.rs190
3 files changed, 155 insertions, 97 deletions
diff --git a/src/preview/preview_default.rs b/src/preview/preview_default.rs
index 9601800..691cf72 100644
--- a/src/preview/preview_default.rs
+++ b/src/preview/preview_default.rs
@@ -8,7 +8,7 @@ pub fn load_preview_path(context: &mut AppContext, backend: &mut TuiBackend, p:
if p.is_dir() {
preview_dir::load_preview(context, p);
} else if p.is_file() {
- preview_file::preview_path_with_script(context, backend, p);
+ preview_file::Background::preview_path_with_script(context, backend, p);
}
}
diff --git a/src/preview/preview_dir.rs b/src/preview/preview_dir.rs
index bf1d151..03ae189 100644
--- a/src/preview/preview_dir.rs
+++ b/src/preview/preview_dir.rs
@@ -4,45 +4,47 @@ use std::thread;
use crate::context::AppContext;
use crate::event::AppEvent;
+use crate::fs::JoshutoDirList;
use crate::history::DirectoryHistory;
-pub fn load_preview(context: &mut AppContext, p: path::PathBuf) -> io::Result<path::PathBuf> {
- // get preview
+pub fn load_preview(context: &mut AppContext, p: path::PathBuf) -> io::Result<()> {
let options = context.config_ref().display_options_ref().clone();
context
.tab_context_mut()
.curr_tab_mut()
.history_mut()
.create_or_soft_update(p.as_path(), &options)?;
- Ok(p)
+ Ok(())
}
-pub struct CursorDir {}
-
-impl CursorDir {
- pub fn load(context: &mut AppContext) -> io::Result<()> {
- let mut p: Option<path::PathBuf> = None;
- if let Some(curr_list) = context.tab_context_ref().curr_tab_ref().curr_list_ref() {
- if let Some(index) = curr_list.index {
- let entry = &curr_list.contents[index];
- p = Some(entry.file_path().to_path_buf())
+pub fn background_load_preview(
+ context: &mut AppContext,
+ p: path::PathBuf,
+) -> thread::JoinHandle<()> {
+ let need_to_load = match context
+ .tab_context_mut()
+ .curr_tab_mut()
+ .history_mut()
+ .get(p.as_path())
+ {
+ Some(entry) => entry.need_update(),
+ None => true,
+ };
+ if need_to_load {
+ let event_tx = context.events.event_tx.clone();
+ let options = context.config_ref().display_options_ref().clone();
+ let handle = thread::spawn(move || {
+ match JoshutoDirList::new(p, &options) {
+ Ok(dirlist) => {
+ event_tx.send(AppEvent::PreviewDir(Ok(dirlist)));
+ }
+ Err(_) => {}
}
- }
-
- let res = match p {
- Some(p) if p.is_dir() => load_preview(context, p),
- Some(p) => Err(io::Error::new(
- io::ErrorKind::InvalidData,
- "Not a directory".to_string(),
- )),
- None => Err(io::Error::new(
- io::ErrorKind::NotFound,
- "No such file or directory".to_string(),
- )),
- };
- match res {
- Ok(_) => Ok(()),
- Err(e) => Err(e),
- }
+ ()
+ });
+ handle
+ } else {
+ let handle = thread::spawn(|| ());
+ handle
}
}
diff --git a/src/preview/preview_file.rs b/src/preview/preview_file.rs
index 5aabb13..1a2e5f9 100644
--- a/src/preview/preview_file.rs
+++ b/src/preview/preview_file.rs
@@ -1,86 +1,142 @@
use std::io;
use std::path;
use std::process::{Command, Output};
+use std::thread;
use tui::layout::{Constraint, Direction, Layout, Rect};
use tui::widgets::{Block, Borders};
use crate::context::AppContext;
-use crate::ui::TuiBackend;
-
-pub fn preview_path_with_script(
- context: &AppContext,
- backend: &mut TuiBackend,
- p: path::PathBuf,
-) -> io::Result<Output> {
- let preview_options = context.config_ref().preview_options_ref();
- let config = context.config_ref();
-
- match preview_options.preview_script.as_ref() {
- None => Err(io::Error::new(
- io::ErrorKind::Other,
- "No preview script specified",
- )),
- Some(script) => {
- let area = backend.terminal.as_ref().unwrap().size().unwrap();
+use crate::event::AppEvent;
+use crate::ui::{self, TuiBackend};
- let constraints: &[Constraint; 3] = &config.display_options_ref().default_layout;
-
- let layout_rect = if config.display_options_ref().show_borders() {
- let area = Rect {
- y: area.top() + 1,
- height: area.height - 2,
- ..area
- };
-
- let block = Block::default().borders(Borders::ALL);
- let inner = block.inner(area);
-
- let layout_rect = Layout::default()
- .direction(Direction::Horizontal)
- .constraints(constraints.as_ref())
- .split(inner);
-
- let block = Block::default().borders(Borders::LEFT);
- let inner3 = block.inner(layout_rect[2]);
- inner3
- } else {
- let layout_rect = Layout::default()
- .direction(Direction::Horizontal)
- .vertical_margin(1)
- .constraints(constraints.as_ref())
- .split(area);
- layout_rect[2]
- };
-
- let file_full_path = p.as_path();
- let preview_width = layout_rect.width;
- let preview_height = layout_rect.height;
- let image_cache = 0;
- let preview_image = if preview_options.preview_images { 1 } else { 0 };
+#[derive(Clone, Debug)]
+pub struct FilePreview {
+ pub _path: path::PathBuf,
+ pub status: std::process::ExitStatus,
+ pub output: String,
+}
+
+impl std::convert::From<(path::PathBuf, Output)> for FilePreview {
+ fn from((p, output): (path::PathBuf, Output)) -> Self {
+ let s = String::from_utf8_lossy(&output.stdout).to_string();
+ let status = output.status;
+ Self {
+ _path: p,
+ status,
+ output: s,
+ }
+ }
+}
+
+pub struct Foreground {}
+
+impl Foreground {
+ pub fn preview_path_with_script(
+ context: &AppContext,
+ backend: &mut TuiBackend,
+ p: path::PathBuf,
+ ) -> io::Result<Output> {
+ let preview_options = context.config_ref().preview_options_ref();
+ let config = context.config_ref();
+
+ match preview_options.preview_script.as_ref() {
+ None => Err(io::Error::new(
+ io::ErrorKind::Other,
+ "No preview script specified",
+ )),
+ Some(script) => {
+ let area = backend.terminal.as_ref().unwrap().size().unwrap();
+ let display_options = config.display_options_ref();
+ let constraints: &[Constraint; 3] = &display_options.default_layout;
+
+ let layout_rect = ui::build_layout(area, constraints, display_options)[2];
+
+ let file_full_path = p.as_path();
+ let preview_width = layout_rect.width;
+ let preview_height = layout_rect.height;
+ let image_cache = 0;
+ let preview_image = if preview_options.preview_images { 1 } else { 0 };
+
+ // spawn preview process
+ Command::new(script)
+ .arg(file_full_path)
+ .arg(preview_width.to_string())
+ .arg(preview_height.to_string())
+ .arg(image_cache.to_string())
+ .arg(preview_image.to_string())
+ .output()
+ }
+ }
+ }
+
+ pub fn preview_with_script(
+ context: &AppContext,
+ backend: &mut TuiBackend,
+ ) -> io::Result<Output> {
+ let curr_tab = context.tab_context_ref().curr_tab_ref();
+ let child_list = curr_tab.child_list_ref();
+
+ let preview_options = context.config_ref().preview_options_ref();
- // spawn preview process
- Command::new(script)
- .arg(file_full_path)
- .arg(preview_width.to_string())
- .arg(preview_height.to_string())
- .arg(image_cache.to_string())
- .arg(preview_image.to_string())
- .output()
+ let config = context.config_ref();
+
+ match child_list.and_then(|list| list.curr_entry_ref()) {
+ None => Err(io::Error::new(io::ErrorKind::Other, "No file to preview")),
+ Some(entry) => {
+ Self::preview_path_with_script(context, backend, entry.file_path().to_path_buf())
+ }
}
}
}
-pub fn preview_with_script(context: &AppContext, backend: &mut TuiBackend) -> io::Result<Output> {
- let curr_tab = context.tab_context_ref().curr_tab_ref();
- let child_list = curr_tab.child_list_ref();
+pub struct Background {}
+
+impl Background {
+ pub fn preview_path_with_script(
+ context: &AppContext,
+ backend: &mut TuiBackend,
+ p: path::PathBuf,
+ ) {
+ if let Some(preview) = context.preview_context_ref().get_preview(p.as_path()) {
+ return;
+ }
+
+ let preview_options = context.config_ref().preview_options_ref();
+ let config = context.config_ref();
- let preview_options = context.config_ref().preview_options_ref();
+ if let Some(script) = preview_options.preview_script.as_ref() {
+ let area = backend.terminal.as_ref().unwrap().size().unwrap();
+ let display_options = config.display_options_ref();
+ let constraints: &[Constraint; 3] = &display_options.default_layout;
+
+ let layout_rect = ui::build_layout(area, constraints, display_options)[2];
+
+ let preview_width = layout_rect.width;
+ let preview_height = layout_rect.height;
+ let image_cache = 0;
+ let preview_image = if preview_options.preview_images { 1 } else { 0 };
- let config = context.config_ref();
+ let script = script.clone();
+ let event_tx = context.clone_event_tx();
+ let thread = thread::spawn(move || {
+ let file_full_path = p.as_path();
- match child_list.and_then(|list| list.curr_entry_ref()) {
- None => Err(io::Error::new(io::ErrorKind::Other, "No file to preview")),
- Some(entry) => preview_path_with_script(context, backend, entry.file_path().to_path_buf()),
+ let res = Command::new(script)
+ .arg(file_full_path)
+ .arg(preview_width.to_string())
+ .arg(preview_height.to_string())
+ .arg(image_cache.to_string())
+ .arg(preview_image.to_string())
+ .output();
+ match res {
+ Ok(output) => {
+ let preview = FilePreview::from((p, output));
+ event_tx.send(AppEvent::PreviewFile(preview));
+ }
+ Err(_) => {}
+ }
+ });
+ }
}
}