Skip to content

Commit 53c6aba

Browse files
committed
add the ability to set file operation colors
Signed-off-by: Luterán Lajos <luteranlajos@protonmail.ch>
1 parent 386943c commit 53c6aba

File tree

9 files changed

+162
-54
lines changed

9 files changed

+162
-54
lines changed

config/theme.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,12 @@ fg = "light_yellow"
4747
bold = true
4848

4949
[mark]
50-
fg = "red"
51-
bold = true
50+
cut.fg = "red"
51+
cut.bold = true
52+
copy.fg = "rgb(235, 104, 65)" # orange
53+
copy.bold = true
54+
symlink.fg = "rgb(254, 132, 172)" # pink
55+
symlink.bold = true
5256

5357
[selection.prefix]
5458
prefix = " "

src/commands/file_ops.rs

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,45 +7,68 @@ use crate::fs::JoshutoDirList;
77
use crate::io::{FileOperation, FileOperationOptions, IoWorkerThread};
88

99
fn new_local_state(context: &mut AppContext, file_op: FileOperation) -> Option<()> {
10-
mark_entries(context);
1110
let list = context.tab_context_ref().curr_tab_ref().curr_list_ref()?;
12-
if list.iter().any(|entry| entry.is_marked()) {
13-
let selected = list.get_selected_paths();
14-
let mut local_state = LocalStateContext::new();
15-
local_state.set_paths(selected.into_iter());
16-
local_state.set_file_op(file_op);
17-
18-
context.set_local_state(local_state);
19-
Some(())
20-
} else {
21-
None
22-
}
11+
let selected = list.get_selected_paths();
12+
let mut local_state = LocalStateContext::new();
13+
local_state.set_paths(selected.into_iter());
14+
local_state.set_file_op(file_op);
15+
16+
context.set_local_state(local_state);
17+
Some(())
2318
}
2419

