diff options
-rw-r--r-- | docs/configuration/joshuto.toml.md | 1 | ||||
-rw-r--r-- | src/commands/change_directory.rs | 3 | ||||
-rw-r--r-- | src/commands/cursor_move.rs | 20 | ||||
-rw-r--r-- | src/commands/parent_cursor_move.rs | 14 | ||||
-rw-r--r-- | src/commands/search_glob.rs | 4 | ||||
-rw-r--r-- | src/commands/search_string.rs | 4 | ||||
-rw-r--r-- | src/commands/subdir_fzf.rs | 4 | ||||
-rw-r--r-- | src/commands/tab_ops.rs | 6 | ||||
-rw-r--r-- | src/context/app_context.rs | 16 | ||||
-rw-r--r-- | src/fs/dirlist.rs | 82 | ||||
-rw-r--r-- | src/history.rs | 40 | ||||
-rw-r--r-- | src/preview/preview_default.rs | 2 | ||||
-rw-r--r-- | src/run.rs | 60 | ||||
-rw-r--r-- | src/tab.rs | 13 | ||||
-rw-r--r-- | src/ui/widgets/tui_dirlist.rs | 33 | ||||
-rw-r--r-- | src/ui/widgets/tui_dirlist_detailed.rs | 64 | ||||
-rw-r--r-- | src/ui/widgets/tui_footer.rs | 2 | ||||
-rw-r--r-- | src/util/input.rs | 3 |
18 files changed, 234 insertions, 137 deletions
diff --git a/docs/configuration/joshuto.toml.md b/docs/configuration/joshuto.toml.md index eeacf58..a1171be 100644 --- a/docs/configuration/joshuto.toml.md +++ b/docs/configuration/joshuto.toml.md @@ -4,7 +4,6 @@ This file is for general configurations. All options available and their default values: ```toml # This is for configuring how many items to reach before 'scrolling' the view -# CURRENTLY DOES NOT WORK scroll_offset = 6 # If joshuto does not know how to open the file, it can resort to opening it via xdg settings diff --git a/src/commands/change_directory.rs b/src/commands/change_directory.rs index 7b89726..6a39337 100644 --- a/src/commands/change_directory.rs +++ b/src/commands/change_directory.rs @@ -13,11 +13,12 @@ pub fn cd(path: &path::Path, context: &mut AppContext) -> std::io::Result<()> { fn change_directory_helper(path: &path::Path, context: &mut AppContext) -> std::io::Result<()> { cd(path, context)?; let options = context.config_ref().display_options_ref().clone(); + let ui_context = context.ui_context_ref().clone(); context .tab_context_mut() .curr_tab_mut() .history_mut() - .populate_to_root(path, &options)?; + .populate_to_root(path, &ui_context, &options)?; Ok(()) } diff --git a/src/commands/cursor_move.rs b/src/commands/cursor_move.rs index def90b2..5d9430f 100644 --- a/src/commands/cursor_move.rs +++ b/src/commands/cursor_move.rs @@ -41,20 +41,24 @@ pub fn lazy_load_directory_size(context: &mut AppContext) { pub fn cursor_move(context: &mut AppContext, new_index: usize) { lazy_load_directory_size(context); let mut new_index = new_index; + let ui_context = context.ui_context_ref().clone(); + let display_options = context.config_ref().display_options_ref().clone(); if let Some(curr_list) = context.tab_context_mut().curr_tab_mut().curr_list_mut() { if !curr_list.is_empty() { let dir_len = curr_list.len(); if new_index >= dir_len { new_index = dir_len - 1; } - curr_list.index = Some(new_index); + curr_list.set_index(Some(new_index), &ui_context, &display_options); } } } pub fn up(context: &mut AppContext, u: usize) -> JoshutoResult<()> { let movement = match context.tab_context_ref().curr_tab_ref().curr_list_ref() { - Some(curr_list) => curr_list.index.map(|idx| if idx > u { idx - u } else { 0 }), + Some(curr_list) => curr_list + .get_index() + .map(|idx| if idx > u { idx - u } else { 0 }), None => None, }; @@ -66,7 +70,7 @@ pub fn up(context: &mut AppContext, u: usize) -> JoshutoResult<()> { pub fn down(context: &mut AppContext, u: usize) -> JoshutoResult<()> { let movement = match context.tab_context_ref().curr_tab_ref().curr_list_ref() { - Some(curr_list) => curr_list.index.map(|idx| idx + u), + Some(curr_list) => curr_list.get_index().map(|idx| idx + u), None => None, }; if let Some(s) = movement { @@ -135,9 +139,11 @@ pub fn page_up(context: &mut AppContext, backend: &mut TuiBackend) -> JoshutoRes let page_size = get_page_size(context, backend).unwrap_or(10); let movement = match context.tab_context_ref().curr_tab_ref().curr_list_ref() { - Some(curr_list) => curr_list - .index - .map(|idx| if idx > page_size { idx - page_size } else { 0 }), + Some(curr_list) => { + curr_list + .get_index() + .map(|idx| if idx > page_size { idx - page_size } else { 0 }) + } None => None, }; @@ -153,7 +159,7 @@ pub fn page_down(context: &mut AppContext, backend: &mut TuiBackend) -> JoshutoR let movement = match context.tab_context_ref().curr_tab_ref().curr_list_ref() { Some(curr_list) => { let dir_len = curr_list.len(); - curr_list.index.map(|idx| { + curr_list.get_index().map(|idx| { if idx + page_size > dir_len - 1 { dir_len - 1 } else { diff --git a/src/commands/parent_cursor_move.rs b/src/commands/parent_cursor_move.rs index d1247d1..3bab3d3 100644 --- a/src/commands/parent_cursor_move.rs +++ b/src/commands/parent_cursor_move.rs @@ -8,17 +8,19 @@ pub fn parent_cursor_move(context: &mut AppContext, new_index: usize) -> Joshuto let mut new_index = new_index; { + let ui_context = context.ui_context_ref().clone(); + let display_options = context.config_ref().display_options_ref().clone(); let curr_tab = context.tab_context_mut().curr_tab_mut(); if let Some(curr_list) = curr_tab.parent_list_mut() { - if curr_list.index.is_some() { + if curr_list.get_index().is_some() { let dir_len = curr_list.contents.len(); if new_index >= dir_len { new_index = dir_len - 1; } let entry = &curr_list.contents[new_index]; if entry.file_path().is_dir() { - curr_list.index = Some(new_index); - path = Some(entry.file_path().to_path_buf()) + path = Some(entry.file_path().to_path_buf()); + curr_list.set_index(Some(new_index), &ui_context, &display_options); } } } @@ -31,7 +33,9 @@ pub fn parent_cursor_move(context: &mut AppContext, new_index: usize) -> Joshuto pub fn parent_up(context: &mut AppContext, u: usize) -> JoshutoResult<()> { let movement = match context.tab_context_ref().curr_tab_ref().parent_list_ref() { - Some(list) => list.index.map(|idx| if idx > u { idx - u } else { 0 }), + Some(list) => list + .get_index() + .map(|idx| if idx > u { idx - u } else { 0 }), None => None, }; @@ -44,7 +48,7 @@ pub fn parent_up(context: &mut AppContext, u: usize) -> JoshutoResult<()> { pub fn parent_down(context: &mut AppContext, u: usize) -> JoshutoResult<()> { let movement = match context.tab_context_ref().curr_tab_ref().parent_list_ref() { - Some(list) => list.index.map(|idx| idx + u), + Some(list) => list.get_index().map(|idx| idx + u), None => None, }; if let Some(s) = movement { diff --git a/src/commands/search_glob.rs b/src/commands/search_glob.rs index a6ca267..c761523 100644 --- a/src/commands/search_glob.rs +++ b/src/commands/search_glob.rs @@ -10,7 +10,7 @@ use super::cursor_move; pub fn search_glob_fwd(curr_tab: &JoshutoTab, glob: &GlobMatcher) -> Option<usize> { let curr_list = curr_tab.curr_list_ref()?; - let offset = curr_list.index? + 1; + let offset = curr_list.get_index()? + 1; let contents_len = curr_list.len(); for i in 0..contents_len { let file_name = curr_list.contents[(offset + i) % contents_len].file_name(); @@ -23,7 +23,7 @@ pub fn search_glob_fwd(curr_tab: &JoshutoTab, glob: &GlobMatcher) -> Option<usiz pub fn search_glob_rev(curr_tab: &JoshutoTab, glob: &GlobMatcher) -> Option<usize> { let curr_list = curr_tab.curr_list_ref()?; - let offset = curr_list.index?; + let offset = curr_list.get_index()?; let contents_len = curr_list.len(); for i in (0..contents_len).rev() { let file_name = curr_list.contents[(offset + i) % contents_len].file_name(); diff --git a/src/commands/search_string.rs b/src/commands/search_string.rs index b5ea94a..62d9a7f 100644 --- a/src/commands/search_string.rs +++ b/src/commands/search_string.rs @@ -8,7 +8,7 @@ use super::cursor_move; pub fn search_string_fwd(curr_tab: &JoshutoTab, pattern: &str) -> Option<usize> { let curr_list = curr_tab.curr_list_ref()?; - let offset = curr_list.index? + 1; + let offset = curr_list.get_index()? + 1; let contents_len = curr_list.contents.len(); for i in 0..contents_len { let file_name_lower = curr_list.contents[(offset + i) % contents_len] @@ -23,7 +23,7 @@ pub fn search_string_fwd(curr_tab: &JoshutoTab, pattern: &str) -> Option<usize> pub fn search_string_rev(curr_tab: &JoshutoTab, pattern: &str) -> Option<usize> { let curr_list = curr_tab.curr_list_ref()?; - let offset = curr_list.index?; + let offset = curr_list.get_index()?; let contents_len = curr_list.contents.len(); for i in (0..contents_len).rev() { let file_name_lower = curr_list.contents[(offset + i) % contents_len] diff --git a/src/commands/subdir_fzf.rs b/src/commands/subdir_fzf.rs index 74c86f2..51de88f 100644 --- a/src/commands/subdir_fzf.rs +++ b/src/commands/subdir_fzf.rs @@ -80,8 +80,10 @@ pub fn fzf_change_dir(context: &mut AppContext, path: &Path) -> JoshutoResult<() }; if let Some(index) = index { + let ui_context = context.ui_context_ref().clone(); + let display_options = context.config_ref().display_options_ref().clone(); if let Some(curr_list) = context.tab_context_mut().curr_tab_mut().curr_list_mut() { - curr_list.index = Some(index); + curr_list.set_index(Some(index), &ui_context, &display_options); } } } diff --git a/src/commands/tab_ops.rs b/src/commands/tab_ops.rs index 0d6ff82..dd27998 100644 --- a/src/commands/tab_ops.rs +++ b/src/commands/tab_ops.rs @@ -96,7 +96,11 @@ pub fn new_tab_home_path(context: &AppContext) -> path::PathBuf { pub fn new_tab(context: &mut AppContext) -> JoshutoResult<()> { let new_tab_path = new_tab_home_path(context); - let tab = JoshutoTab::new(new_tab_path, context.config_ref().display_options_ref())?; + let tab = JoshutoTab::new( + new_tab_path, + context.ui_context_ref(), + context.config_ref().display_options_ref(), + )?; context.tab_context_mut().push_tab(tab); let new_index = context.tab_context_ref().len() - 1; context.tab_context_mut().index = new_index; diff --git a/src/context/app_context.rs b/src/context/app_context.rs index 30aafae..0bdcf28 100644 --- a/src/context/app_context.rs +++ b/src/context/app_context.rs @@ -1,5 +1,6 @@ use std::collections::HashSet; use std::sync::mpsc; +use tui::layout::Rect; use crate::config; use crate::context::{ @@ -20,6 +21,11 @@ pub enum QuitType { ChooseFiles, } +#[derive(Clone, Debug, PartialEq)] +pub struct UiContext { + pub layout: Vec<Rect>, +} + pub struct AppContext { pub quit: QuitType, // event loop querying @@ -42,6 +48,8 @@ pub struct AppContext { preview_context: PreviewContext, // context related to command line commandline_context: CommandLineContext, + // user interface context; data which is input to both, the UI rendering and the app state + ui_context: UiContext, // filesystem watcher to inform about changes in shown directories #[cfg(target_os = "linux")] watcher: notify::INotifyWatcher, @@ -81,6 +89,7 @@ impl AppContext { message_queue: MessageQueue::new(), worker_context: WorkerContext::new(event_tx), preview_context: PreviewContext::new(), + ui_context: UiContext { layout: vec![] }, commandline_context, config, watcher, @@ -172,6 +181,13 @@ impl AppContext { &mut self.preview_context } + pub fn ui_context_ref(&self) -> &UiContext { + &self.ui_context + } + pub fn ui_context_mut(&mut self) -> &mut UiContext { + &mut self.ui_context + } + pub fn worker_context_ref(&self) -> &WorkerContext { &self.worker_context } diff --git a/src/fs/dirlist.rs b/src/fs/dirlist.rs index 0c8d6d6..a2d4bb8 100644 --- a/src/fs/dirlist.rs +++ b/src/fs/dirlist.rs @@ -1,7 +1,9 @@ +use std::cmp; use std::path; use std::slice::{Iter, IterMut}; use crate::config::option::DisplayOption; +use crate::context::UiContext; use crate::fs::{JoshutoDirEntry, JoshutoMetadata}; use crate::history::read_directory; @@ -10,8 +12,10 @@ pub struct JoshutoDirList { path: path::PathBuf, pub contents: Vec<JoshutoDirEntry>, pub metadata: JoshutoMetadata, - pub index: Option<usize>, - pub viewport_index: usize, + /// The cursor position in this dir list + index: Option<usize>, + /// The index in this dir list to start with when rendering the list + viewport_index: usize, _need_update: bool, } @@ -20,6 +24,7 @@ impl JoshutoDirList { path: path::PathBuf, contents: Vec<JoshutoDirEntry>, index: Option<usize>, + viewport_index: usize, metadata: JoshutoMetadata, ) -> Self { Self { @@ -27,7 +32,7 @@ impl JoshutoDirList { contents, metadata, index, - viewport_index: 0, + viewport_index, _need_update: false, } } @@ -41,17 +46,6 @@ impl JoshutoDirList { let index = if contents.is_empty() { None } else { Some(0) }; - let viewport_index = match index { - None => 0, - Some(index) => { - if index < options.scroll_offset() { - 0 - } else { - index - options.scroll_offset() - } - } - }; - let metadata = JoshutoMetadata::from(&path)?; Ok(Self { @@ -60,10 +54,56 @@ impl JoshutoDirList { metadata, _need_update: false, index, - viewport_index, + viewport_index: if let Some(ix) = index { ix } else { 0 }, }) } + pub fn get_index(&self) -> Option<usize> { + self.index + } + + fn update_viewport(&mut self, ui_context: &UiContext, options: &DisplayOption) { + if let Some(ix) = self.index { + let height = ui_context.layout[0].height as usize; + + // get scroll buffer size, corrected in case of too small terminal + let scroll_offset = if height < 4 { + 0 + } else if options.scroll_offset() * 2 > height - 1 { + height / 2 - 1 + } else { + options.scroll_offset() + }; + + // calculate viewport + let viewport_end = self.viewport_index + height; + if (viewport_end as i16 - ix as i16 - 1) < scroll_offset as i16 { + // cursor too low + self.viewport_index = (ix + scroll_offset - height + 1) as usize; + } else if (ix as i16 - self.viewport_index as i16) < scroll_offset as i16 { + // cursor too high + self.viewport_index = cmp::max(ix as i16 - scroll_offset as i16, 0) as usize; + } + } else { + self.viewport_index = 0; + } + } + + pub fn set_index( + &mut self, + index: Option<usize>, + ui_context: &UiContext, + options: &DisplayOption, + ) { + if index == self.index { + return; + } + self.index = index; + if ui_context.layout.len() != 0 { + self.update_viewport(ui_context, options); + } + } + pub fn iter(&self) -> Iter<JoshutoDirEntry> { self.contents.iter() } @@ -138,15 +178,9 @@ impl JoshutoDirList { self.get_curr_mut_(self.index?) } - /// For a given number of entries, visible in a UI, this method returns the index of the entry - /// with which the UI should start to list the entries. - /// - /// This method assures that the cursor is always in the viewport of the UI. - pub fn first_index_for_viewport(&self, viewport_height: usize) -> usize { - match self.index { - Some(index) => index / viewport_height as usize * viewport_height as usize, - None => 0, - } + /// Returns the index of the first entry to be printed in a UI dir list + pub fn first_index_for_viewport(&self) -> usize { + self.viewport_index } fn get_curr_mut_(&mut self, index: usize) -> Option<&mut JoshutoDirEntry> { diff --git a/src/history.rs b/src/history.rs index e754705..391cb8d 100644 --- a/src/history.rs +++ b/src/history.rs @@ -4,10 +4,16 @@ use std::io; use std::path::{Path, PathBuf}; use crate::config::option::DisplayOption; +use crate::context::UiContext; use crate::fs::{JoshutoDirEntry, JoshutoDirList, JoshutoMetadata}; pub trait DirectoryHistory { - fn populate_to_root(&mut self, path: &Path, options: &DisplayOption) -> io::Result<()>; + fn populate_to_root( + &mut self, + path: &Path, + ui_context: &UiContext, + options: &DisplayOption, + ) -> io::Result<()>; fn create_or_soft_update(&mut self, path: &Path, options: &DisplayOption) -> io::Result<()>; fn create_or_reload(&mut self, path: &Path, options: &DisplayOption) -> io::Result<()>; fn reload(&mut self, path: &Path, options: &DisplayOption) -> io::Result<()>; @@ -19,7 +25,12 @@ pub trait DirectoryHistory { pub type JoshutoHistory = HashMap<PathBuf, JoshutoDirList>; impl DirectoryHistory for JoshutoHistory { - fn populate_to_root(&mut self, path: &Path, options: &DisplayOption) -> io::Result<()> { + fn populate_to_root( + &mut self, + path: &Path, + ui_context: &UiContext, + options: &DisplayOption, + ) -> io::Result<()> { let mut dirlists = Vec::new(); let mut prev: Option<&Path> = None; @@ -28,7 +39,7 @@ impl DirectoryHistory for JoshutoHistory { let mut new_dirlist = create_dirlist_with_history(self, curr, options)?; if let Some(ancestor) = prev.as_ref() { if let Some(i) = get_index_of_value(&new_dirlist.contents, ancestor) { - new_dirlist.index = Some(i); + new_dirlist.set_index(Some(i), &ui_context, &options); } } dirlists.push(new_dirlist); @@ -37,7 +48,7 @@ impl DirectoryHistory for JoshutoHistory { JoshutoDirList::from_path(curr.to_path_buf().clone(), options)?; if let Some(ancestor) = prev.as_ref() { if let Some(i) = get_index_of_value(&new_dirlist.contents, ancestor) { - new_dirlist.index = Some(i); + new_dirlist.set_index(Some(i), &ui_context, &options); } } dirlists.push(new_dirlist); @@ -127,7 +138,7 @@ pub fn create_dirlist_with_history( None } else { match history.get(path) { - Some(dirlist) => match dirlist.index { + Some(dirlist) => match dirlist.get_index() { Some(i) if i >= contents_len => Some(contents_len - 1), Some(i) => { let entry = &dirlist.contents[i]; @@ -143,9 +154,26 @@ pub fn create_dirlist_with_history( None => Some(0), } }; + let viewport_index: usize = if contents_len == 0 { + 0 + } else { + match history.get(path) { + Some(dirlist) => match dirlist.first_index_for_viewport() { + i if i >= contents_len => contents_len - 1, + i => i, + }, + None => 0, + } + }; let metadata = JoshutoMetadata::from(path)?; - let dirlist = JoshutoDirList::new(path.to_path_buf(), contents, index, metadata); + let dirlist = JoshutoDirList::new( + path.to_path_buf(), + contents, + index, + viewport_index, + metadata, + ); Ok(dirlist) } diff --git a/src/preview/preview_default.rs b/src/preview/preview_default.rs index bda1077..56947b6 100644 --- a/src/preview/preview_default.rs +++ b/src/preview/preview_default.rs @@ -44,7 +44,7 @@ pub fn load_preview(context: &mut AppContext, backend: &mut TuiBackend) { let curr_tab = context.tab_context_ref().curr_tab_ref(); match curr_tab.curr_list_ref() { Some(curr_list) => { - if let Some(index) = curr_list.index { + if let Some(index) = curr_list.get_index() { let entry = &curr_list.contents[index]; load_list.push((entry.file_path().to_path_buf(), entry.metadata.clone())); } @@ -12,7 +12,6 @@ use crate::ui::PreviewArea; use crate::util::input; use crate::util::to_string::ToString; -use std::path::{Path, PathBuf}; use std::process; use std::thread; use termion::event::{Event, Key}; @@ -26,7 +25,11 @@ pub fn run( let curr_path = std::env::current_dir()?; { // Initialize an initial tab - let tab = JoshutoTab::new(curr_path, context.config_ref().display_options_ref())?; + let tab = JoshutoTab::new( + curr_path, + context.ui_context_ref(), + context.config_ref().display_options_ref(), + )?; context.tab_context_mut().push_tab(tab); // trigger a preview of child @@ -36,27 +39,25 @@ pub fn run( let mut preview_area: Option<PreviewArea> = None; while context.quit == QuitType::DoNot { - backend.render(TuiView::new(context)); + // do the ui + if let Ok(area) = backend.terminal_ref().size() { + // pre-calculate some ui attributes + calculate_ui_context(context, area); - { - let config = context.config_ref(); - let preview_options = config.preview_options_ref(); - if let Ok(area) = backend.terminal_ref().size() { - preview_area = process_preview_on_change( - &context, - area, - preview_area, - preview_options.preview_shown_hook_script.as_ref(), - preview_options.preview_removed_hook_script.as_ref(), - ); - } + // render the ui + backend.render(TuiView::new(context)); + + // invoke preview hooks, if appropriate + preview_area = process_preview_on_change(&context, preview_area); } + // wait for an event and pop it let event = match context.poll_event() { Ok(event) => event, Err(_) => return Ok(()), // TODO }; + // handle the event match event { AppEvent::Termion(Event::Mouse(event)) => { input::process_mouse(event, context, backend, &keymap_t); @@ -106,34 +107,41 @@ pub fn run( } event => input::process_noninteractive(event, context), } + + // update the file system supervisor that watches for changes in the FS context.update_watcher(); - } + } // end of main loop Ok(()) } -fn process_preview_on_change( - context: &AppContext, - area: Rect, - old_preview_area: Option<PreviewArea>, - preview_shown_hook_script: Option<&PathBuf>, - preview_removed_hook_script: Option<&PathBuf>, -) -> Option<PreviewArea> { +fn calculate_ui_context(context: &mut AppContext, area: Rect) { let area = Rect { y: area.top() + 1, height: area.height - 2, ..area }; - - let constraints = views::get_constraints(&context); let config = context.config_ref(); let display_options = config.display_options_ref(); + let constraints = views::get_constraints(&context); let layout = if display_options.show_borders() { views::calculate_layout_with_borders(area, constraints) } else { views::calculate_layout(area, constraints) }; - let new_preview_area = views::calculate_preview(&context, layout[2]); + 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 { @@ -1,6 +1,7 @@ use std::path; use crate::config::option::DisplayOption; +use crate::context::UiContext; use crate::fs::JoshutoDirList; use crate::history::{DirectoryHistory, JoshutoHistory}; @@ -17,9 +18,13 @@ pub struct JoshutoTab { } impl JoshutoTab { - pub fn new(cwd: path::PathBuf, options: &DisplayOption) -> std::io::Result<Self> { + pub fn new( + cwd: path::PathBuf, + ui_context: &UiContext, + options: &DisplayOption, + ) -> std::io::Result<Self> { let mut history = JoshutoHistory::new(); - history.populate_to_root(cwd.as_path(), options)?; + history.populate_to_root(cwd.as_path(), ui_context, options)?; Ok(Self { _cwd: cwd, history }) } @@ -51,7 +56,7 @@ impl JoshutoTab { pub fn child_list_ref(&self) -> Option<&JoshutoDirList> { let curr_list = self.curr_list_ref()?; - let index = curr_list.index?; + let index = curr_list.get_index()?; let path = curr_list.contents[index].file_path(); self.history.get(path) } @@ -69,7 +74,7 @@ impl JoshutoTab { pub fn child_list_mut(&mut self) -> Option<&mut JoshutoDirList> { let child_path = { let curr_list = self.curr_list_ref()?; - let index = curr_list.index?; + let index = curr_list.get_index()?; curr_list.contents[index].file_path().to_path_buf() }; diff --git a/src/ui/widgets/tui_dirlist.rs b/src/ui/widgets/tui_dirlist.rs index 9a14e6a..946834b 100644 --- a/src/ui/widgets/tui_dirlist.rs +++ b/src/ui/widgets/tui_dirlist.rs @@ -32,8 +32,8 @@ impl<'a> Widget for TuiDirList<'a> { return; } - let curr_index = self.dirlist.index.unwrap(); - let skip_dist = self.dirlist.first_index_for_viewport(area.height as usize); + let curr_index = self.dirlist.get_index().unwrap(); + let skip_dist = self.dirlist.first_index_for_viewport(); let drawing_width = area.width as usize; @@ -43,26 +43,21 @@ impl<'a> Widget for TuiDirList<'a> { .enumerate() .take(area.height as usize) .for_each(|(i, entry)| { - let style = style::entry_style(entry); - print_entry(buf, entry, style, (x + 1, y + i as u16), drawing_width - 1); - }); - - // draw selected entry in a different style - let screen_index = curr_index % area.height as usize; + let ix = skip_dist + i; - let entry = self.dirlist.curr_entry_ref().unwrap(); - let style = style::entry_style(entry).add_modifier(Modifier::REVERSED); + let style = if ix == curr_index { + style::entry_style(entry).add_modifier(Modifier::REVERSED) + } else { + style::entry_style(entry) + }; - let space_fill = " ".repeat(drawing_width); - buf.set_string(x, y + screen_index as u16, space_fill.as_str(), style); + if ix == curr_index { + let space_fill = " ".repeat(drawing_width); + buf.set_string(x, y + i as u16, space_fill.as_str(), style); + } - print_entry( - buf, - entry, - style, - (x + 1, y + screen_index as u16), - drawing_width - 1, - ); + print_entry(buf, entry, style, (x + 1, y + i as u16), drawing_width - 1); + }); } } diff --git a/src/ui/widgets/tui_dirlist_detailed.rs b/src/ui/widgets/tui_dirlist_detailed.rs index 7cb0693..f5d07be 100644 --- a/src/ui/widgets/tui_dirlist_detailed.rs +++ b/src/ui/widgets/tui_dirlist_detailed.rs @@ -37,7 +37,7 @@ impl<'a> Widget for TuiDirListDetailed<'a> { let x = area.left(); let y = area.top(); - let curr_index = match self.dirlist.index { + let curr_index = match self.dirlist.get_index() { Some(i) => i, None => { let style = Style::default().bg(Color::Red).fg(Color::White); @@ -47,8 +47,7 @@ impl<'a> Widget for TuiDirListDetailed<'a> { }; let drawing_width = area.width as usize; - let skip_dist = self.dirlist.first_index_for_viewport(area.height as usize); - let screen_index = curr_index % area.height as usize; + let skip_dist = self.dirlist.first_index_for_viewport(); let line_num_style = self.display_options.line_nums(); // Length (In chars) of the last entry's index on current page. // Using this to align all elements @@ -64,20 +63,38 @@ impl<'a> Widget for TuiDirListDetailed<'a> { .enumerate() .take(area.height as usize) .for_each(|(i, entry)| { - let style = style::entry_style(entry); + let ix = skip_dist + i; - let line_number_string = match line_num_style { - LineNumberStyle::Absolute => { - format!("{:1$} ", skip_dist + i + 1, max_index_length) + let style = if ix == curr_index { + style::entry_style(entry).add_modifier(Modifier::REVERSED) + } else { + style::entry_style(entry) + }; + + let line_number_string = if ix == curr_index { + match line_num_style { + LineNumberStyle::None => "".to_string(), + _ => format!("{:<1$} ", curr_index + 1, max_index_length), + } + } else { + match line_num_style { + LineNumberStyle::Absolute => { + format!("{:1$} ", ix + 1, max_index_length) + |