Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8f3daee

Browse files
author
Sebastian Thiel
committed
EntryDataBundle with all data we need: next - don't query during draw
1 parent 7483ddb commit 8f3daee

4 files changed

Lines changed: 103 additions & 88 deletions

File tree

src/interactive/app/common.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use dua::path_of;
22
use dua::traverse::{EntryData, Tree, TreeIndex};
33
use itertools::Itertools;
44
use petgraph::Direction;
5-
use std::path::PathBuf;
65

76
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Eq)]
87
pub enum SortMode {
@@ -26,17 +25,30 @@ impl Default for SortMode {
2625
}
2726
}
2827

29-
pub type EntryDataBundle = (TreeIndex, EntryData, PathBuf);
28+
pub struct EntryDataBundle {
29+
pub index: TreeIndex,
30+
pub data: EntryData,
31+
pub is_dir: bool,
32+
pub exists: bool,
33+
}
34+
3035
pub fn sorted_entries(tree: &Tree, node_idx: TreeIndex, sorting: SortMode) -> Vec<EntryDataBundle> {
3136
use SortMode::*;
3237
tree.neighbors_directed(node_idx, Direction::Outgoing)
3338
.filter_map(|idx| {
34-
tree.node_weight(idx)
35-
.map(|w| (idx, w.clone(), path_of(tree, idx)))
39+
tree.node_weight(idx).map(|w| {
40+
let p = path_of(tree, idx);
41+
EntryDataBundle {
42+
index: idx,
43+
data: w.clone(),
44+
is_dir: p.is_dir(),
45+
exists: p.exists(),
46+
}
47+
})
3648
})
37-
.sorted_by(|(_, l, _), (_, r, _)| match sorting {
38-
SizeDescending => r.size.cmp(&l.size),
39-
SizeAscending => l.size.cmp(&r.size),
49+
.sorted_by(|l, r| match sorting {
50+
SizeDescending => r.data.size.cmp(&l.data.size),
51+
SizeAscending => l.data.size.cmp(&r.data.size),
4052
})
4153
.collect()
4254
}

src/interactive/app/eventloop.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ impl TerminalApp {
184184
self.state.root = parent_idx;
185185
self.state.entries =
186186
sorted_entries(&self.traversal.tree, parent_idx, self.state.sorting);
187-
self.state.selected = self.state.entries.get(0).map(|(idx, _, _)| *idx);
187+
self.state.selected = self.state.entries.get(0).map(|b| b.index);
188188
}
189189
None => self.state.message = Some("Top level reached".into()),
190190
}
@@ -194,9 +194,9 @@ impl TerminalApp {
194194
if let Some(new_root) = self.state.selected {
195195
self.state.entries = sorted_entries(&self.traversal.tree, new_root, self.state.sorting);
196196
match self.state.entries.get(0) {
197-
Some((next_selection, _, _)) => {
197+
Some(b) => {
198198
self.state.root = new_root;
199-
self.state.selected = Some(*next_selection);
199+
self.state.selected = Some(b.index);
200200
}
201201
None => self.state.message = Some("Entry is a file or an empty directory".into()),
202202
}
@@ -219,7 +219,7 @@ impl TerminalApp {
219219
let next_selected_pos = match self.state.selected {
220220
Some(ref selected) => entries
221221
.iter()
222-
.find_position(|(idx, _, _)| *idx == *selected)
222+
.find_position(|b| b.index == *selected)
223223
.map(|(idx, _)| match direction {
224224
CursorDirection::PageDown => idx.saturating_add(10),
225225
CursorDirection::Down => idx.saturating_add(1),
@@ -232,7 +232,7 @@ impl TerminalApp {
232232
self.state.selected = entries
233233
.get(next_selected_pos)
234234
.or(entries.last())
235-
.map(|(idx, _, _)| *idx)
235+
.map(|b| b.index)
236236
.or(self.state.selected)
237237
}
238238

@@ -270,7 +270,7 @@ impl TerminalApp {
270270
let sorting = Default::default();
271271
let root = traversal.root_index;
272272
let entries = sorted_entries(&traversal.tree, root, sorting);
273-
let selected = entries.get(0).map(|(idx, _, _)| *idx);
273+
let selected = entries.get(0).map(|b| b.index);
274274
display_options.byte_vis = ByteVisualization::PercentageAndBar;
275275
Ok(TerminalApp {
276276
state: AppState {

src/interactive/app_test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use crate::interactive::TerminalApp;
1+
use crate::interactive::{SortMode, TerminalApp};
22
use dua::{
33
traverse::{EntryData, Tree, TreeIndex},
4-
ByteFormat, Color, SortMode, TraversalSorting, WalkOptions,
4+
ByteFormat, Color, TraversalSorting, WalkOptions,
55
};
66
use failure::Error;
77
use petgraph::prelude::NodeIndex;

src/interactive/widgets/entries.rs

Lines changed: 76 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::interactive::{
22
sorted_entries,
33
widgets::{fill_background_to_right, List, ListState},
4-
DisplayOptions, SortMode,
4+
DisplayOptions, EntryDataBundle, SortMode,
55
};
66
use dua::traverse::{Tree, TreeIndex};
77
use itertools::Itertools;
@@ -44,7 +44,7 @@ impl<'a, 'b> Widget for Entries<'a, 'b> {
4444
let path_of = |node_idx| dua::path_of(tree, node_idx);
4545

4646
let entries = sorted_entries(tree, *root, *sorting);
47-
let total: u64 = entries.iter().map(|(_, w, _)| w.size).sum();
47+
let total: u64 = entries.iter().map(|b| b.data.size).sum();
4848
let title = match path_of(*root).to_string_lossy().to_string() {
4949
ref p if p.is_empty() => Path::new(".")
5050
.canonicalize()
@@ -62,7 +62,7 @@ impl<'a, 'b> Widget for Entries<'a, 'b> {
6262
selected.map(|selected| {
6363
entries
6464
.iter()
65-
.find_position(|(idx, _, _)| *idx == selected)
65+
.find_position(|b| b.index == selected)
6666
.map(|(idx, _)| idx)
6767
.unwrap_or(0)
6868
}),
@@ -72,81 +72,84 @@ impl<'a, 'b> Widget for Entries<'a, 'b> {
7272

7373
List {
7474
block: Some(block),
75-
items: entries.iter().skip(offset).map(|(node_idx, w, path)| {
76-
let (is_selected, style) = match selected {
77-
Some(idx) if *idx == *node_idx => (
78-
true,
79-
Style {
80-
fg: Color::Black,
81-
bg: if *is_focussed {
82-
Color::White
83-
} else {
84-
Color::DarkGray
75+
items: entries.iter().skip(offset).map(
76+
|EntryDataBundle {
77+
index: node_idx,
78+
data: w,
79+
is_dir,
80+
exists,
81+
}| {
82+
let (is_selected, style) = match selected {
83+
Some(idx) if *idx == *node_idx => (
84+
true,
85+
Style {
86+
fg: Color::Black,
87+
bg: if *is_focussed {
88+
Color::White
89+
} else {
90+
Color::DarkGray
91+
},
92+
..Default::default()
8593
},
86-
..Default::default()
87-
},
88-
),
89-
_ => (
90-
false,
91-
Style {
92-
fg: Color::White,
93-
bg: Color::Reset,
94-
..Default::default()
95-
},
96-
),
97-
};
94+
),
95+
_ => (
96+
false,
97+
Style {
98+
fg: Color::White,
99+
bg: Color::Reset,
100+
..Default::default()
101+
},
102+
),
103+
};
98104

99-
let bytes = Text::Styled(
100-
format!(
101-
"{:>byte_column_width$}",
102-
display.byte_format.display(w.size).to_string(), // we would have to impl alignment/padding ourselves otherwise...
103-
byte_column_width = display.byte_format.width()
104-
)
105-
.into(),
106-
Style {
107-
fg: match (is_selected, *is_focussed) {
108-
(true, true) => Color::DarkGray,
109-
(true, false) => Color::Black,
110-
_ => Color::Green,
105+
let bytes = Text::Styled(
106+
format!(
107+
"{:>byte_column_width$}",
108+
display.byte_format.display(w.size).to_string(), // we would have to impl alignment/padding ourselves otherwise...
109+
byte_column_width = display.byte_format.width()
110+
)
111+
.into(),
112+
Style {
113+
fg: match (is_selected, *is_focussed) {
114+
(true, true) => Color::DarkGray,
115+
(true, false) => Color::Black,
116+
_ => Color::Green,
117+
},
118+
..style
111119
},
112-
..style
113-
},
114-
);
115-
let percentage = Text::Styled(
116-
format!(
117-
" |{}| ",
118-
display.byte_vis.display(w.size as f32 / total as f32)
119-
)
120-
.into(),
121-
style,
122-
);
123-
let name = Text::Styled(
124-
fill_background_to_right(
120+
);
121+
let percentage = Text::Styled(
125122
format!(
126-
"{prefix}{}",
127-
w.name.to_string_lossy(),
128-
prefix = if path.is_dir() && !is_top(*root) {
129-
"/"
130-
} else {
131-
" "
132-
}
133-
),
134-
area.width,
135-
)
136-
.into(),
137-
Style {
138-
fg: match (path.is_dir(), path.exists()) {
139-
(true, true) if !is_selected => Color::DarkGray,
140-
(true, true) => style.fg,
141-
(_, false) => Color::Red,
142-
(false, true) => style.fg,
123+
" |{}| ",
124+
display.byte_vis.display(w.size as f32 / total as f32)
125+
)
126+
.into(),
127+
style,
128+
);
129+
let name = Text::Styled(
130+
fill_background_to_right(
131+
format!(
132+
"{prefix}{}",
133+
w.name.to_string_lossy(),
134+
prefix = if *is_dir && !is_top(*root) { "/" } else { " " }
135+
),
136+
area.width,
137+
)
138+
.into(),
139+
Style {
140+
fg: match (!is_dir, exists) {
141+
(true, true) if !is_selected => Color::DarkGray,
142+
(true, true) => style.fg,
143+
(_, false) => Color::Red,
144+
(false, true) => style.fg,
145+
},
146+
..style
143147
},
144-
..style
145-
},
146-
);
147-
let column_segments = vec![bytes, percentage, name];
148-
column_segments
149-
}),
148+
);
149+
let column_segments = vec![bytes, percentage, name];
150+
column_segments
151+
},
152+
),
150153
}
151154
.draw(area, buf);
152155
}

0 commit comments

Comments
 (0)