|
|
@@ -25,37 +25,24 @@ pub mod output;
|
|
|
pub mod term;
|
|
|
|
|
|
fn exa(options: &Options) {
|
|
|
- let mut dirs: Vec<String> = vec![];
|
|
|
+ let mut dirs: Vec<Path> = vec![];
|
|
|
let mut files: Vec<File> = vec![];
|
|
|
|
|
|
// It's only worth printing out directory names if the user supplied
|
|
|
// more than one of them.
|
|
|
let mut count = 0;
|
|
|
|
|
|
- let mut stack = options.path_strs.clone();
|
|
|
-
|
|
|
// Separate the user-supplied paths into directories and files.
|
|
|
// Files are shown first, and then each directory is expanded
|
|
|
// and listed second.
|
|
|
- loop {
|
|
|
- let file = match stack.pop() {
|
|
|
- None => break,
|
|
|
- Some(f) => f,
|
|
|
- };
|
|
|
-
|
|
|
- let path = Path::new(file.clone());
|
|
|
+ for file in options.path_strs.iter() {
|
|
|
+ let path = Path::new(file);
|
|
|
match fs::stat(&path) {
|
|
|
Ok(stat) => {
|
|
|
- if stat.kind == FileType::Directory {
|
|
|
- match options.dir_action {
|
|
|
- DirAction::AsFile => files.push(File::with_stat(stat, &path, None)),
|
|
|
- DirAction::List => dirs.push(file.clone()),
|
|
|
- DirAction::Recurse => { /* todo */ },
|
|
|
- }
|
|
|
+ if stat.kind == FileType::Directory && options.dir_action != DirAction::AsFile {
|
|
|
+ dirs.push(path);
|
|
|
}
|
|
|
else {
|
|
|
- // May as well reuse the stat result from earlier
|
|
|
- // instead of just using File::from_path().
|
|
|
files.push(File::with_stat(stat, &path, None));
|
|
|
}
|
|
|
}
|
|
|
@@ -68,10 +55,19 @@ fn exa(options: &Options) {
|
|
|
let mut first = files.is_empty();
|
|
|
|
|
|
if !files.is_empty() {
|
|
|
- options.view(None, files);
|
|
|
+ options.view(None, &files[]);
|
|
|
}
|
|
|
|
|
|
- for dir_name in dirs.iter() {
|
|
|
+ // Directories are put on a stack rather than just being iterated through,
|
|
|
+ // as the vector can change as more directories are added.
|
|
|
+ loop {
|
|
|
+ let dir_path = match dirs.pop() {
|
|
|
+ None => break,
|
|
|
+ Some(f) => f,
|
|
|
+ };
|
|
|
+
|
|
|
+ // Put a gap between directories, or between the list of files and the
|
|
|
+ // first directory.
|
|
|
if first {
|
|
|
first = false;
|
|
|
}
|
|
|
@@ -79,19 +75,30 @@ fn exa(options: &Options) {
|
|
|
print!("\n");
|
|
|
}
|
|
|
|
|
|
- match Dir::readdir(Path::new(dir_name.clone())) {
|
|
|
+ match Dir::readdir(&dir_path) {
|
|
|
Ok(ref dir) => {
|
|
|
let unsorted_files = dir.files();
|
|
|
let files: Vec<File> = options.transform_files(unsorted_files);
|
|
|
|
|
|
+ // When recursing, add any directories to the dirs stack
|
|
|
+ // backwards: the *last* element of the stack is used each
|
|
|
+ // time, so by inserting them backwards, they get displayed in
|
|
|
+ // the correct sort order.
|
|
|
+ if options.dir_action == DirAction::Recurse {
|
|
|
+ for dir in files.iter().filter(|f| f.stat.kind == FileType::Directory).rev() {
|
|
|
+ dirs.push(dir.path.clone());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if count > 1 {
|
|
|
- println!("{}:", dir_name);
|
|
|
+ println!("{}:", dir_path.display());
|
|
|
}
|
|
|
+ count += 1;
|
|
|
|
|
|
- options.view(Some(dir), files);
|
|
|
+ options.view(Some(dir), &files[]);
|
|
|
}
|
|
|
Err(e) => {
|
|
|
- println!("{}: {}", dir_name, e);
|
|
|
+ println!("{}: {}", dir_path.display(), e);
|
|
|
return;
|
|
|
}
|
|
|
};
|