diff options
author | Jeff Zhao <jeff.no.zhao@gmail.com> | 2021-06-22 22:34:42 -0400 |
---|---|---|
committer | Jeff Zhao <jeff.no.zhao@gmail.com> | 2021-06-22 22:34:42 -0400 |
commit | a11ed197df4fc3830387931c684346975333baf3 (patch) | |
tree | c11b81c58ff0ac52415684e1e383ebac92b94696 /src/preview | |
parent | 72aaf0c5d10db0004d48e27c58d18d8f2c568f8f (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.rs | 2 | ||||
-rw-r--r-- | src/preview/preview_dir.rs | 60 | ||||
-rw-r--r-- | src/preview/preview_file.rs | 190 |
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(_) => {} + } + }); + } } } |