summaryrefslogtreecommitdiffstats
path: root/src/meta/name.rs
blob: 2048a37e01ba87eaf5a829e1caad730a8e692e52 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use color::{ColoredString, Colors, Elem};
use meta::filetype::FileType;
use std::cmp::{Ordering, PartialOrd};
use std::path::Path;

#[derive(Debug, Eq)]
pub struct Name {
    name: String,
    extension: Option<String>,
    file_type: FileType,
}

impl Name {
    pub fn new(path: &Path, file_type: FileType) -> Self {
        let mut name = path
            .file_name()
            .expect("failed to retrieve file name")
            .to_string_lossy()
            .to_string();

        if file_type == FileType::Directory {
            name.push('/')
        }

        let mut extension = None;
        if let Some(res) = path.extension() {
            extension = Some(
                res.to_str()
                    .expect("failed to encode file name")
                    .to_string(),
            );
        }

        Name {
            name,
            extension,
            file_type,
        }
    }

    pub fn render(&self, colors: &Colors) -> ColoredString {
        let mut content = String::with_capacity(self.name.len() + 3 /* spaces */);

        let elem = match self.file_type {
            FileType::Directory => &Elem::Dir,
            FileType::SymLink => &Elem::SymLink,
            _ => &Elem::File,
        };

        content += &self.name;

        colors.colorize(content, elem)
    }

    pub fn name(&self) -> String {
        self.name.clone()
    }

    pub fn extension(&self) -> Option<String> {
        self.extension.clone()
    }

    pub fn file_type(&self) -> FileType {
        self.file_type
    }

    pub fn is_hidden(&self) -> bool {
        self.name.starts_with('.')
    }
}

impl Ord for Name {
    fn cmp(&self, other: &Name) -> Ordering {
        self.name.cmp(&other.name)
    }
}

impl PartialOrd for Name {
    fn partial_cmp(&self, other: &Name) -> Option<Ordering> {
        Some(self.name.cmp(&other.name))
    }
}

impl PartialEq for Name {
    fn eq(&self, other: &Name) -> bool {
        let mut other_name = other.name.chars();

        if self.name.len() != other.name.len() {
            return false;
        }

        for c in self.name.chars() {
            if let Some(c2) = other_name.next() {
                if c != c2 {
                    return false;
                }
            } else {
                return false;
            }
        }

        true
    }
}