main.rs 4.4 KB
Newer Older
B
Ben S 已提交
1
#![warn(trivial_casts, trivial_numeric_casts)]
B
Ben S 已提交
2
#![warn(unused_qualifications)]
3
#![warn(unused_results)]
B
Ben S 已提交
4

5
extern crate ansi_term;
6
extern crate datetime;
7
extern crate getopts;
8
extern crate libc;
9
extern crate locale;
10
extern crate natord;
B
Benjamin Sago 已提交
11
extern crate num_cpus;
12
extern crate number_prefix;
B
Ben S 已提交
13
extern crate scoped_threadpool;
B
Ben S 已提交
14
extern crate term_grid;
B
Ben S 已提交
15
extern crate unicode_width;
B
Ben S 已提交
16
extern crate users;
B
Ben S 已提交
17
extern crate zoneinfo_compiled;
B
Ben S 已提交
18

B
Ben S 已提交
19 20
#[cfg(feature="git")] extern crate git2;
#[macro_use] extern crate lazy_static;
B
Ben S 已提交
21

B
Ben S 已提交
22
use std::env;
B
Ben S 已提交
23
use std::path::{Component, Path};
24
use std::process;
B
Ben S 已提交
25

B
Ben S 已提交
26 27
use dir::Dir;
use file::File;
28
use options::{Options, View};
B
Ben S 已提交
29

30 31 32 33 34 35 36
mod dir;
mod feature;
mod file;
mod filetype;
mod options;
mod output;
mod term;
B
Ben S 已提交
37

B
Ben S 已提交
38

B
Ben S 已提交
39
struct Exa {
40 41
    options: Options,
}
B
Benjamin Sago 已提交
42

B
Ben S 已提交
43
impl Exa {
B
Ben S 已提交
44
    fn run(&mut self, mut args_file_names: Vec<String>) {
B
Ben S 已提交
45 46
        let mut files = Vec::new();
        let mut dirs = Vec::new();
B
bp 已提交
47

B
Ben S 已提交
48 49 50 51
        if args_file_names.is_empty() {
            args_file_names.push(".".to_owned());
        }

B
Ben S 已提交
52 53 54 55 56 57 58 59 60 61
        for file_name in args_file_names.iter() {
            match File::from_path(Path::new(&file_name), None) {
                Err(e) => {
                    println!("{}: {}", file_name, e);
                },
                Ok(f) => {
                    if f.is_directory() && !self.options.dir_action.treat_dirs_as_files() {
                        match f.to_dir(self.options.should_scan_for_git()) {
                            Ok(d) => dirs.push(d),
                            Err(e) => println!("{}: {}", file_name, e),
62 63
                        }
                    }
B
Ben S 已提交
64 65
                    else {
                        files.push(f);
66
                    }
B
Ben S 已提交
67
                },
B
Ben S 已提交
68 69
            }
        }
B
Ben S 已提交
70

B
Benjamin Sago 已提交
71
        let no_files = files.is_empty();
72 73
        let is_only_dir = dirs.len() == 1 && no_files;

B
Benjamin Sago 已提交
74 75 76
        if !no_files {
            self.print_files(None, files);
        }
B
Ben S 已提交
77

B
Benjamin Sago 已提交
78
        self.print_dirs(dirs, no_files, is_only_dir);
79
    }
80

B
Ben S 已提交
81 82
    fn print_dirs(&self, dir_files: Vec<Dir>, mut first: bool, is_only_dir: bool) {
        for dir in dir_files {
83 84 85 86 87 88 89 90 91 92

            // Put a gap between directories, or between the list of files and the
            // first directory.
            if first {
                first = false;
            }
            else {
                print!("\n");
            }

B
Ben S 已提交
93 94 95
            if !is_only_dir {
                println!("{}:", dir.path.display());
            }
B
Ben S 已提交
96

B
Ben S 已提交
97 98 99 100 101 102 103 104
            let mut children = Vec::new();
            for file in dir.files() {
                match file {
                    Ok(file)       => children.push(file),
                    Err((path, e)) => println!("[{}: {}]", path.display(), e),
                }
            };

105 106
            self.options.filter.filter_files(&mut children);
            self.options.filter.sort_files(&mut children);
B
Ben S 已提交
107 108 109 110

            if let Some(recurse_opts) = self.options.dir_action.recurse_options() {
                let depth = dir.path.components().filter(|&c| c != Component::CurDir).count() + 1;
                if !recurse_opts.tree && !recurse_opts.is_too_deep(depth) {
B
Ben S 已提交
111

B
Ben S 已提交
112 113 114 115 116
                    let mut child_dirs = Vec::new();
                    for child_dir in children.iter().filter(|f| f.is_directory()) {
                        match child_dir.to_dir(false) {
                            Ok(d)  => child_dirs.push(d),
                            Err(e) => println!("{}: {}", child_dir.path.display(), e),
117
                        }
B
Ben S 已提交
118 119
                    }

B
Ben S 已提交
120 121 122 123
                    self.print_files(Some(&dir), children);

                    if !child_dirs.is_empty() {
                        self.print_dirs(child_dirs, false, false);
124 125
                    }

B
Ben S 已提交
126
                    continue;
127
                }
B
Ben S 已提交
128 129 130 131
            }

            self.print_files(Some(&dir), children);

132 133
        }
    }
134

B
Ben S 已提交
135
    fn print_files(&self, dir: Option<&Dir>, files: Vec<File>) {
136
        match self.options.view {
B
Ben S 已提交
137
            View::Grid(g)         => g.view(&files),
B
Ben S 已提交
138
            View::Details(d)      => d.view(dir, files),
139 140
            View::GridDetails(gd) => gd.view(dir, files),
            View::Lines(l)        => l.view(files),
141
        }
142
    }
143
}
144

B
Ben S 已提交
145

146
fn main() {
B
Ben S 已提交
147
    let args: Vec<String> = env::args().skip(1).collect();
148

B
Ben S 已提交
149
    match Options::getopts(&args) {
150
        Ok((options, paths)) => {
151
            let mut exa = Exa { options: options };
B
Ben S 已提交
152
            exa.run(paths);
153
        },
154
        Err(e) => {
155
            println!("{}", e);
156
            process::exit(e.error_code());
157
        },
158 159
    };
}