Change a lot of stuff

This is a shitty comment, I know...
This commit is contained in:
Peltoche 2018-11-16 14:19:07 +01:00
parent 3dc1689e65
commit 4b9568510c
No known key found for this signature in database
GPG key ID: CED68D0487156952
7 changed files with 382 additions and 220 deletions

26
Cargo.lock generated
View file

@ -52,9 +52,16 @@ dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"size 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"users 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "num-traits"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.1.40" version = "0.1.40"
@ -68,6 +75,14 @@ dependencies = [
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "size"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.7.0" version = "0.7.0"
@ -106,6 +121,14 @@ name = "unicode-width"
version = "0.1.5" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "users"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "vec_map" name = "vec_map"
version = "0.8.1" version = "0.8.1"
@ -137,13 +160,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum size 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "baf1794b187cb1fd42cbe074cafc027be10b275c68aa7d039dcbef41e94d01d4"
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum users 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb3c80625ae5e77e1b402f8a0fa89afbd50622a6cae65128844720bd4e26b657"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"

View file

@ -7,4 +7,6 @@ version = "0.1.0"
ansi_term = "0.11.0" ansi_term = "0.11.0"
clap = "2.32.0" clap = "2.32.0"
lazy_static = "1.2.0" lazy_static = "1.2.0"
size = "0.1.1"
time = "0.1.40" time = "0.1.40"
users = "0.8.0"

206
src/core.rs Normal file
View file

@ -0,0 +1,206 @@
use formatter::*;
use size::*;
use std::cmp::Ordering;
use std::fs::{read_link, Metadata};
use std::os::unix::fs::MetadataExt;
use std::path::{Path, PathBuf};
use users::{get_group_by_gid, get_user_by_uid};
use Options;
pub struct Core<'a> {
formatter: Formatter,
options: &'a Options,
}
#[derive(Debug)]
pub struct Meta {
pub path: PathBuf,
pub metadata: Metadata,
pub group: String,
pub user: String,
pub symlink: Option<String>,
pub size_value: String,
pub size_unit: String,
}
impl<'a> Core<'a> {
pub fn new(options: &'a Options) -> Core<'a> {
Core {
options: options,
formatter: Formatter::new(),
}
}
pub fn print(&self, inputs: Vec<&str>) {
let print_folder_name: bool = inputs.len() > 1;
let mut dirs = Vec::new();
let mut files = Vec::new();
for input in inputs {
let path = Path::new(input);
if path.is_dir() {
dirs.push(path);
} else {
files.push(self.path_to_meta(&path).unwrap());
}
}
files.sort_unstable_by(sort_by_meta);
dirs.sort_unstable();
if files.len() > 0 {
self.print_long(&mut files);
}
for dir in dirs {
let folder_metas = self.list_folder_content(dir);
if print_folder_name {
println!("\n{}:", dir.display())
}
self.print_long(&folder_metas);
}
}
pub fn list_folder_content(&self, folder: &Path) -> Vec<Meta> {
let mut content: Vec<Meta> = Vec::new();
for entry in folder.read_dir().expect("read_dir call failed") {
if let Ok(entry) = entry {
if let Some(meta) = self.path_to_meta(entry.path().as_path()) {
content.push(meta);
}
}
}
content.sort_unstable_by(sort_by_meta);
content
}
pub fn path_to_meta(&self, path: &Path) -> Option<Meta> {
let mut name: Option<&str> = None;
if let Some(os_str_name) = path.file_name() {
if let Some(name_str) = os_str_name.to_str() {
name = Some(name_str);
}
}
if name.is_none() {
println!("failed to retrieve file name for {}", path.display());
return None;
}
// Skip the hidden files if the 'display_all' option is not set.
if name.unwrap().starts_with(".") && !self.options.display_all {
return None;
}
let meta;
let mut symlink = None;
if let Ok(res) = read_link(path) {
meta = path.symlink_metadata().unwrap();
symlink = Some(res.to_str().unwrap().to_string());
} else {
meta = path.metadata().unwrap();
}
let user = get_user_by_uid(meta.uid())
.unwrap()
.name()
.to_str()
.unwrap()
.to_string();
let group = get_group_by_gid(meta.gid())
.unwrap()
.name()
.to_str()
.unwrap()
.to_string();
let size = Size::Bytes(meta.len()).to_string(Base::Base10, Style::Abbreviated);
let size_parts: Vec<&str> = size.split(' ').collect();
Some(Meta {
path: path.to_path_buf(),
metadata: meta,
user: user,
group: group,
symlink: symlink,
size_value: size_parts[0].to_string(),
size_unit: size_parts[1].to_string(),
})
}
fn print_long(&self, metas: &Vec<Meta>) {
let max_user_length = self.detect_user_lenght(metas);
let max_group_length = self.detect_group_lenght(metas);
let (max_size_value_length, max_size_unit_length) = self.detect_size_lenghts(metas);
for meta in metas {
print!(
" {} {} {} {} {} {}\n",
self.formatter.format_permissions(&meta),
self.formatter.format_user(&meta.user, max_user_length),
self.formatter.format_group(&meta.group, max_group_length),
self.formatter
.format_size(&meta, max_size_value_length, max_size_unit_length),
self.formatter.format_date(&meta),
self.formatter.format_name(&meta),
);
}
}
fn detect_user_lenght(&self, paths: &Vec<Meta>) -> usize {
let mut max: usize = 0;
for path in paths {
if path.user.len() > max {
max = path.user.len();
}
}
max
}
fn detect_group_lenght(&self, paths: &Vec<Meta>) -> usize {
let mut max: usize = 0;
for path in paths {
if path.group.len() > max {
max = path.group.len();
}
}
max
}
fn detect_size_lenghts(&self, paths: &Vec<Meta>) -> (usize, usize) {
let mut max_value_length: usize = 0;
let mut max_unit_size: usize = 0;
for path in paths {
if path.size_value.len() > max_value_length {
max_value_length = path.size_value.len();
}
if path.size_unit.len() > max_unit_size {
max_unit_size = path.size_unit.len();
}
}
(max_value_length, max_unit_size)
}
}
fn sort_by_meta(a: &Meta, b: &Meta) -> Ordering {
if a.path.is_dir() == b.path.is_dir() {
a.path.cmp(&b.path)
} else if a.path.is_dir() && b.path.is_file() {
Ordering::Less
} else {
Ordering::Greater
}
}

View file

@ -1,5 +1,5 @@
use ansi_term::Colour; use ansi_term::Colour;
use path_lister::Path; use core::Meta;
use std::collections::HashMap; use std::collections::HashMap;
use std::os::unix::fs::PermissionsExt; use std::os::unix::fs::PermissionsExt;
use std::time::{Duration, SystemTime, UNIX_EPOCH}; use std::time::{Duration, SystemTime, UNIX_EPOCH};
@ -8,70 +8,72 @@ use time::Timespec;
const HOURE: u64 = 3600; // 1 HOURE == 3600 seconds const HOURE: u64 = 3600; // 1 HOURE == 3600 seconds
const DAY: u64 = HOURE * 24; // 1 DAY == 25 HOURE const DAY: u64 = HOURE * 24; // 1 DAY == 25 HOURE
#[derive(Hash, Debug, Eq, PartialEq, Copy, Clone)]
pub enum PathKind {
UnrecognizedFile,
RecognizedFile,
Dir,
}
lazy_static! {
pub static ref PathKindColor: HashMap<PathKind, (u8, u8, u8)> = {
let mut m = HashMap::new();
m.insert(PathKind::UnrecognizedFile, (0xFF, 0xFF, 0x04)); // gold
m.insert(PathKind::RecognizedFile, (0x04, 0xFF, 0x04)); // limon
m.insert(PathKind::Dir, (0x00, 0xAF, 0xFF)); // dodgerblue
m
};
}
#[derive(Hash, Debug, Eq, PartialEq, Copy, Clone)]
pub enum LastTimeModified {
DayOld,
HourOld,
Older,
}
lazy_static! {
pub static ref LastTimeModifiedColor: HashMap<LastTimeModified, (u8, u8, u8)> = {
let mut m = HashMap::new();
m.insert(LastTimeModified::HourOld, (0x2C, 0xFF, 0x2C));
m.insert(LastTimeModified::DayOld, (0x1C, 0xFF, 0xB7));
m.insert(LastTimeModified::Older, (0x63, 0xB1, 0x8A));
m
};
}
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Hash, Debug, Eq, PartialEq, Copy, Clone)] #[derive(Hash, Debug, Eq, PartialEq, Copy, Clone)]
pub enum Elem { pub enum Elem {
/// Path Kind
UnrecognizedFile,
RecognizedFile,
Dir,
/// Permissions
Read,
Write,
Exec,
NoAccess,
/// Last Time Modified
DayOld,
HourOld,
Older,
/// Link /// Link
DeadLink, DeadLink,
Link, Link,
/// User / Group Name
User,
Group,
/// File Size /// File Size
FileLarge, FileLarge,
FileMedium, FileMedium,
FileSmall, FileSmall,
}
/// Random lazy_static! {
Report, pub static ref Colors: HashMap<Elem, Colour> = {
User, let mut m = HashMap::new();
Tree, // User / Group
Empty, m.insert(Elem::User, Colour::RGB(0xFF, 0xFF, 0xD8));
Error, m.insert(Elem::Group, Colour::RGB(0xD9, 0xD9, 0x8F));
Normal,
/// Git // Permissions
Addition, m.insert(Elem::Read, Colour::RGB(0x5f, 0xD7, 0x5F));
Modification, m.insert(Elem::Write, Colour::RGB(0xD7, 0xD7, 0x87));
Deletion, m.insert(Elem::Exec, Colour::RGB(0xCD, 0x3A, 0x3A));
Untracked, m.insert(Elem::NoAccess, Colour::RGB(0xD7, 0x89, 0x89));
Unchanged,
// Path Kind
m.insert(Elem::UnrecognizedFile, Colour::RGB(0xFF, 0xFF, 0x04)); // gold
m.insert(Elem::RecognizedFile, Colour::RGB(0x04, 0xFF, 0x04)); // limon
m.insert(Elem::Dir, Colour::RGB(0x00, 0xAF, 0xFF)); // dodgerblue
// Last Time Modified
m.insert(Elem::HourOld, Colour::RGB(0x2C, 0xFF, 0x2C));
m.insert(Elem::DayOld, Colour::RGB(0x1C, 0xFF, 0xB7));
m.insert(Elem::Older, Colour::RGB(0x63, 0xB1, 0x8A));
// Last Time Modified
m.insert(Elem::FileSmall, Colour::RGB(0xFF, 0xFF, 0xD9));
m.insert(Elem::FileMedium, Colour::RGB(0x1C, 0xFF, 0xB7));
m.insert(Elem::FileLarge, Colour::RGB(0xFF, 0xB0, 0x00));
// Link
m.insert(Elem::Link, Colour::RGB(0x3B, 0xCE, 0xCe));
m
};
} }
pub struct Formatter {} pub struct Formatter {}
@ -81,29 +83,38 @@ impl Formatter {
Formatter {} Formatter {}
} }
pub fn format_path(&self, content: &str, path: &Path) -> String { pub fn format_name(&self, meta: &Meta) -> String {
let color = match path.metadata.is_dir() { let mut content = String::new();
true => PathKindColor[&PathKind::Dir],
false => PathKindColor[&PathKind::UnrecognizedFile], let color = match meta.metadata.is_dir() {
true => Colors[&Elem::Dir],
false => Colors[&Elem::UnrecognizedFile],
}; };
Colour::RGB(color.0, color.1, color.2) let file_name = meta.path.file_name().unwrap().to_str().unwrap();
.paint(content) content = content + &color.paint(file_name).to_string();
.to_string()
let color = Colors[&Elem::Link];
if let Some(ref link) = meta.symlink {
content =
content + &color.paint(String::from("") + &color.paint(link).to_string());
}
content
} }
pub fn format_date(&self, path: &Path) -> String { pub fn format_date(&self, meta: &Meta) -> String {
let modified_time = path.metadata.modified().unwrap(); let modified_time = meta.metadata.modified().unwrap();
let now = SystemTime::now(); let now = SystemTime::now();
let color; let color;
if modified_time > now - Duration::new(HOURE, 0) { if modified_time > now - Duration::new(HOURE, 0) {
color = LastTimeModifiedColor[&LastTimeModified::HourOld]; color = Colors[&Elem::HourOld];
} else if modified_time > now - Duration::new(DAY, 0) { } else if modified_time > now - Duration::new(DAY, 0) {
color = LastTimeModifiedColor[&LastTimeModified::DayOld]; color = Colors[&Elem::DayOld];
} else { } else {
color = LastTimeModifiedColor[&LastTimeModified::Older]; color = Colors[&Elem::Older];
} }
let modified_time_since_epoch = modified_time.duration_since(UNIX_EPOCH).unwrap(); let modified_time_since_epoch = modified_time.duration_since(UNIX_EPOCH).unwrap();
@ -112,28 +123,18 @@ impl Formatter {
modified_time_since_epoch.subsec_nanos() as i32, modified_time_since_epoch.subsec_nanos() as i32,
)); ));
Colour::RGB(color.0, color.1, color.2) color.paint(time.ctime().to_string()).to_string()
.paint(time.ctime().to_string())
.to_string()
} }
pub fn format_permissions(&self, path: &Path) -> String { pub fn format_permissions(&self, meta: &Meta) -> String {
let mut res = String::with_capacity(10); let mut res = String::with_capacity(10);
let mode = path.metadata.permissions().mode(); let mode = meta.metadata.permissions().mode();
let read_perm = Colour::RGB(0x5f, 0xD7, 0x5F) let read_perm = Colors[&Elem::Read].paint(String::from("r")).to_string();
.paint(String::from("r")) let write_perm = Colors[&Elem::Write].paint(String::from("w")).to_string();
.to_string(); let exec_perm = Colors[&Elem::Exec].paint(String::from("x")).to_string();
let write_perm = Colour::RGB(0xD7, 0xD7, 0x87) let no_access = Colors[&Elem::NoAccess].paint(String::from("-")).to_string();
.paint(String::from("w"))
.to_string();
let exec_perm = Colour::RGB(0xCD, 0x3A, 0x3A)
.paint(String::from("x"))
.to_string();
let no_access = Colour::RGB(0xD7, 0x89, 0x89)
.paint(String::from("-"))
.to_string();
// User Read Permisssions // User Read Permisssions
match mode & 0o400 { match mode & 0o400 {
@ -191,4 +192,64 @@ impl Formatter {
res.to_string() res.to_string()
} }
pub fn format_user(&self, user_name: &String, max_user_size: usize) -> String {
if user_name.len() == max_user_size {
return Colors[&Elem::User].paint(user_name).to_string();
}
let mut content = String::with_capacity(max_user_size);
content = content + user_name;
for _ in 0..(max_user_size - user_name.len()) {
content.push(' ');
}
content
}
pub fn format_group(&self, group_name: &String, max_group_size: usize) -> String {
if group_name.len() == max_group_size {
return Colors[&Elem::Group].paint(group_name).to_string();
}
let mut content = String::with_capacity(max_group_size);
content = content + group_name;
for _ in 0..(max_group_size - group_name.len()) {
content.push(' ');
}
content
}
pub fn format_size(
&self,
meta: &Meta,
max_value_length: usize,
max_unit_size: usize,
) -> String {
let mut content = String::with_capacity(max_value_length + max_unit_size + 1);
for _ in 0..(max_value_length - meta.size_value.len()) {
content.push(' ');
}
content = content + meta.size_value.as_str();
content.push(' ');
content = content + meta.size_unit.as_str();
for _ in 0..(max_unit_size - meta.size_unit.len()) {
content.push(' ');
}
if meta.metadata.len() < 10 * 1044 * 1024 {
return Colors[&Elem::FileSmall].paint(content).to_string();
} else if meta.metadata.len() < 100 * 1044 * 1024 {
return Colors[&Elem::FileMedium].paint(content).to_string();
} else {
return Colors[&Elem::FileLarge].paint(content).to_string();
}
}
} }

View file

@ -2,18 +2,17 @@ extern crate clap;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
extern crate ansi_term; extern crate ansi_term;
extern crate size;
extern crate time; extern crate time;
extern crate users;
mod core;
mod formatter; mod formatter;
mod path_lister;
mod presenter;
use clap::{App, Arg}; use clap::{App, Arg};
use path_lister::PathLister; use core::Core;
use presenter::Presenter;
pub struct Options { pub struct Options {
pub display_long: bool,
pub display_all: bool, pub display_all: bool,
} }
@ -21,20 +20,16 @@ fn main() {
let matches = App::new("lsd") let matches = App::new("lsd")
.about("A ls comment with a lot of pretty colors and some other stuff.") .about("A ls comment with a lot of pretty colors and some other stuff.")
.arg(Arg::with_name("FILE").multiple(true).default_value(".")) .arg(Arg::with_name("FILE").multiple(true).default_value("."))
.arg(Arg::with_name("long").short("l"))
.arg(Arg::with_name("all").short("a")) .arg(Arg::with_name("all").short("a"))
.get_matches(); .get_matches();
let options = Options { let options = Options {
display_long: matches.is_present("long"),
display_all: matches.is_present("all"), display_all: matches.is_present("all"),
}; };
let inputs: Vec<&str> = matches.values_of("FILE").unwrap().collect(); let inputs: Vec<&str> = matches.values_of("FILE").unwrap().collect();
let path_lister = PathLister::new(&options); let core = Core::new(&options);
let presenter = Presenter::new(&options); core.print(inputs);
presenter.print(path_lister.list_paths_to_print(inputs));
} }

