Some refactoring and improvements for clippy

This commit is contained in:
Guilleag01
2026-03-21 14:26:19 +01:00
parent a4cf1c1973
commit 33bb9d86b7
6 changed files with 116 additions and 79 deletions

View File

@@ -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 {

View File

@@ -1,3 +1,7 @@
#![warn(clippy::pedantic)]
#![warn(clippy::nursery)]
#![deny(clippy::unwrap_used)]
pub mod config;
pub mod element;
pub mod out;

View File

@@ -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);
}

View File

@@ -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)
);
}
}

View File

@@ -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.get_name().as_str(),
name_length - (3 + 2 * current_depth),
j,
current_depth,
)
.as_str(),
);
print!("{}", pad_string(e_name, name_length + 2, true));
e_name.push_str(&get_slice_of_string(
e.get_name().as_str(),
name_length - (3 + 2 * current_depth),
j,
current_depth,
));
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,
);

View File

@@ -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" => "󰗄 ",