summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/views/tui_folder_view.rs6
-rw-r--r--src/ui/views/tui_hsplit_view.rs20
-rw-r--r--src/ui/widgets/tui_dirlist.rs84
-rw-r--r--src/ui/widgets/tui_dirlist_detailed.rs33
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,
);