options.rs 3.7 KB
Newer Older
B
Ben S 已提交
1 2
extern crate getopts;

B
Ben S 已提交
3
use file::File;
B
Ben S 已提交
4
use std::cmp::lexical_ordering;
B
Ben S 已提交
5
use column::{Column, Permissions, FileName, FileSize, User, Group, HardLinks, Inode, Blocks};
B
Ben S 已提交
6
use std::ascii::StrAsciiExt;
B
Ben S 已提交
7 8

pub enum SortField {
B
Ben S 已提交
9
    Name, Extension, Size
B
Ben S 已提交
10 11 12 13 14
}

pub struct Options {
    pub showInvisibles: bool,
    pub sortField: SortField,
B
Ben S 已提交
15
    pub reverse: bool,
B
Ben S 已提交
16
    pub dirs: Vec<String>,
B
Ben S 已提交
17
    pub columns: Vec<Column>,
B
Ben S 已提交
18
    pub header: bool,
B
Ben S 已提交
19 20 21
}

impl SortField {
22
    fn from_word(word: String) -> SortField {
B
Ben S 已提交
23 24 25
        match word.as_slice() {
            "name" => Name,
            "size" => Size,
B
Ben S 已提交
26 27
            "ext"  => Extension,
            _      => fail!("Invalid sorting order"),
B
Ben S 已提交
28 29 30 31 32
        }
    }
}

impl Options {
B
Ben S 已提交
33
    pub fn getopts(args: Vec<String>) -> Result<Options, getopts::Fail_> {
B
Ben S 已提交
34
        let opts = [
B
Ben S 已提交
35
            getopts::optflag("a", "all", "show dot-files"),
B
Ben S 已提交
36
            getopts::optflag("b", "binary", "use binary prefixes in file sizes"),
B
Ben S 已提交
37
            getopts::optflag("g", "group", "show group as well as user"),
B
Ben S 已提交
38
            getopts::optflag("h", "header", "show a header row at the top"),
B
Ben S 已提交
39
            getopts::optflag("i", "inode", "show each file's inode number"),
B
Ben S 已提交
40
            getopts::optflag("l", "links", "show number of hard links"),
B
Ben S 已提交
41 42
            getopts::optflag("r", "reverse", "reverse order of files"),
            getopts::optopt("s", "sort", "field to sort by", "WORD"),
B
Ben S 已提交
43
            getopts::optflag("S", "blocks", "show number of file system blocks"),
B
Ben S 已提交
44 45 46 47 48 49 50
        ];

        match getopts::getopts(args.tail(), opts) {
            Err(f) => Err(f),
            Ok(matches) => Ok(Options {
                showInvisibles: matches.opt_present("all"),
                reverse: matches.opt_present("reverse"),
B
Ben S 已提交
51
                header: matches.opt_present("header"),
B
Ben S 已提交
52
                sortField: matches.opt_str("sort").map(|word| SortField::from_word(word)).unwrap_or(Name),
53
                dirs: if matches.free.is_empty() { vec![ ".".to_string() ] } else { matches.free.clone() },
B
Ben S 已提交
54
                columns: Options::columns(matches),
B
Ben S 已提交
55 56 57 58
            })
        }
    }

B
Ben S 已提交
59
    fn columns(matches: getopts::Matches) -> Vec<Column> {
B
Ben S 已提交
60 61 62 63 64 65 66
        let mut columns = vec![];

        if matches.opt_present("inode") {
            columns.push(Inode);
        }

        columns.push(Permissions);
B
Ben S 已提交
67 68 69 70 71 72

        if matches.opt_present("links") {
            columns.push(HardLinks);
        }
        
        columns.push(FileSize(matches.opt_present("binary")));
B
Ben S 已提交
73 74 75 76 77

        if matches.opt_present("blocks") {
            columns.push(Blocks);
        }

B
Ben S 已提交
78
        columns.push(User);
B
Ben S 已提交
79 80 81 82 83 84 85 86

        if matches.opt_present("group") {
            columns.push(Group);
        }

        columns.push(FileName);

        return columns;
B
Ben S 已提交
87 88
    }

B
Ben S 已提交
89
    fn should_display(&self, f: &File) -> bool {
B
Ben S 已提交
90 91 92
        if self.showInvisibles {
            true
        } else {
B
Ben S 已提交
93
            !f.name.as_slice().starts_with(".")
B
Ben S 已提交
94 95
        }
    }
B
Ben S 已提交
96

B
Ben S 已提交
97 98
    pub fn transform_files<'a>(&self, unordered_files: &'a Vec<File<'a>>) -> Vec<&'a File<'a>> {
        let mut files: Vec<&'a File<'a>> = unordered_files.iter()
B
Ben S 已提交
99
            .filter(|&f| self.should_display(f))
B
Ben S 已提交
100
            .collect();
101 102

        match self.sortField {
B
Ben S 已提交
103
            Name => files.sort_by(|a, b| a.parts.cmp(&b.parts)),
104 105
            Size => files.sort_by(|a, b| a.stat.size.cmp(&b.stat.size)),
            Extension => files.sort_by(|a, b| {
B
Ben S 已提交
106 107
                let exts = a.ext.clone().map(|e| e.as_slice().to_ascii_lower()).cmp(&b.ext.clone().map(|e| e.as_slice().to_ascii_lower()));
                let names = a.name.as_slice().to_ascii_lower().cmp(&b.name.as_slice().to_ascii_lower());
108 109 110 111 112 113 114 115 116 117
                lexical_ordering(exts, names)
            }),
        }

        if self.reverse {
            files.reverse();
        }

        return files;
    }
B
Ben S 已提交
118
}