normalize_punctuation/
walk.rs

1use std::path::Path;
2
3use ignore::{self, DirEntry, WalkBuilder, WalkState};
4
5pub fn find_files_recursively(
6    root: impl AsRef<Path>,
7    extensions: &[&str],
8    f: impl Fn(&Path) + Sync,
9) {
10    let does_entry_match = move |path: &Path| {
11        let Some(extension) = path.extension().and_then(|extension| extension.to_str()) else {
12            return false;
13        };
14        extensions.iter().any(|ext| *ext == extension)
15    };
16
17    let root = root.as_ref();
18
19    // Single file.
20    if root.is_file() && does_entry_match(root) {
21        f(root);
22        return;
23    }
24
25    WalkBuilder::new(root)
26        .follow_links(true)
27        .hidden(true)
28        .max_depth(None)
29        .build_parallel()
30        .run(|| {
31            Box::new(|entry| {
32                if let Ok(entry) = entry {
33                    if is_dir(&entry) {
34                        return WalkState::Continue;
35                    }
36                    let path = entry.path();
37                    if does_entry_match(path) {
38                        f(path);
39                        return WalkState::Continue;
40                    }
41                };
42                WalkState::Skip
43            })
44        });
45}
46
47fn is_dir(entry: &DirEntry) -> bool {
48    entry.file_type().is_some_and(|entry| entry.is_dir())
49}