From 53c6aba4aa443bf491e6d22a1e1598c54d7c47bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luter=C3=A1n=20Lajos?= Date: Fri, 23 Feb 2024 13:37:09 +0100 Subject: [PATCH] add the ability to set file operation colors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: LuterĂ¡n Lajos --- config/theme.toml | 8 +++- src/commands/file_ops.rs | 73 ++++++++++++++++++++++---------- src/config/clean/theme/config.rs | 11 ++++- src/config/raw/theme/config.rs | 2 +- src/fs/dirlist.rs | 10 ++++- src/fs/entry.rs | 34 ++++++++++++--- src/history.rs | 8 +++- src/ui/widgets/tui_footer.rs | 46 ++++++++++++++++---- src/util/style.rs | 24 ++++++++--- 9 files changed, 162 insertions(+), 54 deletions(-) diff --git a/config/theme.toml b/config/theme.toml index eaa4eb846..e5ccc0389 100644 --- a/config/theme.toml +++ b/config/theme.toml @@ -47,8 +47,12 @@ fg = "light_yellow" bold = true [mark] -fg = "red" -bold = true +cut.fg = "red" +cut.bold = true +copy.fg = "rgb(235, 104, 65)" # orange +copy.bold = true +symlink.fg = "rgb(254, 132, 172)" # pink +symlink.bold = true [selection.prefix] prefix = " " diff --git a/src/commands/file_ops.rs b/src/commands/file_ops.rs index a97c2615d..f110d4d55 100644 --- a/src/commands/file_ops.rs +++ b/src/commands/file_ops.rs @@ -7,32 +7,45 @@ use crate::fs::JoshutoDirList; use crate::io::{FileOperation, FileOperationOptions, IoWorkerThread}; fn new_local_state(context: &mut AppContext, file_op: FileOperation) -> Option<()> { - mark_entries(context); let list = context.tab_context_ref().curr_tab_ref().curr_list_ref()?; - if list.iter().any(|entry| entry.is_marked()) { - let selected = list.get_selected_paths(); - let mut local_state = LocalStateContext::new(); - local_state.set_paths(selected.into_iter()); - local_state.set_file_op(file_op); - - context.set_local_state(local_state); - Some(()) - } else { - None - } + let selected = list.get_selected_paths(); + let mut local_state = LocalStateContext::new(); + local_state.set_paths(selected.into_iter()); + local_state.set_file_op(file_op); + + context.set_local_state(local_state); + Some(()) } -fn mark_entries(context: &mut AppContext) { +fn mark_entries(context: &mut AppContext, op: &str) { let tab = context.tab_context_mut().curr_tab_mut(); + if let Some(curr_list) = tab.curr_list_mut() { - if curr_list.selected_count() != 0 { - curr_list.iter_mut().for_each(|entry| { - if entry.is_permanent_selected() { - entry.set_mark_selected(true); + curr_list.iter_mut().for_each(|entry| { + entry.set_mark_cut_selected(false); + entry.set_mark_copy_selected(false); + entry.set_mark_sym_selected(false); + }); + + match curr_list.selected_count() { + count if count != 0 => { + curr_list.iter_mut().for_each(|entry| match op { + "cut" if entry.is_permanent_selected() => entry.set_mark_cut_selected(true), + "copy" if entry.is_permanent_selected() => entry.set_mark_copy_selected(true), + "symlink" if entry.is_permanent_selected() => entry.set_mark_sym_selected(true), + _ => {} + }); + } + _ => { + if let Some(entry) = curr_list.curr_entry_mut() { + match op { + "cut" => entry.set_mark_cut_selected(true), + "copy" => entry.set_mark_copy_selected(true), + "symlink" => entry.set_mark_sym_selected(true), + _ => {} + } } - }) - } else if let Some(entry) = curr_list.curr_entry_mut() { - entry.set_mark_selected(true); + } } } } @@ -40,12 +53,22 @@ fn mark_entries(context: &mut AppContext) { fn unmark_entries(curr_tab: &mut JoshutoDirList) { if curr_tab.selected_count() != 0 { curr_tab.iter_mut().for_each(|entry| { - if entry.is_marked() { - entry.set_mark_selected(false); + if entry.is_marked_cut() { + entry.set_mark_cut_selected(false) + } else if entry.is_marked_copy() { + entry.set_mark_copy_selected(false) + } else if entry.is_marked_sym() { + entry.set_mark_sym_selected(false) } }) } else if let Some(entry) = curr_tab.curr_entry_mut() { - entry.set_mark_selected(false); + if entry.is_marked_cut() { + entry.set_mark_cut_selected(false) + } else if entry.is_marked_copy() { + entry.set_mark_copy_selected(false) + } else if entry.is_marked_sym() { + entry.set_mark_sym_selected(false) + } } } @@ -69,21 +92,25 @@ fn unmark_and_cancel_all(context: &mut AppContext) -> AppResult { } pub fn cut(context: &mut AppContext) -> AppResult { + mark_entries(context, "cut"); new_local_state(context, FileOperation::Cut); Ok(()) } pub fn copy(context: &mut AppContext) -> AppResult { + mark_entries(context, "copy"); new_local_state(context, FileOperation::Copy); Ok(()) } pub fn symlink_absolute(context: &mut AppContext) -> AppResult { + mark_entries(context, "symlink"); new_local_state(context, FileOperation::Symlink { relative: false }); Ok(()) } pub fn symlink_relative(context: &mut AppContext) -> AppResult { + mark_entries(context, "symlink"); new_local_state(context, FileOperation::Symlink { relative: true }); Ok(()) } diff --git a/src/config/clean/theme/config.rs b/src/config/clean/theme/config.rs index 533be85fb..a08a3d9ec 100644 --- a/src/config/clean/theme/config.rs +++ b/src/config/clean/theme/config.rs @@ -15,7 +15,7 @@ pub struct AppTheme { pub regular: AppStyle, pub selection: AppStyle, pub visual_mode_selection: AppStyle, - pub mark: AppStyle, + pub mark: HashMap, pub directory: AppStyle, pub executable: AppStyle, pub link: AppStyle, @@ -53,7 +53,14 @@ impl From for AppTheme { let tabs = raw.tabs; let selection = raw.selection.to_style_theme(); let visual_mode_selection = raw.visual_mode_selection.to_style_theme(); - let mark = raw.mark.to_style_theme(); + let mark: HashMap = raw + .mark + .iter() + .map(|(k, v)| { + let style = v.to_style_theme(); + (k.clone(), style) + }) + .collect(); let executable = raw.executable.to_style_theme(); let regular = raw.regular.to_style_theme(); let directory = raw.directory.to_style_theme(); diff --git a/src/config/raw/theme/config.rs b/src/config/raw/theme/config.rs index 769f90ea6..43f4ffc4f 100644 --- a/src/config/raw/theme/config.rs +++ b/src/config/raw/theme/config.rs @@ -15,7 +15,7 @@ pub struct AppThemeRaw { #[serde(default)] pub visual_mode_selection: AppStyleRaw, #[serde(default)] - pub mark: AppStyleRaw, + pub mark: HashMap, #[serde(default)] pub directory: AppStyleRaw, #[serde(default)] diff --git a/src/fs/dirlist.rs b/src/fs/dirlist.rs index f32947707..98a17a53e 100644 --- a/src/fs/dirlist.rs +++ b/src/fs/dirlist.rs @@ -222,8 +222,14 @@ impl JoshutoDirList { self.contents.iter().filter(|e| e.is_selected()).count() } - pub fn marked_count(&self) -> usize { - self.contents.iter().filter(|e| e.is_marked()).count() + pub fn marked_cut_count(&self) -> usize { + self.contents.iter().filter(|e| e.is_marked_cut()).count() + } + pub fn marked_copy_count(&self) -> usize { + self.contents.iter().filter(|e| e.is_marked_copy()).count() + } + pub fn marked_sym_count(&self) -> usize { + self.contents.iter().filter(|e| e.is_marked_sym()).count() } pub fn iter_selected(&self) -> impl Iterator { diff --git a/src/fs/entry.rs b/src/fs/entry.rs index f83dc9efb..a6a5f898e 100644 --- a/src/fs/entry.rs +++ b/src/fs/entry.rs @@ -19,7 +19,9 @@ pub struct JoshutoDirEntry { /// Temporarily selected by the visual mode range visual_mode_selected: bool, /// Marked for file ops - marked: bool, + marked_cut: bool, + marked_copy: bool, + marked_sym: bool, } impl JoshutoDirEntry { @@ -62,7 +64,9 @@ impl JoshutoDirEntry { metadata, permanent_selected: false, visual_mode_selected: false, - marked: false, + marked_cut: false, + marked_copy: false, + marked_sym: false, }) } @@ -83,7 +87,11 @@ impl JoshutoDirEntry { } pub fn is_selected(&self) -> bool { - self.permanent_selected || self.visual_mode_selected || self.marked + self.permanent_selected + || self.visual_mode_selected + || self.marked_cut + || self.marked_copy + || self.marked_sym } pub fn is_permanent_selected(&self) -> bool { @@ -94,8 +102,14 @@ impl JoshutoDirEntry { self.visual_mode_selected } - pub fn is_marked(&self) -> bool { - self.marked + pub fn is_marked_cut(&self) -> bool { + self.marked_cut + } + pub fn is_marked_copy(&self) -> bool { + self.marked_copy + } + pub fn is_marked_sym(&self) -> bool { + self.marked_sym } pub fn set_permanent_selected(&mut self, selected: bool) { @@ -106,8 +120,14 @@ impl JoshutoDirEntry { self.visual_mode_selected = visual_mode_selected; } - pub fn set_mark_selected(&mut self, mark_selected: bool) { - self.marked = mark_selected; + pub fn set_mark_cut_selected(&mut self, mark_selected: bool) { + self.marked_cut = mark_selected; + } + pub fn set_mark_copy_selected(&mut self, mark_selected: bool) { + self.marked_copy = mark_selected; + } + pub fn set_mark_sym_selected(&mut self, mark_selected: bool) { + self.marked_sym = mark_selected; } pub fn get_ext(&self) -> &str { diff --git a/src/history.rs b/src/history.rs index bd362d084..20bf49463 100644 --- a/src/history.rs +++ b/src/history.rs @@ -195,11 +195,15 @@ pub fn create_dirlist_with_history( for entry in contents.iter_mut() { if let Some(former_entry) = former_entries_by_file_name.get(entry.file_name()) { if preserve_selection { - entry.set_mark_selected(former_entry.is_marked()); + entry.set_mark_cut_selected(former_entry.is_marked_cut()); + entry.set_mark_copy_selected(former_entry.is_marked_copy()); + entry.set_mark_sym_selected(former_entry.is_marked_sym()); entry.set_permanent_selected(former_entry.is_permanent_selected()); entry.set_visual_mode_selected(former_entry.is_visual_mode_selected()); } else { - entry.set_mark_selected(false); + entry.set_mark_cut_selected(false); + entry.set_mark_copy_selected(false); + entry.set_mark_sym_selected(false); entry.set_permanent_selected(false); entry.set_visual_mode_selected(false); } diff --git a/src/ui/widgets/tui_footer.rs b/src/ui/widgets/tui_footer.rs index c62786b8f..bdea9b4c3 100644 --- a/src/ui/widgets/tui_footer.rs +++ b/src/ui/widgets/tui_footer.rs @@ -41,9 +41,13 @@ impl<'a> Widget for TuiFooter<'a> { .add_modifier(THEME_T.selection.modifier); let selection_style = permanent_selected_style(); - let mark_style = mark_selected_style(); + let mark_cut_style = mark_selected_style("cut"); + let mark_copy_style = mark_selected_style("copy"); + let mark_sym_style = mark_selected_style("symlink"); let selected_count = self.dirlist.selected_count(); - let marked_count = self.dirlist.marked_count(); + let marked_cut_count = self.dirlist.marked_cut_count(); + let marked_copy_count = self.dirlist.marked_copy_count(); + let marked_sym_count = self.dirlist.marked_sym_count(); match self.dirlist.get_index() { Some(i) if i < self.dirlist.len() => { @@ -105,22 +109,48 @@ impl<'a> Widget for TuiFooter<'a> { if selected_count > 0 { format!("{} selected", selected_count) } else { - " ".to_string() + "".to_string() }, selection_style, ), - Span::raw(if marked_count > 0 { + Span::raw(if marked_cut_count > 0 { " | ".to_string() } else { "".to_string() }), Span::styled( - if marked_count > 0 { - format!("{} marked", marked_count) + if marked_cut_count > 0 { + format!("{} marked -> cut", marked_cut_count) } else { - " ".to_string() + "".to_string() }, - mark_style, + mark_cut_style, + ), + Span::raw(if marked_copy_count > 0 { + " | ".to_string() + } else { + "".to_string() + }), + Span::styled( + if marked_copy_count > 0 { + format!("{} marked -> copy", marked_copy_count) + } else { + "".to_string() + }, + mark_copy_style, + ), + Span::raw(if marked_sym_count > 0 { + " | ".to_string() + } else { + "".to_string() + }), + Span::styled( + if marked_sym_count > 0 { + format!("{} marked -> symlink", marked_sym_count) + } else { + "".to_string() + }, + mark_sym_style, ), ]; diff --git a/src/util/style.rs b/src/util/style.rs index add18fa46..f26a4802f 100644 --- a/src/util/style.rs +++ b/src/util/style.rs @@ -30,8 +30,14 @@ pub fn entry_style(entry: &JoshutoDirEntry) -> Style { let filetype = metadata.file_type(); let linktype = metadata.link_type(); - if entry.is_marked() { - return mark_selected_style(); + if entry.is_marked_cut() { + return mark_selected_style("cut"); + } + if entry.is_marked_copy() { + return mark_selected_style("copy"); + } + if entry.is_marked_sym() { + return mark_selected_style("symlink"); } if entry.is_permanent_selected() { return permanent_selected_style(); @@ -75,11 +81,15 @@ pub fn permanent_selected_style() -> Style { .add_modifier(THEME_T.selection.modifier) } -pub fn mark_selected_style() -> Style { - Style::default() - .fg(THEME_T.mark.fg) - .bg(THEME_T.mark.bg) - .add_modifier(THEME_T.mark.modifier) +pub fn mark_selected_style(file_op: &str) -> Style { + if let Some(mark) = THEME_T.mark.get(file_op) { + Style::default() + .fg(mark.fg) + .bg(mark.bg) + .add_modifier(mark.modifier) + } else { + Style::default() + } } pub fn symlink_valid_style() -> Style {