diff options
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/views/tui_folder_view.rs | 6 | ||||
-rw-r--r-- | src/ui/views/tui_hsplit_view.rs | 20 | ||||
-rw-r--r-- | src/ui/widgets/tui_dirlist.rs | 84 | ||||
-rw-r--r-- | src/ui/widgets/tui_dirlist_detailed.rs | 33 |
4 files changed, 122 insertions, 21 deletions
diff --git a/src/ui/views/tui_folder_view.rs b/src/ui/views/tui_folder_view.rs index 4f49ab1..8abcc26 100644 --- a/src/ui/views/tui_folder_view.rs +++ b/src/ui/views/tui_folder_view.rs @@ -143,14 +143,14 @@ impl<'a> Widget for TuiFolderView<'a> { Constraint::Ratio(0, _) => {} _ => { if let Some(list) = curr_tab.parent_list_ref().as_ref() { - TuiDirList::new(list, true).render(layout_rect[0], buf); + TuiDirList::new(config, list, true).render(layout_rect[0], buf); } } } // render current view if let Some(list) = curr_list.as_ref() { - TuiDirListDetailed::new(list, display_options, curr_tab.option_ref(), true) + TuiDirListDetailed::new(config, list, display_options, curr_tab.option_ref(), true) .render(layout_rect[1], buf); let footer_area = Self::footer_area(&area); @@ -185,7 +185,7 @@ impl<'a> Widget for TuiFolderView<'a> { } if let Some(list) = child_list.as_ref() { - TuiDirList::new(list, true).render(layout_rect[2], buf); + TuiDirList::new(config, list, true).render(layout_rect[2], buf); } else if let Some(entry) = curr_entry { match curr_tab.history_metadata_ref().get(entry.file_path()) { Some(PreviewDirState::Loading) => { diff --git a/src/ui/views/tui_hsplit_view.rs b/src/ui/views/tui_hsplit_view.rs index 6244e09..a28a4b9 100644 --- a/src/ui/views/tui_hsplit_view.rs +++ b/src/ui/views/tui_hsplit_view.rs @@ -76,8 +76,14 @@ impl<'a> Widget for TuiHSplitView<'a> { // render current view if let Some(list) = curr_list.as_ref() { - TuiDirListDetailed::new(list, display_options, curr_tab.option_ref(), true) - .render(layout_rect, buf); + TuiDirListDetailed::new( + self.context.config_ref(), + list, + display_options, + curr_tab.option_ref(), + true, + ) + .render(layout_rect, buf); let rect = Rect { x: 0, y: area.height - 1, @@ -132,8 +138,14 @@ impl<'a> Widget for TuiHSplitView<'a> { }; if let Some(list) = curr_list.as_ref() { - TuiDirListDetailed::new(list, display_options, curr_tab.option_ref(), false) - .render(layout_rect, buf); + TuiDirListDetailed::new( + self.context.config_ref(), + list, + display_options, + curr_tab.option_ref(), + false, + ) + .render(layout_rect, buf); } } } diff --git a/src/ui/widgets/tui_dirlist.rs b/src/ui/widgets/tui_dirlist.rs index 8d7b35e..3ee6917 100644 --- a/src/ui/widgets/tui_dirlist.rs +++ b/src/ui/widgets/tui_dirlist.rs @@ -4,18 +4,25 @@ use ratatui::style::{Color, Modifier, Style}; use ratatui::widgets::Widget; use unicode_width::UnicodeWidthStr; +use crate::config::clean::app::AppConfig; +use crate::fs::{FileType, JoshutoMetadata}; use crate::fs::{JoshutoDirEntry, JoshutoDirList}; use crate::ui::widgets::trim_file_label; use crate::util::style; pub struct TuiDirList<'a> { - dirlist: &'a JoshutoDirList, + pub config: &'a AppConfig, + pub dirlist: &'a JoshutoDirList, pub focused: bool, } impl<'a> TuiDirList<'a> { - pub fn new(dirlist: &'a JoshutoDirList, focused: bool) -> Self { - Self { dirlist, focused } + pub fn new(config: &'a AppConfig, dirlist: &'a JoshutoDirList, focused: bool) -> Self { + Self { + config, + dirlist, + focused, + } } } @@ -58,24 +65,83 @@ impl<'a> Widget for TuiDirList<'a> { buf.set_string(x, y + i as u16, space_fill.as_str(), style); - print_entry(buf, entry, style, (x + 1, y + i as u16), drawing_width - 1); + print_entry( + self.config, + buf, + entry, + style, + (x + 1, y + i as u16), + drawing_width - 1, + ); }); } } fn print_entry( + config: &AppConfig, buf: &mut Buffer, entry: &JoshutoDirEntry, style: Style, (x, y): (u16, u16), drawing_width: usize, ) { - let name = entry.label(); - let name_width = name.width(); - let label = if name_width > drawing_width { - trim_file_label(name, drawing_width) + let name = entry.file_name(); + #[cfg(feature = "devicons")] + let (label, label_width) = { + if config.display_options_ref().show_icons() { + let icon = get_entry_icon(&config, entry.file_name(), entry.ext(), &entry.metadata); + let label = format!("{icon} {name}"); + let label_width = label.width(); + (label, label_width) + } else { + (name.to_string(), name.width()) + } + }; + + #[cfg(not(feature = "devicons"))] + let (label, label_width) = { + let label = name.to_string(); + let label_width = label.width(); + (label, label_width) + }; + + let label = if label_width > drawing_width { + trim_file_label(&label, drawing_width) } else { - name.to_string() + label.to_string() }; buf.set_string(x, y, label, style); } + +#[cfg(feature = "devicons")] +pub fn get_entry_icon( + config: &AppConfig, + name: &str, + ext: Option<&str>, + metadata: &JoshutoMetadata, +) -> &'static str { + use crate::ICONS_T; + + if let FileType::Directory = metadata.file_type() { + return ICONS_T + .directory_exact + .get(name) + .map(|s| s.as_str()) + .unwrap_or(ICONS_T.default_dir.as_str()); + } + ICONS_T + .file_exact + .get(name) + .map(|s| s.as_str()) + .unwrap_or_else(|| { + ext.and_then(|ext| { + let ext: String = if config.case_sensitive_ext { + ext.to_owned() + } else { + ext.to_lowercase() + }; + ICONS_T.ext.get(&ext).map(|s| s.as_str()) + }) + .unwrap_or_else(|| ICONS_T.default_file.as_str()) + }) +} diff --git a/src/ui/widgets/tui_dirlist_detailed.rs b/src/ui/widgets/tui_dirlist_detailed.rs index b35dcea..0b203fe 100644 --- a/src/ui/widgets/tui_dirlist_detailed.rs +++ b/src/ui/widgets/tui_dirlist_detailed.rs @@ -9,30 +9,36 @@ use crate::config::clean::app::display::line_mode::LineMode; use crate::config::clean::app::display::line_number::LineNumberStyle; use crate::config::clean::app::display::tab::TabDisplayOption; use crate::config::clean::app::display::DisplayOption; +use crate::config::clean::app::AppConfig; use crate::fs::{FileType, JoshutoDirEntry, JoshutoDirList, LinkType}; use crate::util::string::UnicodeTruncate; use crate::util::style; use crate::util::{format, unix}; use unicode_width::UnicodeWidthStr; +use super::tui_dirlist::get_entry_icon; + const MIN_LEFT_LABEL_WIDTH: i32 = 15; const ELLIPSIS: &str = "…"; pub struct TuiDirListDetailed<'a> { - dirlist: &'a JoshutoDirList, - display_options: &'a DisplayOption, - tab_display_options: &'a TabDisplayOption, + pub config: &'a AppConfig, + pub dirlist: &'a JoshutoDirList, + pub display_options: &'a DisplayOption, + pub tab_display_options: &'a TabDisplayOption, pub focused: bool, } impl<'a> TuiDirListDetailed<'a> { pub fn new( + config: &'a AppConfig, dirlist: &'a JoshutoDirList, display_options: &'a DisplayOption, tab_display_options: &'a TabDisplayOption, focused: bool, ) -> Self { Self { + config, dirlist, display_options, tab_display_options, @@ -104,6 +110,7 @@ impl<'a> Widget for TuiDirListDetailed<'a> { prefix.push_str(&line_number_prefix); print_entry( + self.config, buf, entry, style, @@ -130,6 +137,7 @@ fn get_entry_size_string(entry: &JoshutoDirEntry) -> String { #[allow(clippy::too_many_arguments)] fn print_entry( + config: &AppConfig, buf: &mut Buffer, entry: &JoshutoDirEntry, style: Style, @@ -143,7 +151,22 @@ fn print_entry( LinkType::Normal => "", LinkType::Symlink { .. } => "-> ", }; - let left_label_original = entry.label(); + + let name = entry.file_name(); + #[cfg(feature = "devicons")] + let label = { + if config.display_options_ref().show_icons() { + let icon = get_entry_icon(&config, entry.file_name(), entry.ext(), &entry.metadata); + format!("{icon} {name}") + } else { + name.to_string() + } + }; + + #[cfg(not(feature = "devicons"))] + let label = name.to_string(); + + let left_label_original = label; let right_label_original = format!( " {}{} ", symlink_string, @@ -168,7 +191,7 @@ fn print_entry( // factor left_label and right_label let drawing_width = drawing_width - prefix_width; let (left_label, right_label) = factor_labels_for_entry( - left_label_original, + &left_label_original, right_label_original.as_str(), drawing_width, ); |