minor fix

This commit is contained in:
Guilleag01
2023-11-09 18:13:32 +01:00
parent 830dc5d9ac
commit 8a690d0082
1856 changed files with 4052 additions and 0 deletions

0
src/config.json Normal file
View File

9
src/config.rs Normal file
View File

@@ -0,0 +1,9 @@
// use colored::Colorize;
// use crate::element::Element;
// pub struct Config {
// dir_config: Vec<usize>,
// }
// impl Config {}

110
src/element.rs Normal file
View File

@@ -0,0 +1,110 @@
use std::{fmt::Display, fs, os::unix::prelude::FileTypeExt, path::Path, time::SystemTime};
use crate::utils::get_icon_file_type;
#[derive(Copy, Clone)]
pub enum TypeOfFile {
File,
Dir,
Link,
Block,
Socket,
}
#[derive(Clone)]
pub struct Element {
path: String,
file_type: TypeOfFile,
name: String,
perms: fs::Permissions,
size: u64,
creation: SystemTime,
}
impl Element {
pub fn new(path_str: &str) -> Element {
let path_built = Path::new(path_str);
// println!("{:?}", path_built);
let metadata = fs::metadata(path_str).unwrap();
let symlink_metadata = fs::symlink_metadata(path_str).unwrap();
let t: TypeOfFile;
if symlink_metadata.is_symlink() {
t = TypeOfFile::Link;
} else if metadata.is_dir() {
t = TypeOfFile::Dir;
} else if metadata.is_file() {
t = TypeOfFile::File;
} else if metadata.file_type().is_block_device() {
t = TypeOfFile::Block;
} else if metadata.file_type().is_socket() {
t = TypeOfFile::Socket;
} else {
t = TypeOfFile::File;
}
Self {
path: path_str.to_string(),
file_type: t,
name: path_built
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string(),
perms: metadata.permissions(),
size: metadata.len(),
creation: metadata.created().unwrap(),
}
}
pub fn get_path_string(&self) -> String {
self.path.clone()
}
pub fn get_file_type(&self) -> TypeOfFile {
self.file_type
}
pub fn get_name(&self) -> String {
self.name.clone()
}
pub fn get_perms(&self) -> fs::Permissions {
self.perms.clone()
}
pub fn get_size(&self) -> u64 {
self.size
}
pub 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 mut is_dir = false;
let icon = match self.file_type {
TypeOfFile::File => file_icon,
TypeOfFile::Dir => {
is_dir = true;
""
}
TypeOfFile::Link => " 󱅷 ",
TypeOfFile::Block => " 󰋊 ",
TypeOfFile::Socket => " 󰛳 ",
};
write!(
f,
"{}{}{} ",
icon,
self.name.as_str(),
if is_dir { "/" } else { "" }
)
}
}

4
src/lib.rs Normal file
View File

@@ -0,0 +1,4 @@
pub mod config;
pub mod element;
pub mod out;
pub mod utils;

42
src/main.rs Normal file
View File

@@ -0,0 +1,42 @@
use clap::Parser;
use lsplus::{
element::Element,
out::{default::default, list::list},
};
use std::fs;
// Needs to be defined in main
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
pub struct Args {
/// Show hidden files
#[arg(short, long, default_value_t = false)]
all: bool,
/// Print as a list
#[arg(short, long, default_value_t = false)]
list: bool,
/// Path of the directory to list
#[arg(default_value_t = String::from("."))]
path: String,
}
fn main() {
let args = Args::parse();
let paths = fs::read_dir(args.path).unwrap();
let _max_width = 50;
let elements: Vec<Element> = paths
.map(|e| Element::new(e.unwrap().path().to_str().unwrap()))
.filter(|element| args.all || !element.get_name().starts_with('.'))
.collect();
if args.list {
list(elements);
} else {
default(elements);
}
}

50
src/out/default.rs Normal file
View File

@@ -0,0 +1,50 @@
use crate::element::Element;
use crate::utils::{get_string_length, pad_string};
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 mut i = 1;
let mut num_columns = 1;
let mut column_widths: Vec<usize> = Vec::new();
let mut total = std::usize::MAX;
while total >= width - 1 {
total = 0;
num_columns = (elements.len() as f32 / i as f32).ceil() as usize;
column_widths = vec![0; num_columns];
for j in 0..num_columns {
let mut max_len = 0;
for k in 0..i {
if i * j + k < elements.len() {
let space = get_string_length(&elements[i * j + k].to_string());
if space > max_len {
max_len = space;
}
}
}
// println!("Max len {}", max_len);
total += max_len;
column_widths[j] = max_len;
}
i += 1;
}
i -= 1;
for k in 0..i {
for j in 0..num_columns {
if i * j + k < elements.len() {
print!(
"{}",
pad_string(elements[i * j + k].to_string(), column_widths[j], true)
);
}
}
println!();
}
println!();
}

100
src/out/list.rs Normal file
View File

