Create the Batch struct

This commit is contained in:
Peltoche 2018-12-02 15:05:27 +01:00
parent e4f08321a5
commit 2d6627ce7f
No known key found for this signature in database
GPG key ID: CED68D0487156952
4 changed files with 151 additions and 137 deletions

2
Cargo.lock generated
View file

@ -47,7 +47,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lsd"
version = "0.4.0"
version = "0.4.1-pre"
dependencies = [
"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)",

124
src/batch.rs Normal file
View file

@ -0,0 +1,124 @@
use meta::FileType;
use meta::Meta;
use std::cmp::Ordering;
use term_grid::{Cell, Direction, Filling, Grid, GridOptions};
use terminal_size::terminal_size;
pub struct Batch(Vec<Meta>);
impl From<Vec<Meta>> for Batch {
fn from(metas: Vec<Meta>) -> Self {
Batch(metas)
}
}
impl Batch {
pub fn sort(&mut self) {
self.0.sort_unstable_by(sort_by_meta);
}
pub fn print_short(&self) {
let term_width = match terminal_size() {
Some((w, _)) => w.0 as usize,
None => panic!("failed to retrieve terminal size"),
};
let mut grid = Grid::new(GridOptions {
filling: Filling::Spaces(1),
direction: Direction::LeftToRight,
});
for meta in &self.0 {
let mut content = String::from(" ");
content += &meta.name.render();
grid.add(Cell {
width: content.len(),
contents: content,
});
}
println!(
"{}",
grid.fit_into_width(term_width * 2)
.expect("failed to print the grid")
);
}
pub fn print_long(&self) {
let max_user_length = self.detect_user_lenght();
let max_group_length = self.detect_group_lenght();
let (max_size_value_length, max_size_unit_length) = self.detect_size_lenghts();
for meta in &self.0 {
let mut link_str = String::new();
if let Some(ref symlink) = meta.symlink {
link_str = symlink.render();
}
println!(
"{}{} {} {} {} {}{}",
meta.file_type.render(),
meta.permissions.render(),
meta.owner.render(max_user_length, max_group_length),
meta.size
.render(max_size_value_length, max_size_unit_length),
meta.date.render(),
meta.name.render(),
link_str,
);
}
}
fn detect_user_lenght(&self) -> usize {
let mut max: usize = 0;
for meta in &self.0 {
let user = meta.owner.render_user();
if user.len() > max {
max = user.len();
}
}
max
}
fn detect_group_lenght(&self) -> usize {
let mut max: usize = 0;
for meta in &self.0 {
let group = meta.owner.render_group();
if group.len() > max {
max = group.len();
}
}
max
}
fn detect_size_lenghts(&self) -> (usize, usize) {
let mut max_value_length: usize = 0;
let mut max_unit_size: usize = 0;
for meta in &self.0 {
if meta.size.render_value().len() > max_value_length {
max_value_length = meta.size.render_value().len();
}
if meta.size.render_unit().len() > max_unit_size {
max_unit_size = meta.size.render_unit().len();
}
}
(max_value_length, max_unit_size)
}
}
fn sort_by_meta(a: &Meta, b: &Meta) -> Ordering {
if a.file_type == FileType::Directory && b.file_type != FileType::Directory {
Ordering::Less
} else if b.file_type == FileType::Directory && a.file_type != FileType::Directory {
Ordering::Greater
} else {
a.name.cmp(&b.name)
}
}

View file

@ -1,8 +1,6 @@
use meta::{FileType, Meta};
use std::cmp::Ordering;
use batch::Batch;
use meta::Meta;
use std::path::Path;
use term_grid::{Cell, Direction, Filling, Grid, GridOptions};
use terminal_size::terminal_size;
use Options;
pub struct Core<'a> {
@ -15,8 +13,6 @@ impl<'a> Core<'a> {
}
pub fn run(&self, inputs: Vec<&str>) {
let print_folder_name: bool = inputs.len() > 1;
let mut dirs = Vec::new();
let mut files = Vec::new();
@ -28,101 +24,46 @@ impl<'a> Core<'a> {
} else if path.is_file() {
files.push(Meta::from(path));
} else {
match path.metadata() {
Ok(_) => panic!("shouldn't failed"),
Err(err) => println!("cannot access '{}': {}", path.display(), err),
};
let err = path.metadata().unwrap_err();
println!("cannot access '{}': {}", path.display(), err);
}
}
files.sort_unstable_by(sort_by_meta);
let print_folder_name: bool = dirs.len() + files.len() > 1;
let mut file_batch = Batch::from(files);
file_batch.sort();
self.print(&file_batch);
dirs.sort_unstable();
if !files.is_empty() {
self.print(&files);
}
for dir in dirs {
let folder_metas = self.list_folder_content(dir);
if folder_metas.is_empty() {
continue;
}
if let Some(folder_batch) = self.list_folder_content(dir) {
if print_folder_name {
println!("\n{}:", dir.display())
}
if print_folder_name {
println!("\n{}:", dir.display())
self.print(&folder_batch);
}
self.print(&folder_metas);
}
}
fn print(&self, metas: &[Meta]) {
pub fn print<'b>(&self, batch: &'b Batch) {
if self.options.display_long {
self.print_long(metas)
batch.print_long();
} else {
self.print_short(metas)
batch.print_short();
}
}
fn print_short(&self, metas: &[Meta]) {
let term_width = match terminal_size() {
Some((w, _)) => w.0 as usize,
None => panic!("failed to retrieve terminal size"),
};
let mut grid = Grid::new(GridOptions {
filling: Filling::Spaces(1),
direction: Direction::LeftToRight,
});
for meta in metas {
let mut content = String::from(" ");
content += &meta.name.render();
grid.add(Cell {
width: content.len(),
contents: content,
});
}
println!(
"{}",
grid.fit_into_width(term_width * 2)
.expect("failed to print the grid")
);
}
fn print_long(&self, metas: &[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 {
let mut link_str = String::new();
if let Some(ref symlink) = meta.symlink {
link_str = symlink.render();
}
println!(
"{}{} {} {} {} {}{}",
meta.file_type.render(),
meta.permissions.render(),
meta.owner.render(max_user_length, max_group_length),
meta.size
.render(max_size_value_length, max_size_unit_length),
meta.date.render(),
meta.name.render(),
link_str,
);
}
}
pub fn list_folder_content(&self, folder: &Path) -> Vec<Meta> {
let mut content: Vec<Meta> = Vec::new();
pub fn list_folder_content(&self, folder: &Path) -> Option<Batch> {
let mut metas: Vec<Meta> = Vec::new();
let dir = match folder.read_dir() {
Ok(dir) => dir,
Err(err) => {
println!("cannot open directory'{}': {}", folder.display(), err);
return content;
return None;
}
};
@ -130,66 +71,14 @@ impl<'a> Core<'a> {
if let Ok(entry) = entry {
let meta = Meta::from(entry.path().as_path());
if !meta.name.is_hidden() || self.options.display_all {
content.push(meta);
metas.push(meta);
}
}
}
content.sort_unstable_by(sort_by_meta);
let mut batch = Batch::from(metas);
batch.sort();
content
}
fn detect_user_lenght(&self, metas: &[Meta]) -> usize {
let mut max: usize = 0;
for meta in metas {
let user = meta.owner.render_user();
if user.len() > max {
max = user.len();
}
}
max
}
fn detect_group_lenght(&self, metas: &[Meta]) -> usize {
let mut max: usize = 0;
for meta in metas {
let group = meta.owner.render_group();
if group.len() > max {
max = group.len();
}
}
max
}
fn detect_size_lenghts(&self, metas: &[Meta]) -> (usize, usize) {
let mut max_value_length: usize = 0;
let mut max_unit_size: usize = 0;
for meta in metas {
if meta.size.render_value().len() > max_value_length {
max_value_length = meta.size.render_value().len();
}
if meta.size.render_unit().len() > max_unit_size {
max_unit_size = meta.size.render_unit().len();
}
}
(max_value_length, max_unit_size)
}
}
fn sort_by_meta(a: &Meta, b: &Meta) -> Ordering {
if a.file_type == FileType::Directory && b.file_type != FileType::Directory {
Ordering::Less
} else if b.file_type == FileType::Directory && a.file_type != FileType::Directory {
Ordering::Greater
} else {
a.name.cmp(&b.name)
Some(batch)
}
}

View file

@ -8,6 +8,7 @@ extern crate terminal_size;
extern crate time;
extern crate users;
mod batch;
mod color;
mod core;
mod icon;