25-
fn mark_entries(context: &mut AppContext) {
20+
fn mark_entries(context: &mut AppContext, op: &str) {
2621
let tab = context.tab_context_mut().curr_tab_mut();
22+
2723
if let Some(curr_list) = tab.curr_list_mut() {
28-
if curr_list.selected_count() != 0 {
29-
curr_list.iter_mut().for_each(|entry| {
30-
if entry.is_permanent_selected() {
31-
entry.set_mark_selected(true);
24+
curr_list.iter_mut().for_each(|entry| {
25+
entry.set_mark_cut_selected(false);
26+
entry.set_mark_copy_selected(false);
27+
entry.set_mark_sym_selected(false);
28+
});
29+
30+
match curr_list.selected_count() {
31+
count if count != 0 => {
32+
curr_list.iter_mut().for_each(|entry| match op {
33+
"cut" if entry.is_permanent_selected() => entry.set_mark_cut_selected(true),
34+
"copy" if entry.is_permanent_selected() => entry.set_mark_copy_selected(true),
35+
"symlink" if entry.is_permanent_selected() => entry.set_mark_sym_selected(true),
36+
_ => {}
37+
});
38+
}
39+
_ => {
40+
if let Some(entry) = curr_list.curr_entry_mut() {
41+
match op {
42+
"cut" => entry.set_mark_cut_selected(true),
43+
"copy" => entry.set_mark_copy_selected(true),
44+
"symlink" => entry.set_mark_sym_selected(true),
45+
_ => {}
46+
}
3247
}
33-
})
34-
} else if let Some(entry) = curr_list.curr_entry_mut() {
35-
entry.set_mark_selected(true);
48+
}
3649
}
3750
}
3851
}
3952

4053
fn unmark_entries(curr_tab: &mut JoshutoDirList) {
4154
if curr_tab.selected_count() != 0 {
4255
curr_tab.iter_mut().for_each(|entry| {
43-
if entry.is_marked() {
44-
entry.set_mark_selected(false);
56+
if entry.is_marked_cut() {
57+
entry.set_mark_cut_selected(false)
58+
} else if entry.is_marked_copy() {
59+
entry.set_mark_copy_selected(false)
60+
} else if entry.is_marked_sym() {
61+
entry.set_mark_sym_selected(false)
4562
}
4663
})
4764
} else if let Some(entry) = curr_tab.curr_entry_mut() {
48-
entry.set_mark_selected(false);
65+
if entry.is_marked_cut() {
66+
entry.set_mark_cut_selected(false)
67+
} else if entry.is_marked_copy() {
68+
entry.set_mark_copy_selected(false)
69+
} else if entry.is_marked_sym() {
70+
entry.set_mark_sym_selected(false)
71+
}
4972
}
5073
}
5174

@@ -69,21 +92,25 @@ fn unmark_and_cancel_all(context: &mut AppContext) -> AppResult {
6992
}
7093

7194
pub fn cut(context: &mut AppContext) -> AppResult {
95+
mark_entries(context, "cut");
7296
new_local_state(context, FileOperation::Cut);
7397
Ok(())
7498
}
7599

76100
pub fn copy(context: &mut AppContext) -> AppResult {
101+
mark_entries(context, "copy");
77102
new_local_state(context, FileOperation::Copy);
78103
Ok(())
79104
}
80105

81106
pub fn symlink_absolute(context: &mut AppContext) -> AppResult {
107+
mark_entries(context, "symlink");
82108
new_local_state(context, FileOperation::Symlink { relative: false });
83109
Ok(())
84110
}
85111

86112
pub fn symlink_relative(context: &mut AppContext) -> AppResult {
113+
mark_entries(context, "symlink");
87114
new_local_state(context, FileOperation::Symlink { relative: true });
88115
Ok(())
89116
}

src/config/clean/theme/config.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub struct AppTheme {
1515
pub regular: AppStyle,
1616
pub selection: AppStyle,
1717
pub visual_mode_selection: AppStyle,
18-
pub mark: AppStyle,
18+
pub mark: HashMap<String, AppStyle>,
1919
pub directory: AppStyle,
2020
pub executable: AppStyle,
2121
pub link: AppStyle,
@@ -53,7 +53,14 @@ impl From<AppThemeRaw> for AppTheme {
5353
let tabs = raw.tabs;
5454
let selection = raw.selection.to_style_theme();
5555
let visual_mode_selection = raw.visual_mode_selection.to_style_theme();
56-
let mark = raw.mark.to_style_theme();
56+
let mark: HashMap<String, AppStyle> = raw
57+
.mark
58+
.iter()
59+
.map(|(k, v)| {
60+
let style = v.to_style_theme();
61+
(k.clone(), style)
62+
})
63+
.collect();
5764
let executable = raw.executable.to_style_theme();
5865
let regular = raw.regular.to_style_theme();
5966
let directory = raw.directory.to_style_theme();

src/config/raw/theme/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub struct AppThemeRaw {
1515
#[serde(default)]
1616
pub visual_mode_selection: AppStyleRaw,
1717
#[serde(default)]
18-
pub mark: AppStyleRaw,
18+
pub mark: HashMap<String, AppStyleRaw>,
1919
#[serde(default)]
2020
pub directory: AppStyleRaw,
2121
#[serde(default)]

src/fs/dirlist.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,14 @@ impl JoshutoDirList {
222222
self.contents.iter().filter(|e| e.is_selected()).count()
223223
}
224224

225-
pub fn marked_count(&self) -> usize {
226-
self.contents.iter().filter(|e| e.is_marked()).count()
225+
pub fn marked_cut_count(&self) -> usize {
226+
self.contents.iter().filter(|e| e.is_marked_cut()).count()
227+
}
228+
pub fn marked_copy_count(&self) -> usize {
229+
self.contents.iter().filter(|e| e.is_marked_copy()).count()
230+
}
231+
pub fn marked_sym_count(&self) -> usize {
232+
self.contents.iter().filter(|e| e.is_marked_sym()).count()
227233
}
228234

229235
pub fn iter_selected(&self) -> impl Iterator<Item = &JoshutoDirEntry> {

src/fs/entry.rs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ pub struct JoshutoDirEntry {
1919
/// Temporarily selected by the visual mode range
2020
visual_mode_selected: bool,
2121
/// Marked for file ops
22-
marked: bool,
22+
marked_cut: bool,
23+
marked_copy: bool,
24+
marked_sym: bool,
2325
}
2426

2527
impl JoshutoDirEntry {
@@ -62,7 +64,9 @@ impl JoshutoDirEntry {
6264
metadata,
6365
permanent_selected: false,
6466
visual_mode_selected: false,
65-
marked: false,
67+
marked_cut: false,
68+
marked_copy: false,
69+
marked_sym: false,
6670
})
6771
}
6872

@@ -83,7 +87,11 @@ impl JoshutoDirEntry {
8387
}
8488

8589
pub fn is_selected(&self) -> bool {
86-
self.permanent_selected || self.visual_mode_selected || self.marked
90+
self.permanent_selected
91+
|| self.visual_mode_selected
92+
|| self.marked_cut
93+
|| self.marked_copy
94+
|| self.marked_sym
8795
}
8896

8997
pub fn is_permanent_selected(&self) -> bool {
@@ -94,8 +102,14 @@ impl JoshutoDirEntry {
94102
self.visual_mode_selected
95103
}
96104

97-
pub fn is_marked(&self) -> bool {
98-
self.marked
105+
pub fn is_marked_cut(&self) -> bool {
106+
self.marked_cut
107+
}
108+
pub fn is_marked_copy(&self) -> bool {
109+
self.marked_copy
110+
}
111+
pub fn is_marked_sym(&self) -> bool {
112+
self.marked_sym
99113
}
100114

101115
pub fn set_permanent_selected(&mut self, selected: bool) {
@@ -106,8 +120,14 @@ impl JoshutoDirEntry {
106120
self.visual_mode_selected = visual_mode_selected;
107121
}
108122

109-
pub fn set_mark_selected(&mut self, mark_selected: bool) {
110-
self.marked = mark_selected;
123+
pub fn set_mark_cut_selected(&mut self, mark_selected: bool) {
124+
self.marked_cut = mark_selected;
125+
}
126+
pub fn set_mark_copy_selected(&mut self, mark_selected: bool) {
127+
self.marked_copy = mark_selected;
128+
}
129+
pub fn set_mark_sym_selected(&mut self, mark_selected: bool) {
130+
self.marked_sym = mark_selected;
111131
}
112132

113133
pub fn get_ext(&self) -> &str {

src/history.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,15 @@ pub fn create_dirlist_with_history(
195195
for entry in contents.iter_mut() {
196196
if let Some(former_entry) = former_entries_by_file_name.get(entry.file_name()) {
197197
if preserve_selection {
198-
entry.set_mark_selected(former_entry.is_marked());
198+
entry.set_mark_cut_selected(former_entry.is_marked_cut());
199+
entry.set_mark_copy_selected(former_entry.is_marked_copy());
200+
entry.set_mark_sym_selected(former_entry.is_marked_sym());
199201
entry.set_permanent_selected(former_entry.is_permanent_selected());
200202
entry.set_visual_mode_selected(former_entry.is_visual_mode_selected());
201203
} else {
202-
entry.set_mark_selected(false);
204+
entry.set_mark_cut_selected(false);
205+
entry.set_mark_copy_selected(false);
206+
entry.set_mark_sym_selected(false);
203207
entry.set_permanent_selected(false);
204208
entry.set_visual_mode_selected(false);
205209
}

src/ui/widgets/tui_footer.rs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,13 @@ impl<'a> Widget for TuiFooter<'a> {
4141
.add_modifier(THEME_T.selection.modifier);
4242

4343
let selection_style = permanent_selected_style();
44-
let mark_style = mark_selected_style();
44+
let mark_cut_style = mark_selected_style("cut");
45+
let mark_copy_style = mark_selected_style("copy");
46+
let mark_sym_style = mark_selected_style("symlink");
4547
let selected_count = self.dirlist.selected_count();
46-
let marked_count = self.dirlist.marked_count();
48+
let marked_cut_count = self.dirlist.marked_cut_count();
49+
let marked_copy_count = self.dirlist.marked_copy_count();
50+
let marked_sym_count = self.dirlist.marked_sym_count();
4751

4852
match self.dirlist.get_index() {
4953
Some(i) if i < self.dirlist.len() => {
@@ -105,22 +109,48 @@ impl<'a> Widget for TuiFooter<'a> {
105109
if selected_count > 0 {
106110
format!("{} selected", selected_count)
107111
} else {
108-
" ".to_string()
112+
"".to_string()
109113
},
110114
selection_style,
111115
),
112-
Span::raw(if marked_count > 0 {
116+
Span::raw(if marked_cut_count > 0 {
113117
" | ".to_string()
114118
} else {
115119
"".to_string()
116120
}),
117121
Span::styled(
118-
if marked_count > 0 {
119-
format!("{} marked", marked_count)
122+
if marked_cut_count > 0 {
123+
format!("{} marked -> cut", marked_cut_count)
120124
} else {
121-
" ".to_string()
125+
"".to_string()
122126
},
123-
mark_style,
127+
mark_cut_style,
128+
),
129+
Span::raw(if marked_copy_count > 0 {
130+
" | ".to_string()
131+
} else {
132+
"".to_string()
133+
}),
134+
Span::styled(
135+
if marked_copy_count > 0 {
136+
format!("{} marked -> copy", marked_copy_count)
137+
} else {
138+
"".to_string()
139+
},
140+
mark_copy_style,
141+
),
142+
Span::raw(if marked_sym_count > 0 {
143+
" | ".to_string()
144+
} else {
145+
"".to_string()
146+
}),
147+
Span::styled(
148+
if marked_sym_count > 0 {
149+
format!("{} marked -> symlink", marked_sym_count)
150+
} else {
151+
"".to_string()
152+
},
153+
mark_sym_style,
124154
),
125155
];
126156

src/util/style.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,14 @@ pub fn entry_style(entry: &JoshutoDirEntry) -> Style {
3030
let filetype = metadata.file_type();
3131
let linktype = metadata.link_type();
3232

33-
if entry.is_marked() {
34-
return mark_selected_style();
33+
if entry.is_marked_cut() {
34+
return mark_selected_style("cut");
35+
}
36+
if entry.is_marked_copy() {
37+
return mark_selected_style("copy");
38+
}
39+
if entry.is_marked_sym() {
40+
return mark_selected_style("symlink");
3541
}
3642
if entry.is_permanent_selected() {
3743
return permanent_selected_style();
@@ -75,11 +81,15 @@ pub fn permanent_selected_style() -> Style {
7581
.add_modifier(THEME_T.selection.modifier)
7682
}
7783

78-
pub fn mark_selected_style() -> Style {
79-
Style::default()
80-
.fg(THEME_T.mark.fg)
81-
.bg(THEME_T.mark.bg)
82-
.add_modifier(THEME_T.mark.modifier)
84+
pub fn mark_selected_style(file_op: &str) -> Style {
85+
if let Some(mark) = THEME_T.mark.get(file_op) {
86+
Style::default()
87+
.fg(mark.fg)
88+
.bg(mark.bg)
89+
.add_modifier(mark.modifier)
90+
} else {
91+
Style::default()
92+
}
8393
}
8494

8595
pub fn symlink_valid_style() -> Style {

0 commit comments

Comments
 (0)