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
use std::{
    io::{self, stdout, Write},
    path::Path,
    sync::{Arc, Mutex},
};

use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor};

#[derive(Debug)]
pub struct Match<'a> {
    pub col: Vec<usize>,
    pub path: &'a [u8],
}

pub fn scan_print_end(path: &Path, pat: &[u8], pat_len: usize) {
    let bw = BufferWriter::stdout(ColorChoice::Always);
    let b = Arc::new(Mutex::new(bw.buffer()));
    for entry in jwalk::WalkDir::new(Path::new(path)) {
        let entry = match entry {
            Ok(e) => e,
            _ => continue,
        };
        let path = entry.path();
        let path = path.to_str().unwrap_or("").as_bytes();
        let path_len = path.len();
        if pat_len > path_len {
            continue;
        }
        let mut col: Vec<usize> = Vec::new();
        let mut i = 0;
        while i <= path_len - pat_len {
            if &path[i..i + pat_len] == pat {
                col.push(i + 1);
            }
            i += 1;
        }
        if col.is_empty() {
            continue;
        }
        let _ = write_match(Match { col, path }, pat_len, &b);
    }
    bw.print(&b.lock().unwrap()).unwrap();
}

pub fn scan_print(path: &Path, pat: &[u8], pat_len: usize) {
    for entry in jwalk::WalkDir::new(Path::new(path)) {
        let entry = match entry {
            Ok(e) => e,
            _ => continue,
        };
        let path = entry.path();
        let path = path.to_str().unwrap_or("").as_bytes();
        let path_len = path.len();
        if pat_len > path_len {
            continue;
        }
        let mut col: Vec<usize> = Vec::new();
        let mut i = 0;
        while i <= path_len - pat_len {
            if &path[i..i + pat_len] == pat {
                col.push(i + 1);
            }
            i += 1;
        }
        if col.is_empty() {
            continue;
        }
        let _ = print_match(Match { col, path }, pat_len);
    }
}

pub fn print_all_paths(path: &Path) {
    let mut handle = stdout().lock();
    for entry in jwalk::WalkDir::new(Path::new(path)) {
        let entry = match entry {
            Ok(e) => e,
            _ => continue,
        };
        let path = entry.path();
        let path = match path.to_str() {
            Some(p) => p,
            _ => continue,
        };
        let _ = writeln!(handle, "{}", path);
    }
}

pub fn write_match(m: Match, pat_len: usize, b: &Arc<Mutex<termcolor::Buffer>>) -> io::Result<()> {
    let mut binding = ColorSpec::new();
    let red = binding.set_fg(Some(Color::Red));
    let mut b = b.lock().unwrap();
    let mut j = 0;
    for i in m.col.iter() {
        let col = i - 1;
        b.write(&m.path[j..col])?;
        b.set_color(&red)?;
        b.write(&m.path[col..col + pat_len])?;
        b.reset()?;
        j = col + pat_len;
    }
    b.write(&m.path[m.col[m.col.len() - 1] - 1 + pat_len..])?;
    write!(b, "\n")?;

    Ok(())
}

pub fn print_match(m: Match, pat_len: usize) -> io::Result<()> {
    let mut binding = ColorSpec::new();
    let red = binding.set_fg(Some(Color::Red));
    let bw = BufferWriter::stdout(ColorChoice::Always);
    let mut b = bw.buffer();
    let mut j = 0;
    for i in m.col.iter() {
        let col = i - 1;
        b.write(&m.path[j..col])?;
        b.set_color(&red)?;
        b.write(&m.path[col..col + pat_len])?;
        b.reset()?;
        j = col + pat_len;
    }
    b.write(&m.path[m.col[m.col.len() - 1] - 1 + pat_len..])?;
    write!(b, "\n")?;
    bw.print(&b).unwrap();

    Ok(())
}