|
@@ -20,10 +20,15 @@ use self::Misfire::*;
|
|
|
pub struct Options {
|
|
pub struct Options {
|
|
|
pub dir_action: DirAction,
|
|
pub dir_action: DirAction,
|
|
|
pub path_strs: Vec<String>,
|
|
pub path_strs: Vec<String>,
|
|
|
|
|
+ pub filter: FileFilter,
|
|
|
|
|
+ view: View,
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#[derive(PartialEq, Debug, Copy)]
|
|
|
|
|
+pub struct FileFilter {
|
|
|
reverse: bool,
|
|
reverse: bool,
|
|
|
show_invisibles: bool,
|
|
show_invisibles: bool,
|
|
|
sort_field: SortField,
|
|
sort_field: SortField,
|
|
|
- view: View,
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl Options {
|
|
impl Options {
|
|
@@ -45,6 +50,7 @@ impl Options {
|
|
|
getopts::optflag("R", "recurse", "recurse into directories"),
|
|
getopts::optflag("R", "recurse", "recurse into directories"),
|
|
|
getopts::optopt ("s", "sort", "field to sort by", "WORD"),
|
|
getopts::optopt ("s", "sort", "field to sort by", "WORD"),
|
|
|
getopts::optflag("S", "blocks", "show number of file system blocks"),
|
|
getopts::optflag("S", "blocks", "show number of file system blocks"),
|
|
|
|
|
+ getopts::optflag("T", "tree", "recurse into subdirectories in a tree view"),
|
|
|
getopts::optflag("x", "across", "sort multi-column view entries across"),
|
|
getopts::optflag("x", "across", "sort multi-column view entries across"),
|
|
|
getopts::optflag("?", "help", "show list of command-line options"),
|
|
getopts::optflag("?", "help", "show list of command-line options"),
|
|
|
];
|
|
];
|
|
@@ -64,20 +70,28 @@ impl Options {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
Ok(Options {
|
|
Ok(Options {
|
|
|
- dir_action: try!(dir_action(&matches)),
|
|
|
|
|
- path_strs: if matches.free.is_empty() { vec![ ".".to_string() ] } else { matches.free.clone() },
|
|
|
|
|
- reverse: matches.opt_present("reverse"),
|
|
|
|
|
- show_invisibles: matches.opt_present("all"),
|
|
|
|
|
- sort_field: sort_field,
|
|
|
|
|
- view: try!(view(&matches)),
|
|
|
|
|
|
|
+ dir_action: try!(dir_action(&matches)),
|
|
|
|
|
+ path_strs: if matches.free.is_empty() { vec![ ".".to_string() ] } else { matches.free.clone() },
|
|
|
|
|
+ view: try!(view(&matches)),
|
|
|
|
|
+ filter: FileFilter {
|
|
|
|
|
+ reverse: matches.opt_present("reverse"),
|
|
|
|
|
+ show_invisibles: matches.opt_present("all"),
|
|
|
|
|
+ sort_field: sort_field,
|
|
|
|
|
+ },
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ pub fn transform_files<'a>(&self, files: Vec<File<'a>>) -> Vec<File<'a>> {
|
|
|
|
|
+ self.filter.transform_files(files)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/// Display the files using this Option's View.
|
|
/// Display the files using this Option's View.
|
|
|
- pub fn view(&self, dir: Option<&Dir>, files: &[File]) {
|
|
|
|
|
- self.view.view(dir, files)
|
|
|
|
|
|
|
+ pub fn view(&self, dir: Option<&Dir>, files: &[File], filter: FileFilter) {
|
|
|
|
|
+ self.view.view(dir, files, filter)
|
|
|
}
|
|
}
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
+impl FileFilter {
|
|
|
/// Transform the files (sorting, reversing, filtering) before listing them.
|
|
/// Transform the files (sorting, reversing, filtering) before listing them.
|
|
|
pub fn transform_files<'a>(&self, mut files: Vec<File<'a>>) -> Vec<File<'a>> {
|
|
pub fn transform_files<'a>(&self, mut files: Vec<File<'a>>) -> Vec<File<'a>> {
|
|
|
|
|
|
|
@@ -111,7 +125,7 @@ impl Options {
|
|
|
/// What to do when encountering a directory?
|
|
/// What to do when encountering a directory?
|
|
|
#[derive(PartialEq, Debug, Copy)]
|
|
#[derive(PartialEq, Debug, Copy)]
|
|
|
pub enum DirAction {
|
|
pub enum DirAction {
|
|
|
- AsFile, List, Recurse
|
|
|
|
|
|
|
+ AsFile, List, Recurse, Tree
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// User-supplied field to sort by.
|
|
/// User-supplied field to sort by.
|
|
@@ -189,7 +203,7 @@ fn view(matches: &getopts::Matches) -> Result<View, Misfire> {
|
|
|
Err(Misfire::Useless("oneline", true, "long"))
|
|
Err(Misfire::Useless("oneline", true, "long"))
|
|
|
}
|
|
}
|
|
|
else {
|
|
else {
|
|
|
- Ok(View::Details(try!(Columns::new(matches)), matches.opt_present("header")))
|
|
|
|
|
|
|
+ Ok(View::Details(try!(Columns::new(matches)), matches.opt_present("header"), matches.opt_present("tree")))
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
else if matches.opt_present("binary") {
|
|
else if matches.opt_present("binary") {
|
|
@@ -242,12 +256,14 @@ fn file_size(matches: &getopts::Matches) -> Result<SizeFormat, Misfire> {
|
|
|
fn dir_action(matches: &getopts::Matches) -> Result<DirAction, Misfire> {
|
|
fn dir_action(matches: &getopts::Matches) -> Result<DirAction, Misfire> {
|
|
|
let recurse = matches.opt_present("recurse");
|
|
let recurse = matches.opt_present("recurse");
|
|
|
let list = matches.opt_present("list-dirs");
|
|
let list = matches.opt_present("list-dirs");
|
|
|
|
|
+ let tree = matches.opt_present("tree");
|
|
|
|
|
|
|
|
- match (recurse, list) {
|
|
|
|
|
- (true, true ) => Err(Misfire::Conflict("recurse", "list-dirs")),
|
|
|
|
|
- (true, false) => Ok(DirAction::Recurse),
|
|
|
|
|
- (false, true ) => Ok(DirAction::AsFile),
|
|
|
|
|
- (false, false) => Ok(DirAction::List),
|
|
|
|
|
|
|
+ match (recurse, list, tree) {
|
|
|
|
|
+ (true, true, _ ) => Err(Misfire::Conflict("recurse", "list-dirs")),
|
|
|
|
|
+ (true, false, false) => Ok(DirAction::Recurse),
|
|
|
|
|
+ (true, false, true ) => Ok(DirAction::Tree),
|
|
|
|
|
+ (false, true, _ ) => Ok(DirAction::AsFile),
|
|
|
|
|
+ (false, false, _ ) => Ok(DirAction::List),
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -304,7 +320,6 @@ impl Columns {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- columns.push(FileName);
|
|
|
|
|
columns
|
|
columns
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|