@@ -0,0 +1,100 @@
use crate::element::Element;
use crate::utils::{get_size_string, get_string_length, pad_string, system_time_to_string};
pub fn list(mut elements: Vec<Element>) {
elements.sort_unstable_by_key(|a: &Element| a.get_name());
let width = term_size::dimensions().unwrap().0;
// ╭──────────────╼ File name ╾──────────────┬─╼ Size ╾─┬──╼ Creation ╾──╮
// │ │ │ │
// ╰─────────────────────────────────────────┴──────────┴────────────────╯
let mut name_max_len = 0;
for e in &elements {
let length = get_string_length(e.to_string().as_str());
if length > name_max_len {
name_max_len = length;
}
}
let name_length = name_max_len
.max(14 + (elements.len() as f32).log10() as usize)
.max(13)
.min(width - 30);
print_header(name_length);
print_elements(&elements, name_length);
print_footer(&elements, name_length);
}
fn print_header(name_length: usize) {
print!("");
for _ in 0..((name_length - 13) as f32 / 2.0).floor() as usize {
print!("");
}
print!("╼ File name ╾");
for _ in 0..((name_length - 13) as f32 / 2.0).ceil() as usize {
print!("");
}
println!("┬─╼ Size ╾─┬──╼ Creation ╾──╮");
}
fn print_elements(elements: &Vec<Element>, name_length: usize) {
for e in elements {
let str_len = get_string_length(e.get_name().as_str());
print!("");
if get_string_length(e.to_string().as_str()) > name_length {
print!(
"{}",
pad_string(
e.to_string().as_str()[..=name_length].to_string(),
name_length,
true
)
);
print!("");
print!("{}", pad_string(get_size_string(e.get_size()), 10, false));
print!("");
print!(" {} ", system_time_to_string(e.get_creation()));
println!("");
for i in 1..(str_len / (name_length - 5) + 1) {
print!(
"{}",
pad_string(
e.get_name().as_str()
[((name_length - 5) * i)..((name_length - 5) * (i + 1)).min(str_len)]
.to_string(),
name_length - 3,
true
)
);
println!("│ │ │");
}
} else {
print!("{}", pad_string(e.to_string(), name_length, true));
print!("");
print!("{}", pad_string(get_size_string(e.get_size()), 10, false));
print!("");
print!(" {} ", system_time_to_string(e.get_creation()));
println!("");
}
}
}
fn print_footer(elements: &Vec<Element>, name_length: usize) {
let num_elements = elements.len();
let num_elements_len = (num_elements as f32).log10() as usize;
let name_length_fixed = name_length - (num_elements_len + 14);
print!("");
for _ in 0..((name_length_fixed) as f32 / 2.0).floor() as usize {
print!("");
}
print!("{} Elements ╾", num_elements);
for _ in 0..((name_length_fixed) as f32 / 2.0).ceil() as usize {
print!("");
}
// for _ in 0..(name_length - (num_elements_len + 15)) {
// print!("─");
// }
println!("┴──────────┴────────────────╯");
}

2
src/out/mod.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod default;
pub mod list;

67
src/utils.rs Normal file
View File

@@ -0,0 +1,67 @@
use std::time::SystemTime;
use chrono::offset::Utc;
use chrono::DateTime;
pub fn pad_string(s: String, pad: usize, after: bool) -> String {
let mut s2 = String::new();
if after {
s2.push_str(s.as_str());
for _ in 0..(pad - get_string_length(&s)) {
s2.push(' ');
}
} else {
for _ in 0..(pad - get_string_length(&s)) {
s2.push(' ');
}
s2.push_str(s.as_str());
}
s2
}
// Some characters like  counts for more than one
// character when using .len()
#[inline]
pub fn get_string_length(s: &str) -> usize {
s.chars().collect::<Vec<char>>().len();
s.chars().count()
}
pub fn get_size_string(bytes: u64) -> String {
if bytes == 0 {
return String::from("0.00 B ");
}
let bytes_f32 = bytes as f32;
let exp = bytes_f32.log(1024.0).floor();
// print!("\n{}", exp);
let divided_num = bytes_f32 / 1024.0_f32.powf(exp);
let unit = ['B', 'K', 'M', 'G', 'T', 'P', 'Y', 'E'][exp as usize];
format!("{:.2} {} ", divided_num, unit)
}
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()
}
pub fn get_icon_file_type<'a>(filename: String) -> &'a str {
let extension = filename.split('.').collect::<Vec<&str>>()[1..].join(".");
match extension.to_lowercase().as_str() {
"zip" | "rar" | "7zip" | "tar" | "tar.gz" | "tgz" => " 󰗄 ",
"rs" => "",
"jpg" | "jpeg" | "png" | "bmp" | "gif" | "webp" | "svg" => " 󰋩 ",
"flv" | "avi" | "mp4" | "webm" | "mov" => "",
"exe" | "ini" | "bat" => "",
"py" => "",
"c" => "",
"cpp" => "",
"json" => "",
"pdf" => " 󰈦 ",
"java" | "jar" => "",
"js" => "",
"html" => "",
"css" => "",
"csv" => "",
_ => " 󰈔 ",
}
}