Some refactoring and improvements for clippy
This commit is contained in:
@@ -28,7 +28,9 @@ pub struct Element {
|
||||
}
|
||||
|
||||
impl Element {
|
||||
pub fn new(path_str: &str) -> Element {
|
||||
/// # Panics
|
||||
#[must_use]
|
||||
pub fn new(path_str: &str) -> Self {
|
||||
let path_built = Path::new(path_str);
|
||||
let metadata: fs::Metadata;
|
||||
if let Result::Ok(m) = fs::metadata(path_str) {
|
||||
@@ -37,13 +39,18 @@ impl Element {
|
||||
return Self {
|
||||
path: path_str.to_string(),
|
||||
file_type: TypeOfFile::File,
|
||||
name: path_str.split('/').next_back().unwrap().to_string(),
|
||||
name: path_str
|
||||
.split('/')
|
||||
.next_back()
|
||||
.expect("Error splitting path")
|
||||
.to_string(),
|
||||
perms: None,
|
||||
size: 0,
|
||||
creation: SystemTime::UNIX_EPOCH,
|
||||
};
|
||||
}
|
||||
let symlink_metadata = fs::symlink_metadata(path_str).unwrap();
|
||||
let symlink_metadata = fs::symlink_metadata(path_str)
|
||||
.unwrap_or_else(|e| panic!("Error while getting metadata from file: {path_str}: {e}"));
|
||||
|
||||
let t: TypeOfFile;
|
||||
|
||||
@@ -63,14 +70,19 @@ impl Element {
|
||||
|
||||
let mut name = path_built
|
||||
.file_name()
|
||||
.unwrap()
|
||||
.expect("Error getting os string from path")
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.expect("Error ")
|
||||
.to_string();
|
||||
|
||||
if symlink_metadata.is_symlink() {
|
||||
name.push_str(" -> ");
|
||||
name.push_str(read_link(path_built).unwrap().to_str().unwrap())
|
||||
name.push_str(
|
||||
read_link(path_built)
|
||||
.unwrap_or_else(|e| panic!("Error reading link from {path_str}: {e}"))
|
||||
.to_str()
|
||||
.expect("Error"),
|
||||
);
|
||||
}
|
||||
|
||||
let s = if t == TypeOfFile::Dir {
|
||||
@@ -79,44 +91,52 @@ impl Element {
|
||||
metadata.len()
|
||||
};
|
||||
|
||||
let now = SystemTime::now();
|
||||
|
||||
Self {
|
||||
path: path_str.to_string(),
|
||||
file_type: t,
|
||||
name,
|
||||
perms: Some(metadata.permissions()),
|
||||
size: s,
|
||||
creation: metadata.created().unwrap_or(SystemTime::now()),
|
||||
creation: metadata.created().unwrap_or(now),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_path_string(&self) -> String {
|
||||
self.path.clone()
|
||||
}
|
||||
|
||||
pub fn get_file_type(&self) -> TypeOfFile {
|
||||
#[must_use]
|
||||
pub const fn get_file_type(&self) -> TypeOfFile {
|
||||
self.file_type
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_name(&self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_perms(&self) -> Option<fs::Permissions> {
|
||||
self.perms.clone()
|
||||
}
|
||||
|
||||
pub fn get_size(&self) -> u64 {
|
||||
#[must_use]
|
||||
pub const fn get_size(&self) -> u64 {
|
||||
self.size
|
||||
}
|
||||
|
||||
pub fn get_creation(&self) -> SystemTime {
|
||||
#[must_use]
|
||||
pub const fn get_creation(&self) -> SystemTime {
|
||||
self.creation
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Element {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let file_icon = get_icon_file_type(self.get_name());
|
||||
let file_icon = get_icon_file_type(&self.get_name());
|
||||
|
||||
let mut is_dir = false;
|
||||
let icon = match self.file_type {
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#![warn(clippy::pedantic)]
|
||||
#![warn(clippy::nursery)]
|
||||
#![deny(clippy::unwrap_used)]
|
||||
|
||||
pub mod config;
|
||||
pub mod element;
|
||||
pub mod out;
|
||||
|
||||
10
src/main.rs
10
src/main.rs
@@ -1,4 +1,3 @@
|
||||
#![warn(clippy::pedantic)]
|
||||
use clap::Parser;
|
||||
use lsplus::{
|
||||
out::{default::default, list::list},
|
||||
@@ -32,12 +31,17 @@ pub struct Args {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// 138
|
||||
// let a: usize = 100;
|
||||
// let b = a as f32;
|
||||
// println!("{}, {}", a.checked_ilog10().unwrap(), b.log10().floor());
|
||||
|
||||
let args = Args::parse();
|
||||
|
||||
let elements = get_elements_from_path(args.path, args.all);
|
||||
let elements = get_elements_from_path(&args.path, args.all);
|
||||
|
||||
if args.list {
|
||||
list(elements, args.recursive, args.sort);
|
||||
list(elements, args.recursive, &args.sort);
|
||||
} else {
|
||||
default(elements);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
use crate::element::Element;
|
||||
use crate::utils::{get_string_length, pad_string};
|
||||
|
||||
/// # Panics
|
||||
pub fn default(mut elements: Vec<Element>) {
|
||||
elements.sort_unstable_by_key(|a: &Element| a.get_name());
|
||||
|
||||
let width = term_size::dimensions().unwrap().0;
|
||||
let width = term_size::dimensions()
|
||||
.expect("Error getting terminal width")
|
||||
.0;
|
||||
|
||||
let mut i = 1;
|
||||
|
||||
@@ -14,7 +17,7 @@ pub fn default(mut elements: Vec<Element>) {
|
||||
let mut total = usize::MAX;
|
||||
while total >= width - 1 {
|
||||
total = 0;
|
||||
num_columns = (elements.len() as f32 / i as f32).ceil() as usize;
|
||||
num_columns = (elements.len() / i) + 1;
|
||||
column_widths = vec![0; num_columns];
|
||||
for j in 0..num_columns {
|
||||
let mut max_len = 0;
|
||||
@@ -43,7 +46,7 @@ pub fn default(mut elements: Vec<Element>) {
|
||||
if i * j + k < elements.len() {
|
||||
print!(
|
||||
"{} ",
|
||||
pad_string(elements[i * j + k].to_string(), column_widths[j], true)
|
||||
pad_string(&elements[i * j + k].to_string(), column_widths[j], true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,25 @@ use crate::utils::{
|
||||
system_time_to_string, SortBy,
|
||||
};
|
||||
|
||||
pub fn list(mut elements: Vec<Element>, recursive_limit: usize, sort_by: SortBy) {
|
||||
/// # Panics
|
||||
pub fn list(mut elements: Vec<Element>, recursive_limit: usize, sort_by: &SortBy) {
|
||||
// ╭──────────────╼ File name ╾──────────────┬─╼ Size ╾─┬──╼ Creation ╾──╮
|
||||
// │ some_example_file │ 420.69 G │ 01-01-70 00:00 │
|
||||
// ╰─────────────────────────────────────────┴──────────┴────────────────╯
|
||||
let width = term_size::dimensions().unwrap().0;
|
||||
let width = term_size::dimensions()
|
||||
.expect("Error getting terminal dimensions")
|
||||
.0;
|
||||
|
||||
let name_max_len = get_max_width(&elements, recursive_limit, 0);
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
let elements_len = elements
|
||||
.len()
|
||||
.checked_ilog10()
|
||||
.expect("Error while doing log10 of elements len");
|
||||
|
||||
let name_length = name_max_len
|
||||
.max(14 + (elements.len() as f32).log10() as usize)
|
||||
.max(14_usize + elements_len as usize)
|
||||
.max(13)
|
||||
.min(width - 31);
|
||||
|
||||
@@ -24,18 +33,18 @@ pub fn list(mut elements: Vec<Element>, recursive_limit: usize, sort_by: SortBy)
|
||||
recursive_limit,
|
||||
0,
|
||||
&Vec::new(),
|
||||
&sort_by,
|
||||
sort_by,
|
||||
);
|
||||
print_footer(num_elements, name_length);
|
||||
}
|
||||
|
||||
fn print_header(name_length: usize) {
|
||||
print!("╭");
|
||||
for _ in 0..((name_length - 12) as f32 / 2.0).floor() as usize {
|
||||
for _ in 0..((name_length - 12) / 2) {
|
||||
print!("─");
|
||||
}
|
||||
print!("╼ File name ╾");
|
||||
for _ in 0..((name_length - 12) as f32 / 2.0).ceil() as usize {
|
||||
for _ in 0..(((name_length + name_length % 2) - 12) / 2) {
|
||||
print!("─");
|
||||
}
|
||||
println!("┬─╼ Size ╾─┬──╼ Creation ╾──╮");
|
||||
@@ -71,35 +80,19 @@ fn print_elements(
|
||||
|
||||
e_string.push_str(e.to_string().as_str());
|
||||
let file_text = pad_string(
|
||||
get_slice_of_string(e_string.as_str(), name_length - 1, 0, current_depth),
|
||||
&get_slice_of_string(e_string.as_str(), name_length - 1, 0, current_depth),
|
||||
name_length,
|
||||
true,
|
||||
);
|
||||
|
||||
print!(
|
||||
"{}",
|
||||
file_text // if e.get_file_type() == TypeOfFile::Dir {
|
||||
// file_text.cyan().to_string()
|
||||
// } else {
|
||||
// file_text
|
||||
// }
|
||||
);
|
||||
|
||||
// text.push_str(
|
||||
// pad_string(
|
||||
// get_slice_of_string(e_string.as_str(), name_length - 1, 0, current_depth),
|
||||
// name_length,
|
||||
// true,
|
||||
// )
|
||||
// .as_str(),
|
||||
// );
|
||||
print!("{file_text}");
|
||||
|
||||
print_size_and_creation_date(e);
|
||||
|
||||
let num_splits =
|
||||
get_string_length(e.get_name().as_str()) / (name_length - (2 + 2 * current_depth));
|
||||
|
||||
for j in 1..num_splits + 1 {
|
||||
for j in 1..=num_splits {
|
||||
let mut e_name = String::from("│ ");
|
||||
if current_depth > 0 {
|
||||
add_recursive_lines(
|
||||
@@ -108,19 +101,16 @@ fn print_elements(
|
||||
i == elements.len() - 1,
|
||||
" ",
|
||||
"│ ",
|
||||
)
|
||||
);
|
||||
}
|
||||
e_name.push_str(" ");
|
||||
e_name.push_str(
|
||||
get_slice_of_string(
|
||||
e_name.push_str(&get_slice_of_string(
|
||||
e.get_name().as_str(),
|
||||
name_length - (3 + 2 * current_depth),
|
||||
j,
|
||||
current_depth,
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
print!("{}", pad_string(e_name, name_length + 2, true));
|
||||
));
|
||||
print!("{}", pad_string(&e_name, name_length + 2, true));
|
||||
// text.push_str(pad_string(e_name, name_length + 2, true).as_str());
|
||||
println!("│ │ │");
|
||||
// text.push_str("│ │ │\n");
|
||||
@@ -130,7 +120,7 @@ fn print_elements(
|
||||
let dir_path = e.get_path_string();
|
||||
new_is_last_element.push(i == elements.len() - 1);
|
||||
num_elements += print_elements(
|
||||
&mut get_elements_from_path(dir_path, true),
|
||||
&mut get_elements_from_path(&dir_path, true),
|
||||
name_length,
|
||||
recursive_limit,
|
||||
current_depth + 1,
|
||||
@@ -167,9 +157,13 @@ fn add_recursive_lines(
|
||||
|
||||
#[inline]
|
||||
fn get_slice_of_string(e: &str, name_length: usize, i: usize, _current_depth: usize) -> String {
|
||||
e.chars().collect::<Vec<char>>()[((name_length) * i).min(get_string_length(e))
|
||||
..((name_length) * (i + 1)).min(get_string_length(e))]
|
||||
.iter()
|
||||
// e.chars().collect::<Vec<char>>()[((name_length) * i).min(get_string_length(e))
|
||||
// ..((name_length) * (i + 1)).min(get_string_length(e))]
|
||||
// .iter()
|
||||
// .collect()
|
||||
e.chars()
|
||||
.skip(((name_length) * i).min(get_string_length(e)))
|
||||
.take(((name_length) * (i + 1)).min(get_string_length(e)))
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -178,7 +172,7 @@ fn print_size_and_creation_date(e: &Element) {
|
||||
if e.get_file_type() == TypeOfFile::Dir {
|
||||
print!(" ");
|
||||
} else {
|
||||
print!("{}", pad_string(get_size_string(e.get_size()), 10, false));
|
||||
print!("{}", pad_string(&get_size_string(e.get_size()), 10, false));
|
||||
}
|
||||
print!("│");
|
||||
print!(" {} ", system_time_to_string(e.get_creation()));
|
||||
@@ -186,14 +180,14 @@ fn print_size_and_creation_date(e: &Element) {
|
||||
}
|
||||
|
||||
fn print_footer(num_elements: usize, name_length: usize) {
|
||||
let num_elements_len = (num_elements as f32).log10() as usize;
|
||||
let num_elements_len = num_elements.checked_ilog10().expect("Error") as usize;
|
||||
let name_length_fixed = name_length - (num_elements_len + 13);
|
||||
print!("╰");
|
||||
for _ in 0..((name_length_fixed) as f32 / 2.0).floor() as usize {
|
||||
for _ in 0..((name_length_fixed) / 2) {
|
||||
print!("─");
|
||||
}
|
||||
print!("╼ {} Elements ╾", num_elements);
|
||||
for _ in 0..((name_length_fixed) as f32 / 2.0).ceil() as usize {
|
||||
print!("╼ {num_elements} Elements ╾");
|
||||
for _ in 0..usize::midpoint(name_length_fixed, name_length_fixed % 2) {
|
||||
print!("─");
|
||||
}
|
||||
println!("┴──────────┴────────────────╯");
|
||||
@@ -205,7 +199,7 @@ fn get_max_width(elements: &Vec<Element>, recursive_limit: usize, current_depth:
|
||||
let mut length = e.to_string().chars().count() + current_depth * 2;
|
||||
if e.get_file_type() == TypeOfFile::Dir && current_depth < recursive_limit {
|
||||
let recursive_width = get_max_width(
|
||||
&get_elements_from_path(e.get_path_string(), true),
|
||||
&get_elements_from_path(&e.get_path_string(), true),
|
||||
recursive_limit,
|
||||
current_depth + 1,
|
||||
);
|
||||
|
||||
44
src/utils.rs
44
src/utils.rs
@@ -20,24 +20,27 @@ impl Display for SortBy {
|
||||
Self::SIZE => "size",
|
||||
Self::CREATION => "creation",
|
||||
};
|
||||
write!(f, "{}", text)
|
||||
write!(f, "{text}")
|
||||
}
|
||||
}
|
||||
|
||||
/// # Panics
|
||||
#[inline]
|
||||
pub fn get_elements_from_path(path: String, all: bool) -> Vec<Element> {
|
||||
#[must_use]
|
||||
pub fn get_elements_from_path(path: &str, all: bool) -> Vec<Element> {
|
||||
fs::read_dir(path)
|
||||
.unwrap()
|
||||
.map(|e| Element::new(e.unwrap().path().to_str().unwrap()))
|
||||
.unwrap_or_else(|e| panic!("Error reading directory {path}: {e}"))
|
||||
.map(|e| Element::new(e.expect("Error").path().to_str().expect("Error")))
|
||||
.filter(|element| all || !element.get_name().starts_with('.'))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn pad_string(s: String, pad: usize, after: bool) -> String {
|
||||
#[must_use]
|
||||
pub fn pad_string(s: &str, pad: usize, after: bool) -> String {
|
||||
let mut s2 = String::new();
|
||||
let s_length = get_string_length(&s);
|
||||
let s_length = get_string_length(s);
|
||||
if after {
|
||||
s2.push_str(s.as_str());
|
||||
s2.push_str(s);
|
||||
for _ in 0..(pad.saturating_sub(s_length)) {
|
||||
s2.push(' ');
|
||||
}
|
||||
@@ -45,7 +48,7 @@ pub fn pad_string(s: String, pad: usize, after: bool) -> String {
|
||||
for _ in 0..(pad.saturating_sub(s_length)) {
|
||||
s2.push(' ');
|
||||
}
|
||||
s2.push_str(s.as_str());
|
||||
s2.push_str(s);
|
||||
}
|
||||
s2
|
||||
}
|
||||
@@ -53,26 +56,30 @@ pub fn pad_string(s: String, pad: usize, after: bool) -> String {
|
||||
// Some characters like counts for more than one
|
||||
// character when using .len()
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn get_string_length(s: &str) -> usize {
|
||||
s.chars().count()
|
||||
}
|
||||
|
||||
/// # Panics
|
||||
#[must_use]
|
||||
pub fn get_size_string(bytes: u64) -> String {
|
||||
if bytes == 0 {
|
||||
return String::from(" 0 B ");
|
||||
}
|
||||
let bytes_f32 = bytes as f32;
|
||||
let exp = bytes_f32.log(1024.0).floor();
|
||||
let divided_num = bytes_f32 / 1024.0_f32.powf(exp);
|
||||
// let bytes_f32 = bytes as f32;
|
||||
let exp = bytes.checked_ilog(1024).expect("Error");
|
||||
let divided_num = bytes / 1024_u64.pow(exp);
|
||||
let unit = ['B', 'K', 'M', 'G', 'T', 'P', 'Y', 'E'][exp as usize];
|
||||
if unit == 'B' {
|
||||
format!("{:.0} {} ", divided_num, unit)
|
||||
format!("{divided_num:.0} {unit} ")
|
||||
} else {
|
||||
format!("{:.2} {} ", divided_num, unit)
|
||||
format!("{divided_num:.2} {unit} ")
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn system_time_to_string(system_time: SystemTime) -> String {
|
||||
let datetime: DateTime<Utc> = system_time.into();
|
||||
datetime.format("%d-%m-%y %H:%M").to_string()
|
||||
@@ -87,9 +94,14 @@ pub fn sort_elements(elements: &mut [Element], sort_by: &SortBy) {
|
||||
}
|
||||
}
|
||||
|
||||
// ALL ICONS MUST BE FOLLOWED BY A SPACE
|
||||
pub fn get_icon_file_type<'a>(filename: String) -> &'a str {
|
||||
let extension = filename.split('.').next_back().unwrap();
|
||||
/// # Panics
|
||||
#[must_use]
|
||||
pub fn get_icon_file_type<'a>(filename: &str) -> &'a str {
|
||||
// ALL ICONS MUST BE FOLLOWED BY A SPACE
|
||||
let extension = filename
|
||||
.split('.')
|
||||
.next_back()
|
||||
.expect("Error while sparating filename extension");
|
||||
match extension.to_lowercase().as_str() {
|
||||
"jpg" | "jpeg" | "png" | "bmp" | "gif" | "webp" | "svg" => " ",
|
||||
"zip" | "rar" | "7zip" | "tar" | "gz" | "tgz" => " ",
|
||||
|
||||
Reference in New Issue
Block a user