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
extern crate libc;
use crate::colors::*;
use chrono::{DateTime, Local};
use libc::{S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR};
use std::os::unix::fs::PermissionsExt;
use std::{error::Error, ffi::OsString, path::Path};
#[derive(Clone)]
pub struct Entry {
mode: (bool, u32),
size: f64,
modified: DateTime<Local>,
file_name: OsString,
pub print: String,
}
impl Entry {
pub fn new(
mode: (bool, u32),
size: f64,
modified: DateTime<Local>,
file_name: OsString,
) -> Self {
let mut entry = Entry {
mode,
size,
modified,
file_name,
print: String::new(),
};
entry.generate_print();
entry
}
pub fn from_path(path: &Path) -> Result<Self, Box<dyn Error>> {
let metadata = path.metadata()?;
let mode = (metadata.is_dir(), metadata.permissions().mode());
let size = metadata.len() as f64;
let modified: DateTime<Local> = DateTime::from(metadata.modified()?);
let file_name = path.as_os_str().to_os_string();
let entry = Entry::new(mode, size, modified, file_name);
Ok(entry)
}
fn generate_print(&mut self) {
let order = if self.size % 1000000000000.0 != self.size {
self.size /= 1000000000000.0;
"TB"
} else if self.size % 1000000000.0 != self.size {
self.size /= 1000000000.0;
"GB"
} else if self.size % 1000000.0 != self.size {
self.size /= 1000000.0;
"MB"
} else if self.size % 1000.0 != self.size {
self.size /= 1000.0;
"KB"
} else {
"B"
};
self.print = format!(
"{} {} {} {}",
self.clone().parse_permissions(),
format_args!("{}{:>5} {}{:<2}{}", MAGENTA, self.size, BOLD, order, RESET),
format_args!(
"{}{}{}",
CYAN,
self.modified.format("%_d %b %H %H:%M"),
RESET
),
format_args!("{}{:?}{}", BLUE, self.file_name, RESET)
);
}
fn parse_permissions(self) -> String {
let mut formated_mode = String::new();
let directory: String = if self.mode.0 {
format!("{}{}d{}", BLUE, BOLD, RESET)
} else {
format!("{}·{}", BLACK, RESET)
};
formated_mode.push_str(directory.as_str());
let user = self.triplet(S_IRUSR, S_IWUSR, S_IXUSR);
formated_mode.push_str(user.as_str());
let group = self.triplet(S_IRGRP, S_IWGRP, S_IXGRP);
formated_mode.push_str(group.as_str());
let other = self.triplet(S_IROTH, S_IWOTH, S_IXOTH);
formated_mode.push_str(other.as_str());
formated_mode
}
fn triplet(&self, read: u32, write: u32, execute: u32) -> String {
match (
self.mode.1 & read,
self.mode.1 & write,
self.mode.1 & execute,
) {
(0, 0, 0) => format!("{}---{}", BLACK, RESET),
(_, 0, 0) => format!("{}{}r{}{}--{}", BOLD, GREEN, RESET, BLACK, RESET),
(0, _, 0) => format!("{}-{}{}w{}{}-{}", BLACK, BOLD, YELLOW, RESET, BLACK, RESET),
(0, 0, _) => format!("{}--{}{}x{}", BLACK, BOLD, RED, RESET),
(_, 0, _) => format!(
"{}{}r{}{}-{}{}x{}",
BOLD, GREEN, RESET, BLACK, BOLD, RED, RESET
),
(_, _, 0) => format!("{}{}r{}w{}{}-{}", BOLD, GREEN, YELLOW, RESET, BLACK, RESET),
(0, _, _) => format!("{}-{}{}w{}x{}", BLACK, BOLD, YELLOW, GREEN, RESET),
(_, _, _) => format!("{}{}r{}w{}x{}", BOLD, GREEN, YELLOW, GREEN, RESET),
}
}
}