summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJeff Zhao <jeff.no.zhao@gmail.com>2021-11-27 18:35:36 -0500
committerJeff Zhao <jeff.no.zhao@gmail.com>2021-11-27 18:35:36 -0500
commit186e9a1f9efcb3832a2e3deff8243d8e9c4de6b2 (patch)
tree0057009a735bde5b169e8ff5bba998564d5bc605 /src
parent14ed540354eab0feb2f65b47a63f46e0ae34203b (diff)
add scrolling support to file preview
Diffstat (limited to 'src')
-rw-r--r--src/commands/mod.rs1
-rw-r--r--src/commands/preview_cursor_move.rs77
-rw-r--r--src/context/preview_context.rs6
-rw-r--r--src/key_command/command.rs3
-rw-r--r--src/key_command/constants.rs2
-rw-r--r--src/key_command/impl_appcommand.rs3
-rw-r--r--src/key_command/impl_appexecute.rs3
-rw-r--r--src/key_command/impl_comment.rs3
-rw-r--r--src/key_command/impl_from_str.rs22
-rw-r--r--src/preview/preview_default.rs2
-rw-r--r--src/preview/preview_file.rs7
-rw-r--r--src/ui/views/tui_folder_view.rs4
-rw-r--r--src/ui/widgets/tui_file_preview.rs7
13 files changed, 134 insertions, 6 deletions
diff --git a/src/commands/mod.rs b/src/commands/mod.rs
index 3e9cef1..866e5ed 100644
--- a/src/commands/mod.rs
+++ b/src/commands/mod.rs
@@ -9,6 +9,7 @@ pub mod new_directory;
pub mod open_file;
pub mod parent_cursor_move;
pub mod parent_directory;
+pub mod preview_cursor_move;
pub mod quit;
pub mod reload;
pub mod rename_file;
diff --git a/src/commands/preview_cursor_move.rs b/src/commands/preview_cursor_move.rs
new file mode 100644
index 0000000..6b30a14
--- /dev/null
+++ b/src/commands/preview_cursor_move.rs
@@ -0,0 +1,77 @@
+use std::path::PathBuf;
+
+use crate::context::AppContext;
+use crate::error::JoshutoResult;
+
+pub fn preview_cursor_move(context: &mut AppContext, new_index: usize) -> JoshutoResult<()> {
+ let file_path: Option<PathBuf> = {
+ let curr_tab = context.tab_context_ref().curr_tab_ref();
+ let curr_list = curr_tab.curr_list_ref();
+ let curr_entry = curr_list.and_then(|c| c.curr_entry_ref());
+ let file_path = curr_entry.map(|e| e.file_path().to_path_buf());
+ file_path
+ };
+
+ let preview_context = context.preview_context_mut();
+
+ if let Some(file_path) = file_path {
+ if let Some(Some(preview)) = preview_context.get_preview_mut(&file_path) {
+ preview.index = new_index;
+ }
+ }
+ Ok(())
+}
+
+pub fn preview_up(context: &mut AppContext, u: usize) -> JoshutoResult<()> {
+ let new_index = {
+ let curr_tab = context.tab_context_ref().curr_tab_ref();
+ let curr_list = curr_tab.curr_list_ref();
+ let curr_entry = curr_list.and_then(|c| c.curr_entry_ref());
+ let file_path = curr_entry.map(|e| e.file_path());
+
+ let preview_context = context.preview_context_ref();
+
+ if let Some(file_path) = file_path {
+ if let Some(Some(preview)) = preview_context.get_preview_ref(&file_path) {
+ if preview.index < u {
+ Some(0)
+ } else {
+ Some(preview.index - u)
+ }
+ } else {
+ None
+ }
+ } else {
+ None
+ }
+ };
+ if let Some(new_index) = new_index {
+ preview_cursor_move(context, new_index);
+ }
+ Ok(())
+}
+
+pub fn preview_down(context: &mut AppContext, u: usize) -> JoshutoResult<()> {
+ let new_index = {
+ let curr_tab = context.tab_context_ref().curr_tab_ref();
+ let curr_list = curr_tab.curr_list_ref();
+ let curr_entry = curr_list.and_then(|c| c.curr_entry_ref());
+ let file_path = curr_entry.map(|e| e.file_path());
+
+ let preview_context = context.preview_context_ref();
+
+ if let Some(file_path) = file_path {
+ if let Some(Some(preview)) = preview_context.get_preview_ref(&file_path) {
+ Some(preview.index + u)
+ } else {
+ None
+ }
+ } else {
+ None
+ }
+ };
+ if let Some(new_index) = new_index {
+ preview_cursor_move(context, new_index);
+ }
+ Ok(())
+}
diff --git a/src/context/preview_context.rs b/src/context/preview_context.rs
index 2483ec0..d08371c 100644
--- a/src/context/preview_context.rs
+++ b/src/context/preview_context.rs
@@ -18,10 +18,14 @@ impl PreviewContext {
self.previews.get(p).is_some()
}
- pub fn get_preview(&self, p: &path::Path) -> Option<&Option<FilePreview>> {
+ pub fn get_preview_ref(&self, p: &path::Path) -> Option<&Option<FilePreview>> {
self.previews.get(p)
}
+ pub fn get_preview_mut(&mut self, p: &path::Path) -> Option<&mut Option<FilePreview>> {
+ self.previews.get_mut(p)
+ }
+
pub fn insert_preview(&mut self, p: path::PathBuf, preview: Option<FilePreview>) {
self.previews.insert(p, preview);
}
diff --git a/src/key_command/command.rs b/src/key_command/command.rs
index 0c2df9b..1eddfd6 100644
--- a/src/key_command/command.rs
+++ b/src/key_command/command.rs
@@ -27,6 +27,9 @@ pub enum Command {
ParentCursorMoveUp(usize),
ParentCursorMoveDown(usize),
+ PreviewCursorMoveUp(usize),
+ PreviewCursorMoveDown(usize),
+
// ChildCursorMoveUp(usize),
// ChildCursorMoveDown(usize),
DeleteFiles,
diff --git a/src/key_command/constants.rs b/src/key_command/constants.rs
index 2738d47..fa92adf 100644
--- a/src/key_command/constants.rs
+++ b/src/key_command/constants.rs
@@ -24,6 +24,8 @@ pub const CMD_CURSOR_MOVE_PAGEUP: &str = "cursor_move_page_up";
pub const CMD_CURSOR_MOVE_PAGEDOWN: &str = "cursor_move_page_down";
pub const CMD_PARENT_CURSOR_MOVE_UP: &str = "parent_cursor_move_up";
pub const CMD_PARENT_CURSOR_MOVE_DOWN: &str = "parent_cursor_move_down";
+pub const CMD_PREVIEW_CURSOR_MOVE_UP: &str = "preview_cursor_move_up";
+pub const CMD_PREVIEW_CURSOR_MOVE_DOWN: &str = "preview_cursor_move_down";
pub const CMD_DELETE_FILES: &str = "delete_files";
pub const CMD_NEW_DIRECTORY: &str = "mkdir";
pub const CMD_OPEN_FILE: &str = "open";
diff --git a/src/key_command/impl_appcommand.rs b/src/key_command/impl_appcommand.rs
index 5080352..477196a 100644
--- a/src/key_command/impl_appcommand.rs
+++ b/src/key_command/impl_appcommand.rs
@@ -34,6 +34,9 @@ impl AppCommand for Command {
Self::ParentCursorMoveUp(_) => CMD_PARENT_CURSOR_MOVE_UP,
Self::ParentCursorMoveDown(_) => CMD_PARENT_CURSOR_MOVE_DOWN,
+ Self::PreviewCursorMoveUp(_) => CMD_PREVIEW_CURSOR_MOVE_UP,
+ Self::PreviewCursorMoveDown(_) => CMD_PREVIEW_CURSOR_MOVE_DOWN,
+
Self::DeleteFiles => CMD_DELETE_FILES,
Self::NewDirectory(_) => CMD_NEW_DIRECTORY,
Self::OpenFile => CMD_OPEN_FILE,
diff --git a/src/key_command/impl_appexecute.rs b/src/key_command/impl_appexecute.rs
index 7d1ba75..eb94647 100644
--- a/src/key_command/impl_appexecute.rs
+++ b/src/key_command/impl_appexecute.rs
@@ -44,6 +44,9 @@ impl AppExecute for Command {
Self::ParentCursorMoveUp(u) => parent_cursor_move::parent_up(context, *u),
Self::ParentCursorMoveDown(u) => parent_cursor_move::parent_down(context, *u),
+ Self::PreviewCursorMoveUp(u) => preview_cursor_move::preview_up(context, *u),
+ Self::PreviewCursorMoveDown(u) => preview_cursor_move::preview_down(context, *u),
+
Self::DeleteFiles => {
delete_files::delete_selected_files(context, backend)?;
Ok(())
diff --git a/src/key_command/impl_comment.rs b/src/key_command/impl_comment.rs
index 58b51c8..aea23fc 100644
--- a/src/key_command/impl_comment.rs
+++ b/src/key_command/impl_comment.rs
@@ -46,6 +46,9 @@ impl CommandComment for Command {
Self::ParentCursorMoveUp(_) => "Cursor up in parent list",
Self::ParentCursorMoveDown(_) => "Cursor down in parent list",
+ Self::PreviewCursorMoveUp(_) => "Cursor up in file preview",
+ Self::PreviewCursorMoveDown(_) => "Cursor down in file preview",
+
Self::DeleteFiles => "Delete selected files",
Self::NewDirectory(_) => "Make a new directory",
Self::OpenFile => "Open a file",
diff --git a/src/key_command/impl_from_str.rs b/src/key_command/impl_from_str.rs
index 75bb771..ec13bc8 100644
--- a/src/key_command/impl_from_str.rs
+++ b/src/key_command/impl_from_str.rs
@@ -141,6 +141,28 @@ impl std::str::FromStr for Command {
)),
},
}
+ } else if command == CMD_PREVIEW_CURSOR_MOVE_DOWN {
+ match arg {
+ "" => Ok(Self::PreviewCursorMoveDown(1)),
+ arg => match arg.trim().parse::<usize>() {
+ Ok(s) => Ok(Self::PreviewCursorMoveDown(s)),
+ Err(e) => Err(JoshutoError::new(
+ JoshutoErrorKind::ParseError,
+ e.to_string(),
+ )),
+ },
+ }
+ } else if command == CMD_PREVIEW_CURSOR_MOVE_UP {
+ match arg {
+ "" => Ok(Self::PreviewCursorMoveUp(1)),
+ arg => match arg.trim().parse::<usize>() {
+ Ok(s) => Ok(Self::PreviewCursorMoveUp(s)),
+ Err(e) => Err(JoshutoError::new(
+ JoshutoErrorKind::ParseError,
+ e.to_string(),
+ )),
+ },
+ }
} else if command == CMD_NEW_DIRECTORY {
if arg.is_empty() {
Err(JoshutoError::new(
diff --git a/src/preview/preview_default.rs b/src/preview/preview_default.rs
index 0c5142c..bda1077 100644
--- a/src/preview/preview_default.rs
+++ b/src/preview/preview_default.rs
@@ -28,7 +28,7 @@ pub fn load_preview_path(
} else if metadata.len() <= preview_options.max_preview_size {
let need_to_load = context
.preview_context_ref()
- .get_preview(p.as_path())
+ .get_preview_ref(p.as_path())
.is_none();
if need_to_load {
diff --git a/src/preview/preview_file.rs b/src/preview/preview_file.rs
index 6b23a4a..d4e08c5 100644
--- a/src/preview/preview_file.rs
+++ b/src/preview/preview_file.rs
@@ -19,6 +19,7 @@ pub enum PreviewState {
pub struct FilePreview {
pub status: std::process::ExitStatus,
pub output: String,
+ pub index: usize,
}
impl std::convert::From<Output> for FilePreview {
@@ -26,7 +27,11 @@ impl std::convert::From<Output> for FilePreview {
let s = String::from_utf8_lossy(&output.stdout).to_string();
let s2 = s.replace('\t', " ").to_string();
let status = output.status;
- Self { status, output: s2 }
+ Self {
+ status,
+ output: s2,
+ index: 0,
+ }
}
}
diff --git a/src/ui/views/tui_folder_view.rs b/src/ui/views/tui_folder_view.rs
index 398c3d8..944e1f5 100644
--- a/src/ui/views/tui_folder_view.rs
+++ b/src/ui/views/tui_folder_view.rs
@@ -48,7 +48,7 @@ impl<'a> Widget for TuiFolderView<'a> {
Some(_) => (true, &display_options.default_layout),
None => match curr_entry {
None => (false, &display_options.no_preview_layout),
- Some(e) => match preview_context.get_preview(e.file_path()) {
+ Some(e) => match preview_context.get_preview_ref(e.file_path()) {
Some(Some(p)) if p.status.code() != Some(1) => {
(true, &display_options.default_layout)
}
@@ -158,7 +158,7 @@ impl<'a> Widget for TuiFolderView<'a> {
if let Some(list) = child_list.as_ref() {
TuiDirList::new(list).render(layout_rect[2], buf);
} else if let Some(entry) = curr_entry {
- if let Some(Some(preview)) = preview_context.get_preview(entry.file_path()) {
+ if let Some(Some(preview)) = preview_context.get_preview_ref(entry.file_path()) {
match preview.status.code() {
Some(1) | None => {}
_ => {
diff --git a/src/ui/widgets/tui_file_preview.rs b/src/ui/widgets/tui_file_preview.rs
index 0a784cc..cc9e7bd 100644
--- a/src/ui/widgets/tui_file_preview.rs
+++ b/src/ui/widgets/tui_file_preview.rs
@@ -21,7 +21,12 @@ impl<'a> TuiFilePreview<'a> {
impl<'a> Widget for TuiFilePreview<'a> {
fn render(self, area: Rect, buf: &mut Buffer) {
let text: Text = ansi_to_text(self.preview.output.as_str().as_bytes().to_vec()).unwrap();
- for (y, line) in (area.y..area.y + area.height).zip(text.lines) {
+ for (line, y) in text
+ .lines
+ .iter()
+ .skip(self.preview.index)
+ .zip(area.y..area.y + area.height)
+ {
buf.set_spans(area.x, y, &line, area.width);
}
}