1use crate::constants;
2use std::{
3 ffi::OsStr,
4 fs,
5 path::{Path, PathBuf},
6};
7use walkdir::WalkDir;
8
9pub fn get_sway_files(path: PathBuf) -> Vec<PathBuf> {
10 let mut files = vec![];
11 let mut dir_entries = vec![path];
12
13 while let Some(next_dir) = dir_entries.pop() {
14 if let Ok(read_dir) = fs::read_dir(&next_dir) {
15 for entry in read_dir.filter_map(Result::ok) {
16 let path = entry.path();
17 if path.is_dir() {
18 dir_entries.push(path);
19 } else if is_sway_file(&path) {
20 files.push(path);
21 }
22 }
23 }
24 }
25 files
26}
27
28pub fn is_sway_file(file: &Path) -> bool {
29 file.is_file() && file.extension() == Some(OsStr::new(constants::SWAY_EXTENSION))
30}
31
32pub fn iter_prefixes<T>(slice: &[T]) -> impl DoubleEndedIterator<Item = &[T]> {
44 (1..=slice.len()).map(move |len| &slice[..len])
45}
46
47pub fn find_nested_manifest_dir(starter_path: &Path) -> Option<PathBuf> {
49 find_nested_dir_with_file(starter_path, constants::MANIFEST_FILE_NAME)
50}
51
52pub fn find_nested_dir_with_file(starter_path: &Path, file_name: &str) -> Option<PathBuf> {
56 let starter_dir = if starter_path.is_dir() {
57 starter_path
58 } else {
59 starter_path.parent()?
60 };
61 WalkDir::new(starter_path).into_iter().find_map(|e| {
62 let entry = e.ok()?;
63 if entry.path() != starter_dir.join(file_name) && entry.file_name() == OsStr::new(file_name)
64 {
65 let mut entry = entry.path().to_path_buf();
66 entry.pop();
67 Some(entry)
68 } else {
69 None
70 }
71 })
72}
73
74pub fn find_parent_dir_with_file<P: AsRef<Path>>(
78 starter_path: P,
79 file_name: &str,
80) -> Option<PathBuf> {
81 let mut path = std::fs::canonicalize(starter_path).ok()?;
82 let root_path = PathBuf::from("/");
83 while path != root_path {
84 path.push(file_name);
85 if path.exists() {
86 path.pop();
87 return Some(path);
88 }
89 path.pop();
90 path.pop();
91 }
92 None
93}
94
95pub fn find_parent_manifest_dir<P: AsRef<Path>>(starter_path: P) -> Option<PathBuf> {
97 find_parent_dir_with_file(starter_path, constants::MANIFEST_FILE_NAME)
98}
99
100pub fn find_parent_manifest_dir_with_check<T: AsRef<Path>, F>(
103 starter_path: T,
104 check: F,
105) -> Option<PathBuf>
106where
107 F: Fn(&Path) -> bool,
108{
109 find_parent_manifest_dir(&starter_path).and_then(|manifest_dir| {
110 if check(&manifest_dir) {
112 Some(manifest_dir)
113 } else {
114 manifest_dir
115 .parent()
116 .and_then(|parent_dir| find_parent_manifest_dir_with_check(parent_dir, check))
117 }
118 })
119}