Add the --recursive option

This commit is contained in:
Peltoche 2018-12-04 13:29:54 +01:00
parent 823b04a258
commit 8989ca44fe
No known key found for this signature in database
GPG key ID: CED68D0487156952
4 changed files with 44 additions and 16 deletions

View file

@ -2,6 +2,8 @@ use ansi_term::{ANSIString, ANSIStrings};
use meta::FileType; use meta::FileType;
use meta::Meta; use meta::Meta;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::iter::IntoIterator;
use std::vec::IntoIter;
pub struct Batch(Vec<Meta>); pub struct Batch(Vec<Meta>);
@ -11,6 +13,15 @@ impl From<Vec<Meta>> for Batch {
} }
} }
impl IntoIterator for Batch {
type Item = Meta;
type IntoIter = IntoIter<Meta>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl Batch { impl Batch {
pub fn sort(&mut self) { pub fn sort(&mut self) {
self.0.sort_unstable_by(sort_by_meta); self.0.sort_unstable_by(sort_by_meta);

View file

@ -1,7 +1,7 @@
use batch::Batch; use batch::Batch;
use display::Display; use display::Display;
use meta::Meta; use meta::{FileType, Meta};
use std::path::Path; use std::path::{Path, PathBuf};
use Options; use Options;
pub struct Core<'a> { pub struct Core<'a> {
@ -13,23 +13,19 @@ impl<'a> Core<'a> {
Core { options } Core { options }
} }
pub fn run(&self, inputs: Vec<&str>) { pub fn run(&self, paths: Vec<PathBuf>) {
let display = Display::new(self.options); let display = Display::new(self.options);
let mut dirs = Vec::new(); let mut dirs = Vec::new();
let mut files = Vec::new(); let mut files = Vec::new();
for input in inputs { for path in paths {
let path = Path::new(input);
if path.is_dir() { if path.is_dir() {
dirs.push(path); dirs.push(path);
} else { } else if let Some(meta) = Meta::from_path(&path) {
if let Some(meta) = Meta::from_path(path) {
files.push(meta); files.push(meta);
} }
} }
}
let print_folder_name: bool = dirs.len() + files.len() > 1; let print_folder_name: bool = dirs.len() + files.len() > 1;
@ -42,12 +38,26 @@ impl<'a> Core<'a> {
dirs.sort_unstable(); dirs.sort_unstable();
for dir in dirs { for dir in dirs {
if let Some(folder_batch) = self.list_folder_content(dir) { if let Some(folder_batch) = self.list_folder_content(dir.as_path()) {
if print_folder_name { if print_folder_name || self.options.recursive {
println!("\n{}:", dir.display()) println!("\n{}:", dir.display())
} }
display.print_outputs(self.get_batch_outputs(&folder_batch)); display.print_outputs(self.get_batch_outputs(&folder_batch));
if self.options.recursive {
let folder_dirs = folder_batch
.into_iter()
.filter_map(|x| {
if x.file_type == FileType::Directory {
Some(x.path)
} else {
None
}
}).collect();
self.run(folder_dirs);
}
} }
} }
} }
@ -73,7 +83,7 @@ impl<'a> Core<'a> {
for entry in dir { for entry in dir {
if let Ok(entry) = entry { if let Ok(entry) = entry {
if let Some(meta) = Meta::from_path(entry.path().as_path()) { if let Some(meta) = Meta::from_path(&entry.path()) {
if !meta.name.is_hidden() || self.options.display_all { if !meta.name.is_hidden() || self.options.display_all {
metas.push(meta); metas.push(meta);
} }

View file

@ -17,11 +17,13 @@ mod meta;
use clap::{App, Arg}; use clap::{App, Arg};
use core::Core; use core::Core;
use std::path::PathBuf;
pub struct Options { pub struct Options {
pub display_all: bool, pub display_all: bool,
pub display_long: bool, pub display_long: bool,
pub display_online: bool, pub display_online: bool,
pub recursive: bool,
} }
fn main() { fn main() {
@ -31,17 +33,20 @@ fn main() {
.arg(Arg::with_name("all").short("a").long("all")) .arg(Arg::with_name("all").short("a").long("all"))
.arg(Arg::with_name("long").short("l").long("long")) .arg(Arg::with_name("long").short("l").long("long"))
.arg(Arg::with_name("oneline").short("1").long("oneline")) .arg(Arg::with_name("oneline").short("1").long("oneline"))
.arg(Arg::with_name("recursive").short("R").long("recursive"))
.get_matches(); .get_matches();
let options = Options { let options = Options {
display_all: matches.is_present("all"), display_all: matches.is_present("all"),
display_long: matches.is_present("long"), display_long: matches.is_present("long"),
display_online: matches.is_present("oneline"), display_online: matches.is_present("oneline"),
recursive: matches.is_present("recursive"),
}; };
let inputs: Vec<&str> = matches let inputs = matches
.values_of("FILE") .values_of("FILE")
.expect("failed to retrieve cli value") .expect("failed to retrieve cli value")
.map(PathBuf::from)
.collect(); .collect();
let core = Core::new(&options); let core = Core::new(&options);

View file

@ -15,11 +15,12 @@ pub use self::size::Size;
pub use self::symlink::SymLink; pub use self::symlink::SymLink;
use std::fs::read_link; use std::fs::read_link;
use std::path::Path; use std::path::PathBuf;
#[derive(Debug)] #[derive(Debug)]
pub struct Meta { pub struct Meta {
pub name: Name, pub name: Name,
pub path: PathBuf,
pub permissions: Permissions, pub permissions: Permissions,
pub date: Date, pub date: Date,
pub owner: Owner, pub owner: Owner,
@ -29,7 +30,7 @@ pub struct Meta {
} }
impl Meta { impl Meta {
pub fn from_path(path: &Path) -> Option<Self> { pub fn from_path(path: &PathBuf) -> Option<Self> {
let mut metadata = match path.metadata() { let mut metadata = match path.metadata() {
Ok(res) => res, Ok(res) => res,
Err(err) => { Err(err) => {
@ -51,6 +52,7 @@ impl Meta {
} }
Some(Meta { Some(Meta {
path: path.to_path_buf(),
symlink: SymLink::from_path(&path), symlink: SymLink::from_path(&path),
size: Size::from(&metadata), size: Size::from(&metadata),
permissions: Permissions::from(&metadata), permissions: Permissions::from(&metadata),