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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use std::fmt;
use std::path::Path;

use ignore::overrides::OverrideBuilder;
use termion::color::{self, Color};

pub struct RenderOptions {
    pub fg_color: Box<Color>,
    pub bg_color: Box<Color>,
}

impl fmt::Debug for RenderOptions {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{{ fg_color: ?, bg_color: ? }}")
    }
}

impl RenderOptions {
    pub fn new() -> Self {
        Self {
            fg_color: Box::new(color::White),
            bg_color: Box::new(color::Blue),
        }
    }

    pub fn fg_color(&mut self, color: Box<Color>) -> &mut Self {
        self.fg_color = color;
        self
    }

    pub fn bg_color(&mut self, color: Box<Color>) -> &mut Self {
        self.bg_color = color;
        self
    }
}

pub fn validate_ignore(pat: &str) -> Result<(), String> {
    OverrideBuilder::new(".")
        .add(pat)
        .map(|_| {})
        .map_err(|e| format!("Error parsing ignore: {:?}", e))
}

#[derive(Debug)]
pub struct FsOptions<P: AsRef<Path>> {
    pub root: P,
    pub max_depth: Option<usize>,
    pub follow_links: bool,
    pub max_filesize: Option<u64>,
    pub hidden: bool,
    pub only_dirs: bool,
    pub no_ignore: bool,
    pub no_git_exclude: bool,
    pub custom_ignore: Vec<String>,
}

impl<P: AsRef<Path>> FsOptions<P> {
    pub fn new(root: P) -> Self {
        Self {
            root,
            max_depth: None,
            follow_links: false,
            max_filesize: None,
            hidden: true,
            only_dirs: false,
            no_ignore: true,
            no_git_exclude: true,
            custom_ignore: Vec::new(),
        }
    }

    /// Set the root directory from which to build the tree.
    pub fn root(&mut self, root: P) -> &mut Self {
        self.root = root;
        self
    }

    /// Set a maximum depth for the tree to search. `None` indicates no limit.
    ///
    /// `None` by default.
    pub fn max_depth(&mut self, max_depth: Option<usize>) -> &mut Self {
        self.max_depth = max_depth;
        self
    }

    /// Set whether or not to follow links.
    ///
    /// Disabled by default.
    pub fn follow_links(&mut self, follow_links: bool) -> &mut Self {
        self.follow_links = follow_links;
        self
    }

    /// Set a maximum file size to include. `None` indicates no limit.
    ///
    /// `None` by default.
    pub fn max_filesize(&mut self, max_filesize: Option<u64>) -> &mut Self {
        self.max_filesize = max_filesize;
        self
    }

    /// Set whether or not to ignore hidden files.
    ///
    /// Enabled by default.
    pub fn hidden(&mut self, hidden: bool) -> &mut Self {
        self.hidden = hidden;
        self
    }

    /// Set whether or not to consider directories only.
    ///
    /// Disabled by default.
    pub fn only_dirs(&mut self, only_dirs: bool) -> &mut Self {
        self.only_dirs = only_dirs;
        self
    }

    /// Set whether or not to read `.[git]ignore` files.
    ///
    /// Enabled by default.
    pub fn no_ignore(&mut self, no_ignore: bool) -> &mut Self {
        self.no_ignore = no_ignore;
        self
    }

    /// Set whether or not to read `.git/info/exclude` files.
    ///
    /// Enabled by default.
    pub fn no_git_exclude(&mut self, no_git_exclude: bool) -> &mut Self {
        self.no_git_exclude = no_git_exclude;
        self
    }

    /// Add a custom ignore path.
    pub fn add_custom_ignore(&mut self, path: &str) -> &mut Self {
        self.custom_ignore.push(path.to_owned());
        self
    }
}