forked from KSXGitHub/parallel-disk-usage
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcoloring.rs
More file actions
126 lines (114 loc) · 3.87 KB
/
Copy pathcoloring.rs
File metadata and controls
126 lines (114 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use super::{ChildPosition, TreeHorizontalSlice};
use crate::ls_colors::LsColors;
use derive_more::Display;
use std::{collections::HashMap, ffi::OsStr, fmt};
use zero_copy_pads::Width;
/// Coloring configuration: ANSI prefix strings from the environment and a full-path-to-color map.
#[derive(Debug)]
pub struct Coloring<'a> {
ls_colors: LsColors,
map: HashMap<Vec<&'a OsStr>, Color>,
}
impl<'a> Coloring<'a> {
/// Create a new [`Coloring`] from LS_COLORS prefixes and a path-components-to-color map.
pub fn new(ls_colors: LsColors, map: HashMap<Vec<&'a OsStr>, Color>) -> Self {
Coloring { ls_colors, map }
}
/// Look up the color for a node identified by its path components and whether it has children,
/// then wrap the given [`TreeHorizontalSlice`] in the appropriate colored or colorless variant.
pub(super) fn maybe_color_tree_slice(
&self,
path_components: &[&'a OsStr],
has_children: bool,
slice: TreeHorizontalSlice<String>,
) -> MaybeColoredTreeHorizontalSlice<'_> {
let color = if has_children {
Some(Color::Directory)
} else {
self.map.get(path_components).copied()
};
match color {
Some(color) => MaybeColoredTreeHorizontalSlice::Colorful(ColoredTreeHorizontalSlice {
slice,
color,
ls_colors: &self.ls_colors,
}),
None => MaybeColoredTreeHorizontalSlice::Colorless(slice),
}
}
}
/// The coloring to apply to a node name.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Color {
/// Color as a directory.
Directory,
/// Color as a regular file.
Normal,
/// Color as an executable file.
Executable,
/// Color as a symbolic link.
Symlink,
}
impl Color {
/// Get the ANSI prefix for this color from the given prefix table.
fn ansi_prefix(self, prefixes: &LsColors) -> AnsiPrefix<'_> {
AnsiPrefix(prefixes.prefix_str(self))
}
}
/// ANSI prefix wrapper for a [`Color`] variant, implements [`Display`].
#[derive(Display)]
struct AnsiPrefix<'a>(&'a str);
impl AnsiPrefix<'_> {
/// Returns the reset suffix to emit after this prefix, or `""` if no prefix.
fn suffix(&self) -> &'static str {
if self.0.is_empty() {
""
} else {
"\x1b[0m"
}
}
}
/// A [`TreeHorizontalSlice`] with its color applied, used for rendering.
pub(super) struct ColoredTreeHorizontalSlice<'a> {
slice: TreeHorizontalSlice<String>,
color: Color,
ls_colors: &'a LsColors,
}
impl fmt::Display for ColoredTreeHorizontalSlice<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let TreeHorizontalSlice {
ancestor_relative_positions,
skeletal_component,
name,
} = &self.slice;
for pos in ancestor_relative_positions {
let connector = match pos {
ChildPosition::Init => "│ ",
ChildPosition::Last => " ",
};
write!(f, "{connector}")?;
}
let prefix = self.color.ansi_prefix(self.ls_colors);
let suffix = prefix.suffix();
write!(f, "{skeletal_component}{prefix}{name}{suffix}")
}
}
impl Width for ColoredTreeHorizontalSlice<'_> {
fn width(&self) -> usize {
self.slice.width()
}
}
/// Either a [`TreeHorizontalSlice`] (colorless) or a [`ColoredTreeHorizontalSlice`] (colorful).
#[derive(Display)]
pub(super) enum MaybeColoredTreeHorizontalSlice<'a> {
Colorless(TreeHorizontalSlice<String>),
Colorful(ColoredTreeHorizontalSlice<'a>),
}
impl Width for MaybeColoredTreeHorizontalSlice<'_> {
fn width(&self) -> usize {
match self {
MaybeColoredTreeHorizontalSlice::Colorless(slice) => slice.width(),
MaybeColoredTreeHorizontalSlice::Colorful(slice) => slice.width(),
}
}
}