View file

@ -1,80 +0,0 @@
use std::fs::Metadata;
use std::io::ErrorKind;
use std::path::{self, PathBuf};
use Options;
pub struct Path {
pub path: PathBuf,
pub metadata: Metadata,
}
pub struct PathLister<'a> {
options: &'a Options,
}
impl<'a> PathLister<'a> {
pub fn new(options: &'a Options) -> PathLister<'a> {
PathLister { options: options }
}
pub fn list_paths_to_print(&self, inputs: Vec<&'a str>) -> Vec<Path> {
let mut res = Vec::new();
for input in inputs.iter() {
let path = path::Path::new(input);
let res_meta = path.metadata();
if let Err(err) = res_meta {
match err.kind() {
ErrorKind::NotFound => println!("Specified path \"{}\" doesn't exists.", input),
ErrorKind::PermissionDenied => {
println!("Cannot open \"{}\": Permission denied", input)
}
_ => println!("Cannot open \"{}\": {}", input, err),
}
continue;
}
if let Ok(meta) = res_meta {
let file_type = meta.file_type();
if file_type.is_file() {
self.add_path_to_list(&mut res, path.to_path_buf(), meta);
continue;
}
if file_type.is_dir() {
self.read_paths_from_dir(&mut res, path.to_path_buf());
continue;
}
if file_type.is_symlink() {}
}
}
res
}
fn read_paths_from_dir(&self, path_list: &mut Vec<Path>, path: PathBuf) {
for entry in path.read_dir().expect("read_dir call failed") {
if let Ok(entry) = entry {
self.add_path_to_list(path_list, entry.path(), entry.metadata().unwrap());
}
}
}
fn add_path_to_list(&self, path_list: &mut Vec<Path>, path: PathBuf, meta: Metadata) {
// Skip the hidden files if the 'display_all' option is not set.
if path.file_name().unwrap().to_str().unwrap().starts_with(".") && !self.options.display_all
{
return;
}
path_list.push(Path {
path: path.to_path_buf(),
metadata: meta,
});
}
}

View file

@ -1,48 +0,0 @@
use formatter::*;
use path_lister::Path;
use Options;
pub struct Presenter<'a> {
formatter: Formatter,
options: &'a Options,
}
impl<'a> Presenter<'a> {
pub fn new(options: &'a Options) -> Presenter<'a> {
Presenter {
options: options,
formatter: Formatter::new(),
}
}
pub fn print(&self, paths: Vec<Path>) {
if self.options.display_long {
self.print_long(&paths);
return;
}
self.print_simple(&paths)
}
fn print_long(&self, paths: &Vec<Path>) {
for path in paths {
print!(
" {} {} {}\n",
self.formatter.format_permissions(path),
self.formatter.format_date(path),
self.formatter
.format_path(path.path.file_name().unwrap().to_str().unwrap(), &path)
);
}
}
fn print_simple(&self, paths: &Vec<Path>) {
for path in paths {
print!(
"{}\n",
self.formatter
.format_path(path.path.file_name().unwrap().to_str().unwrap(), &path)
);
}
}
}