rust ll
This commit is contained in:
@@ -0,0 +1,742 @@
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, Stdio};
|
||||
use std::mem;
|
||||
use std::fs::Metadata;
|
||||
use std::time::UNIX_EPOCH;
|
||||
|
||||
const FILE_SYSTEM_MAX_PATH: usize = 0xfff;
|
||||
const NR_OF_SUPPORTET_LANG: usize = 13;
|
||||
const CARD_LEN: usize = 12;
|
||||
const ERRR: i32 = 0x0FFF_AFFF_u32 as i32;
|
||||
|
||||
const LLL_CLI_HELP_MESSAGE: &str = "\
|
||||
rustc -O -C panic=abort lll.rs -o lll
|
||||
-s --size sort by size
|
||||
-l --ls ls like output
|
||||
-h --help print help
|
||||
-p --path set path default is current
|
||||
-q --qqqq print all absolut paths of a folder
|
||||
@VERSION 10.0.0
|
||||
";
|
||||
|
||||
#[repr(C)]
|
||||
struct Passwd {
|
||||
pw_name: *mut LllLibcChar,
|
||||
pw_passwd: *mut LllLibcChar,
|
||||
pw_uid: u32,
|
||||
pw_gid: u32,
|
||||
pw_gecos: *mut LllLibcChar,
|
||||
pw_dir: *mut LllLibcChar,
|
||||
pw_shell: *mut LllLibcChar,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct Group {
|
||||
gr_name: *mut LllLibcChar,
|
||||
gr_passwd: *mut LllLibcChar,
|
||||
gr_gid: u32,
|
||||
gr_mem: *mut *mut LllLibcChar,
|
||||
}
|
||||
|
||||
type LllLibcChar = i8;
|
||||
|
||||
extern "C" {
|
||||
fn getpwuid(uid: u32) -> *mut Passwd;
|
||||
fn getgrgid(gid: u32) -> *mut Group;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct TypeEntry {
|
||||
name: &'static str,
|
||||
countet_size: u64,
|
||||
globalsumindex: i32,
|
||||
}
|
||||
|
||||
static mut TYPES: [TypeEntry; NR_OF_SUPPORTET_LANG] = [
|
||||
TypeEntry { name: "", countet_size: 0, globalsumindex: 0 },
|
||||
TypeEntry { name: "c", countet_size: 0, globalsumindex: 1 },
|
||||
TypeEntry { name: "cpp", countet_size: 0, globalsumindex: 2 },
|
||||
TypeEntry { name: "ino", countet_size: 0, globalsumindex: 3 },
|
||||
TypeEntry { name: "py", countet_size: 0, globalsumindex: 4 },
|
||||
TypeEntry { name: "java", countet_size: 0, globalsumindex: 5 },
|
||||
TypeEntry { name: "sh", countet_size: 0, globalsumindex: 6 },
|
||||
TypeEntry { name: "js", countet_size: 0, globalsumindex: 7 },
|
||||
TypeEntry { name: "html", countet_size: 0, globalsumindex: 8 },
|
||||
TypeEntry { name: "asm", countet_size: 0, globalsumindex: 9 },
|
||||
TypeEntry { name: "rs", countet_size: 0, globalsumindex: 10 },
|
||||
TypeEntry { name: "sql", countet_size: 0, globalsumindex: 11 },
|
||||
TypeEntry { name: "h", countet_size: 0, globalsumindex: 1 },
|
||||
];
|
||||
|
||||
static NAME_LIST: [&str; NR_OF_SUPPORTET_LANG] = [
|
||||
"Undefined", "C", "C++", "ESP", "Python", "Java", "ShellScript", "JavaScript", "HTML",
|
||||
"Assembly", "Rust", "SQL", "C",
|
||||
];
|
||||
|
||||
static COLOR_LIST: [u64; NR_OF_SUPPORTET_LANG] = [
|
||||
0x2222_0778_77CC,
|
||||
0x2222_0566_6666,
|
||||
0x2222_0A22_22FF,
|
||||
0x2222_0FEE_AA00,
|
||||
0x2222_00A8_A862,
|
||||
0x2222_00FF_FF00,
|
||||
0x2222_00FF_0010,
|
||||
0x2222_00BB_0010,
|
||||
0x2222_0088_8888,
|
||||
0x2222_00FF_8800,
|
||||
0x2222_00DE_A584,
|
||||
0x2222_0000_00FF,
|
||||
0x2222_0566_6666,
|
||||
];
|
||||
|
||||
fn coloramaprintifarma(ptext: &str, col: u64) -> String {
|
||||
let bg_r = ((col >> 40) & 0xFF) as u8;
|
||||
let bg_g = ((col >> 32) & 0xFF) as u8;
|
||||
let bg_b = ((col >> 24) & 0xFF) as u8;
|
||||
let fg_r = ((col >> 16) & 0xFF) as u8;
|
||||
let fg_g = ((col >> 8) & 0xFF) as u8;
|
||||
let fg_b = (col & 0xFF) as u8;
|
||||
format!(
|
||||
"\x1b[38;2;{};{};{}m\x1b[48;2;{};{};{}m{}\x1b[0m",
|
||||
fg_r, fg_g, fg_b, bg_r, bg_g, bg_b, ptext
|
||||
)
|
||||
}
|
||||
|
||||
fn utf8_char_len_local(c: u8) -> usize {
|
||||
if c < 0x80 {
|
||||
1
|
||||
} else if (c >> 5) == 0x6 {
|
||||
2
|
||||
} else if (c >> 4) == 0xE {
|
||||
3
|
||||
} else if (c >> 3) == 0x1E {
|
||||
4
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
fn pad_utf8(text: &str, mse: usize) -> String {
|
||||
let bytes = text.as_bytes();
|
||||
let mut res = Vec::with_capacity(mse + 4);
|
||||
let mut pos = 0usize;
|
||||
let mut i = 0usize;
|
||||
while pos < mse && i < bytes.len() {
|
||||
let clen = utf8_char_len_local(bytes[i]);
|
||||
if pos + clen > mse {
|
||||
break;
|
||||
}
|
||||
if i + clen > bytes.len() {
|
||||
break;
|
||||
}
|
||||
res.extend_from_slice(&bytes[i..i + clen]);
|
||||
pos += clen;
|
||||
i += clen;
|
||||
}
|
||||
while pos < mse {
|
||||
res.push(b' ');
|
||||
pos += 1;
|
||||
}
|
||||
String::from_utf8_lossy(&res).into_owned()
|
||||
}
|
||||
|
||||
fn coloramaprintifarmafillup(text: &str, advansed_color: u64) -> String {
|
||||
let padded = pad_utf8(text, CARD_LEN);
|
||||
coloramaprintifarma(&padded, advansed_color)
|
||||
}
|
||||
|
||||
fn coll(col: u64, ptext: &str) -> String {
|
||||
let r = ((col >> 16) & 0xFF) as u8;
|
||||
let g = ((col >> 8) & 0xFF) as u8;
|
||||
let b = (col & 0xFF) as u8;
|
||||
format!("\x1b[38;2;{};{};{}m{}\x1b[0m", r, g, b, ptext)
|
||||
}
|
||||
|
||||
fn chngg(pp: &str, color: u64, more_space: i32) -> String {
|
||||
let mse = match more_space {
|
||||
1 => CARD_LEN * 3,
|
||||
2 => CARD_LEN + 3,
|
||||
3 => CARD_LEN.saturating_sub(3),
|
||||
_ => CARD_LEN,
|
||||
};
|
||||
let padded = pad_utf8(pp, mse);
|
||||
coll(color, &padded)
|
||||
}
|
||||
|
||||
fn chngg_wrapper(index: i32) -> String {
|
||||
let idx = if index < 0 || index as usize >= NR_OF_SUPPORTET_LANG {
|
||||
0
|
||||
} else {
|
||||
index as usize
|
||||
};
|
||||
coloramaprintifarmafillup(NAME_LIST[idx], COLOR_LIST[idx])
|
||||
}
|
||||
|
||||
fn mode_to_str(mode: u32) -> String {
|
||||
let mut out = String::with_capacity(10);
|
||||
let ft = mode & 0o170000;
|
||||
out.push(match ft {
|
||||
0o040000 => 'd',
|
||||
0o120000 => 'l',
|
||||
0o020000 => 'c',
|
||||
0o060000 => 'b',
|
||||
0o010000 => 'p',
|
||||
0o140000 => 's',
|
||||
_ => '-',
|
||||
});
|
||||
out.push(if mode & 0o400 != 0 { 'r' } else { '-' });
|
||||
out.push(if mode & 0o200 != 0 { 'w' } else { '-' });
|
||||
out.push(if mode & 0o100 != 0 { 'x' } else { '-' });
|
||||
out.push(if mode & 0o040 != 0 { 'r' } else { '-' });
|
||||
out.push(if mode & 0o020 != 0 { 'w' } else { '-' });
|
||||
out.push(if mode & 0o010 != 0 { 'x' } else { '-' });
|
||||
out.push(if mode & 0o004 != 0 { 'r' } else { '-' });
|
||||
out.push(if mode & 0o002 != 0 { 'w' } else { '-' });
|
||||
out.push(if mode & 0o001 != 0 { 'x' } else { '-' });
|
||||
out
|
||||
}
|
||||
|
||||
fn process_size(size: u64) -> String {
|
||||
let units = ["B", "KB", "MB", "GB", "TB"];
|
||||
let mut s = size as f64;
|
||||
let mut u = 0usize;
|
||||
while s >= 1024.0 && u < 4 {
|
||||
s /= 1024.0;
|
||||
u += 1;
|
||||
}
|
||||
format!("{:.1} {}", s, units[u])
|
||||
}
|
||||
|
||||
fn get_type_ind_by_name(type_s: &str) -> i32 {
|
||||
unsafe {
|
||||
for i in 1..NR_OF_SUPPORTET_LANG {
|
||||
if !TYPES[i].name.is_empty() && TYPES[i].name == type_s {
|
||||
return i as i32;
|
||||
}
|
||||
}
|
||||
}
|
||||
ERRR
|
||||
}
|
||||
|
||||
fn add_type_value(pp_index: i32, filesize: u64) -> i32 {
|
||||
if pp_index < 0 || pp_index as usize >= NR_OF_SUPPORTET_LANG {
|
||||
return -1;
|
||||
}
|
||||
unsafe {
|
||||
TYPES[pp_index as usize].countet_size =
|
||||
TYPES[pp_index as usize].countet_size.saturating_add(filesize);
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
fn get_type(fullpath: &str, filesize: u64) {
|
||||
let bytes = fullpath.as_bytes();
|
||||
let size = bytes.len() as i32;
|
||||
if size <= 0 {
|
||||
return;
|
||||
}
|
||||
let mut point_index: i32 = -1;
|
||||
let mut i = size - 1;
|
||||
loop {
|
||||
if bytes[i as usize] == b'.' {
|
||||
point_index = i;
|
||||
break;
|
||||
}
|
||||
if bytes[i as usize] == b'/' {
|
||||
point_index = -1;
|
||||
break;
|
||||
}
|
||||
if i == 0 {
|
||||
break;
|
||||
}
|
||||
i -= 1;
|
||||
}
|
||||
if point_index <= 0 {
|
||||
return;
|
||||
}
|
||||
let start = (point_index + 1) as usize;
|
||||
if start >= bytes.len() {
|
||||
return;
|
||||
}
|
||||
let type_s = match std::str::from_utf8(&bytes[start..]) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return,
|
||||
};
|
||||
let index = get_type_ind_by_name(type_s);
|
||||
if index != ERRR {
|
||||
add_type_value(index, filesize);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_mount_point(path: &Path) -> bool {
|
||||
let st_path = match fs::metadata(path) {
|
||||
Ok(m) => m,
|
||||
Err(_) => return false,
|
||||
};
|
||||
let parent = path.join("..");
|
||||
let st_parent = match fs::metadata(&parent) {
|
||||
Ok(m) => m,
|
||||
Err(_) => return false,
|
||||
};
|
||||
st_path.dev() != st_parent.dev()
|
||||
}
|
||||
|
||||
fn store_modification_timestamp(metadata: &Metadata, timestamp: &mut i64) {
|
||||
if let Ok(modified) = metadata.modified() {
|
||||
if let Ok(duration) = modified.duration_since(UNIX_EPOCH) {
|
||||
if *timestamp < duration.as_secs() as i64 {
|
||||
*timestamp = duration.as_secs() as i64;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn folder_size(path: &Path, ts_max: &mut i64) -> u64 {
|
||||
if is_mount_point(path) {
|
||||
return 0;
|
||||
}
|
||||
let mut total: u64 = 0;
|
||||
let rd = match fs::read_dir(path) {
|
||||
Ok(d) => d,
|
||||
Err(_) => return 0,
|
||||
};
|
||||
for entry in rd.flatten() {
|
||||
let name = entry.file_name();
|
||||
if name == "." || name == ".." {
|
||||
continue;
|
||||
}
|
||||
let full = entry.path();
|
||||
let st = match fs::symlink_metadata(&full) {
|
||||
Ok(m) => m,
|
||||
Err(_) => continue,
|
||||
};
|
||||
if st.file_type().is_dir() {
|
||||
total = total.saturating_add(folder_size(&full, ts_max));
|
||||
} else if st.file_type().is_symlink() {
|
||||
continue;
|
||||
} else {
|
||||
store_modification_timestamp(&st, ts_max);
|
||||
let sz = st.len();
|
||||
total = total.saturating_add(sz);
|
||||
if let Some(s) = full.to_str() {
|
||||
get_type(s, sz);
|
||||
}
|
||||
}
|
||||
}
|
||||
total
|
||||
}
|
||||
|
||||
fn get_dom_lang_index() -> i32 {
|
||||
let mut local_sums = [0u64; NR_OF_SUPPORTET_LANG];
|
||||
unsafe {
|
||||
for i in 1..NR_OF_SUPPORTET_LANG {
|
||||
let g = TYPES[i].globalsumindex;
|
||||
if g >= 0 && (g as usize) < NR_OF_SUPPORTET_LANG {
|
||||
local_sums[g as usize] = local_sums[g as usize].saturating_add(TYPES[i].countet_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut max_idx = 0i32;
|
||||
let mut max_val = 0u64;
|
||||
for i in 0..NR_OF_SUPPORTET_LANG {
|
||||
if local_sums[i] > max_val {
|
||||
max_val = local_sums[i];
|
||||
max_idx = i as i32;
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
for i in 0..NR_OF_SUPPORTET_LANG {
|
||||
TYPES[i].countet_size = 0;
|
||||
}
|
||||
}
|
||||
max_idx
|
||||
}
|
||||
|
||||
fn get_dom_single_file_index_from_path(path: &str) -> i32 {
|
||||
let ext = Path::new(path)
|
||||
.extension()
|
||||
.and_then(|e| e.to_str())
|
||||
.unwrap_or("");
|
||||
unsafe {
|
||||
for i in 0..NR_OF_SUPPORTET_LANG {
|
||||
if !TYPES[i].name.is_empty() && TYPES[i].name == ext {
|
||||
return i as i32;
|
||||
}
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
fn clipper(content: &str) {
|
||||
let mut child = match Command::new("xclip")
|
||||
.arg("-selection")
|
||||
.arg("clipboard")
|
||||
.stdin(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
Ok(c) => c,
|
||||
Err(_) => return,
|
||||
};
|
||||
if let Some(mut stdin) = child.stdin.take() {
|
||||
let _ = stdin.write_all(content.as_bytes());
|
||||
}
|
||||
let _ = child.wait();
|
||||
}
|
||||
|
||||
fn uid_name(uid: u32) -> String {
|
||||
unsafe {
|
||||
let pw = getpwuid(uid);
|
||||
if pw.is_null() {
|
||||
return "unknown".to_string();
|
||||
}
|
||||
let name = (*pw).pw_name;
|
||||
if name.is_null() {
|
||||
return "unknown".to_string();
|
||||
}
|
||||
std::ffi::CStr::from_ptr(name)
|
||||
.to_string_lossy()
|
||||
.into_owned()
|
||||
}
|
||||
}
|
||||
|
||||
fn gid_name(gid: u32) -> String {
|
||||
unsafe {
|
||||
let gr = getgrgid(gid);
|
||||
if gr.is_null() {
|
||||
return "unknown".to_string();
|
||||
}
|
||||
let name = (*gr).gr_name;
|
||||
if name.is_null() {
|
||||
return "unknown".to_string();
|
||||
}
|
||||
std::ffi::CStr::from_ptr(name)
|
||||
.to_string_lossy()
|
||||
.into_owned()
|
||||
}
|
||||
}
|
||||
|
||||
fn format_mtime(secs: i64) -> String {
|
||||
extern "C" {
|
||||
fn localtime_r(timep: *const i64, result: *mut LibcTm) -> *mut LibcTm;
|
||||
fn strftime(
|
||||
s: *mut i8,
|
||||
max: usize,
|
||||
format: *const i8,
|
||||
tm: *const LibcTm,
|
||||
) -> usize;
|
||||
}
|
||||
#[repr(C)]
|
||||
struct LibcTm {
|
||||
tm_sec: i32,
|
||||
tm_min: i32,
|
||||
tm_hour: i32,
|
||||
tm_mday: i32,
|
||||
tm_mon: i32,
|
||||
tm_year: i32,
|
||||
tm_wday: i32,
|
||||
tm_yday: i32,
|
||||
tm_isdst: i32,
|
||||
tm_gmtoff: i64,
|
||||
tm_zone: *const i8,
|
||||
}
|
||||
unsafe {
|
||||
let mut tm: LibcTm = mem::zeroed();
|
||||
let t = secs;
|
||||
if localtime_r(&t, &mut tm).is_null() {
|
||||
return String::from("?");
|
||||
}
|
||||
let mut buf = [0i8; 64];
|
||||
let fmt = b"%e. %b %H:%M\0";
|
||||
let n = strftime(
|
||||
buf.as_mut_ptr(),
|
||||
buf.len(),
|
||||
fmt.as_ptr() as *const i8,
|
||||
&tm,
|
||||
);
|
||||
if n == 0 {
|
||||
return String::from("?");
|
||||
}
|
||||
std::ffi::CStr::from_ptr(buf.as_ptr())
|
||||
.to_string_lossy()
|
||||
.trim()
|
||||
.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_absolut_path(name: &str) {
|
||||
let cwd = match env::current_dir() {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
eprintln!("ERROR: getcwd: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let mut absolut = cwd;
|
||||
absolut.push(name);
|
||||
let s = absolut.to_string_lossy().into_owned();
|
||||
println!("{}", s);
|
||||
clipper(&s);
|
||||
}
|
||||
|
||||
fn sort_by_timestamp(unix_timestamps: &mut [i64], rows: &mut [String]) {
|
||||
let n = unix_timestamps.len();
|
||||
if n <= 1 {
|
||||
return;
|
||||
}
|
||||
for i in 0..n - 1 {
|
||||
let mut max_index = i;
|
||||
for j in i + 1..n {
|
||||
if unix_timestamps[j] > unix_timestamps[max_index] {
|
||||
max_index = j;
|
||||
}
|
||||
}
|
||||
if max_index != i {
|
||||
unix_timestamps.swap(i, max_index);
|
||||
rows.swap(i, max_index);
|
||||
}
|
||||
}
|
||||
rows.reverse();
|
||||
unix_timestamps.reverse();
|
||||
}
|
||||
|
||||
fn sort_by_size(sizes: &mut [u64], rows: &mut [String]) {
|
||||
let n = sizes.len();
|
||||
if n <= 1 {
|
||||
return;
|
||||
}
|
||||
for i in 0..n - 1 {
|
||||
let mut max_index = i;
|
||||
for j in i + 1..n {
|
||||
if sizes[j] < sizes[max_index] {
|
||||
max_index = j;
|
||||
}
|
||||
}
|
||||
if max_index != i {
|
||||
sizes.swap(i, max_index);
|
||||
rows.swap(i, max_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_absolut_paths(path_to_process: &str) {
|
||||
let rd = match fs::read_dir(path_to_process) {
|
||||
Ok(d) => d,
|
||||
Err(e) => {
|
||||
eprintln!("opendir: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let is_dot = path_to_process.starts_with('.');
|
||||
let cwd = env::current_dir().ok();
|
||||
for entry in rd.flatten() {
|
||||
let name = entry.file_name();
|
||||
if name == "." || name == ".." {
|
||||
continue;
|
||||
}
|
||||
let name_s = name.to_string_lossy();
|
||||
if is_dot {
|
||||
if let Some(ref p) = cwd {
|
||||
println!("{}/{}", p.display(), name_s);
|
||||
}
|
||||
} else {
|
||||
println!("{}/{}", path_to_process.trim_end_matches('/'), name_s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main_lll_impl(sort_by_size_flag: bool, path_to_process: &str) -> i32 {
|
||||
let rd = match fs::read_dir(path_to_process) {
|
||||
Ok(d) => d,
|
||||
Err(e) => {
|
||||
eprintln!("opendir: {}", e);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
let mut rows: Vec<String> = Vec::new();
|
||||
let mut sizes: Vec<u64> = Vec::new();
|
||||
let mut unix_timestamps: Vec<i64> = Vec::new();
|
||||
for entry in rd.flatten() {
|
||||
let name_os = entry.file_name();
|
||||
if name_os == "." || name_os == ".." {
|
||||
continue;
|
||||
}
|
||||
let name = name_os.to_string_lossy();
|
||||
let full: PathBuf = Path::new(path_to_process).join(&*name);
|
||||
let st = match fs::symlink_metadata(&full) {
|
||||
Ok(m) => m,
|
||||
Err(_) => continue,
|
||||
};
|
||||
let mode = st.mode();
|
||||
let perms = mode_to_str(mode);
|
||||
let links = st.nlink();
|
||||
let owner = uid_name(st.uid());
|
||||
let group = gid_name(st.gid());
|
||||
let ft = st.file_type();
|
||||
let raw_size: u64;
|
||||
let sizebuf: String;
|
||||
let mut timestamp: i64 = 0;
|
||||
if ft.is_dir() {
|
||||
raw_size = folder_size(&full, &mut timestamp);
|
||||
sizebuf = process_size(raw_size);
|
||||
if let Some(s) = full.to_str() {
|
||||
get_type(s, raw_size);
|
||||
}
|
||||
} else {
|
||||
store_modification_timestamp(&st, &mut timestamp);
|
||||
raw_size = st.len();
|
||||
sizebuf = process_size(raw_size);
|
||||
if let Some(s) = full.to_str() {
|
||||
get_type(s, raw_size);
|
||||
}
|
||||
}
|
||||
let timestr = format_mtime(timestamp);
|
||||
let ja_index = get_dom_lang_index();
|
||||
let line = if ft.is_symlink() {
|
||||
match fs::read_link(&full) {
|
||||
Ok(target) => {
|
||||
let t = target.to_string_lossy();
|
||||
format!(
|
||||
"{} {:3} {} {} {:>8} {} {} -> {}",
|
||||
perms, links, owner, group, sizebuf, timestr, name, t
|
||||
)
|
||||
}
|
||||
Err(_) => format!(
|
||||
"{} {:3} {} {} {:>8} {} {}",
|
||||
perms, links, owner, group, sizebuf, timestr, name
|
||||
),
|
||||
}
|
||||
} else {
|
||||
let owner_col = chngg(&owner, 0x44FF44, 0);
|
||||
let group_col = chngg(&group, 0x88FF88, 0);
|
||||
let size_col = chngg(&sizebuf, 0xFF0000, 3);
|
||||
let time_col = chngg(×tr, 0x888866, 2);
|
||||
let type_fld = chngg_wrapper(ja_index);
|
||||
let name_col = chngg(
|
||||
&name,
|
||||
if ft.is_dir() { 0x9999FF } else { 0xFF33FF },
|
||||
1,
|
||||
);
|
||||
format!(
|
||||
"{} {:3} {} {} {:>8} {} {} {}",
|
||||
perms, links, owner_col, group_col, size_col, time_col, type_fld, name_col
|
||||
)
|
||||
};
|
||||
rows.push(line);
|
||||
sizes.push(raw_size);
|
||||
unix_timestamps.push(timestamp);
|
||||
}
|
||||
if !rows.is_empty() {
|
||||
if sort_by_size_flag {
|
||||
sort_by_size(&mut sizes, &mut rows);
|
||||
} else {
|
||||
sort_by_timestamp(&mut unix_timestamps, &mut rows);
|
||||
}
|
||||
}
|
||||
for row in &rows {
|
||||
println!("{}", row);
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
fn main_ls_impl() -> i32 {
|
||||
let rd = match fs::read_dir(".") {
|
||||
Ok(d) => d,
|
||||
Err(e) => {
|
||||
eprintln!("opendir: {}", e);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
let mut entries: Vec<String> = Vec::new();
|
||||
for entry in rd.flatten() {
|
||||
let name_os = entry.file_name();
|
||||
if name_os == "." || name_os == ".." {
|
||||
continue;
|
||||
}
|
||||
let name = name_os.to_string_lossy();
|
||||
let full = PathBuf::from(format!("./{}", name));
|
||||
let st = match fs::symlink_metadata(&full) {
|
||||
Ok(m) => m,
|
||||
Err(_) => continue,
|
||||
};
|
||||
let ft = st.file_type();
|
||||
let mut max_date_ts: i64 = 0;
|
||||
if ft.is_dir() {
|
||||
let _ = folder_size(&full, &mut max_date_ts);
|
||||
}
|
||||
let links = st.nlink();
|
||||
let lang_idx = if ft.is_dir() {
|
||||
get_dom_lang_index()
|
||||
} else {
|
||||
get_dom_single_file_index_from_path(full.to_str().unwrap_or(""))
|
||||
};
|
||||
let name_color: u64 = if ft.is_dir() { 0x9999FF } else { 0xFF33FF };
|
||||
let type_fld = chngg_wrapper(lang_idx);
|
||||
let project_name = chngg(&name, name_color, 1);
|
||||
let _ = {
|
||||
let b = project_name.as_bytes();
|
||||
let take = b.len().min(45);
|
||||
String::from_utf8_lossy(&b[..take]).into_owned()
|
||||
};
|
||||
let line = format!("{:5} {:>8} {:>46}", links, type_fld, project_name);
|
||||
entries.push(line);
|
||||
}
|
||||
let mut i = 0usize;
|
||||
while i < entries.len() {
|
||||
let end = (i + 4).min(entries.len());
|
||||
let mut line = String::new();
|
||||
for j in i..end {
|
||||
if j > i {
|
||||
line.push(' ');
|
||||
}
|
||||
line.push_str(&entries[j]);
|
||||
}
|
||||
println!("{}", line);
|
||||
i = end;
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let argc = args.len();
|
||||
let exit_code = if argc == 1 {
|
||||
main_lll_impl(false, ".")
|
||||
} else if argc == 2 || argc == 3 {
|
||||
let a1 = args[1].as_str();
|
||||
if a1 == "-s" || a1 == "--size" {
|
||||
main_lll_impl(true, ".")
|
||||
} else if a1 == "-l" || a1 == "--ls" {
|
||||
main_ls_impl()
|
||||
} else if a1 == "-h" || a1 == "--help" {
|
||||
print!("{}", LLL_CLI_HELP_MESSAGE);
|
||||
println!("FILE_SYSTEM_MAX_PATH : {}", FILE_SYSTEM_MAX_PATH);
|
||||
0
|
||||
} else if a1 == "-p" || a1 == "--path" {
|
||||
if argc != 3 {
|
||||
eprintln!("Unbekannter Parameter oder falsche Nutzung");
|
||||
1
|
||||
} else {
|
||||
main_lll_impl(false, &args[2])
|
||||
}
|
||||
} else if a1 == "-q" || a1 == "--qqqq" {
|
||||
if argc == 2 {
|
||||
print_absolut_paths(".");
|
||||
} else {
|
||||
print_absolut_paths(&args[2]);
|
||||
}
|
||||
0
|
||||
} else {
|
||||
get_absolut_path(&args[1]);
|
||||
0
|
||||
}
|
||||
} else {
|
||||
eprintln!("Unbekannter Parameter oder falsche Nutzung");
|
||||
1
|
||||
};
|
||||
std::process::exit(exit_code);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user