-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathdirectory.rs
More file actions
126 lines (110 loc) · 3 KB
/
Copy pathdirectory.rs
File metadata and controls
126 lines (110 loc) · 3 KB
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::{
env, fs,
path::{Path, PathBuf},
};
use crate::fuzzy::fuzzy_match_score;
pub fn get_current_directory() -> PathBuf {
env::current_dir().unwrap_or(PathBuf::from("/"))
}
/// Returns all directories for the given path
pub fn get_all_directories_in(path: &Path) -> Vec<Directory> {
let dirs_res = fs::read_dir(path);
let Ok(dirs) = dirs_res else {
return vec![];
};
dirs.filter_map(|entry| Directory::try_from(entry.ok()?.path().as_path()).ok())
.collect()
}
/// Get the sub directories at a specified depth relative to the given cwd.
///
/// ### Example
///
/// With this dir structure:
///
/// ```text
/// User/ <-- CWD
/// Desktop/
/// Wallpapers/
/// Documents/
/// FirstProject/
/// SecondProject/
/// ```
///
/// Depth 0 returns `Desktop` and `Documents`.
///
/// Depth 1 returns `Wallpapers`, `FirstProject` and `SecondProject`.
pub fn sub_directories(cwd: &Path, depth: u32) -> Vec<Directory> {
let mut directories = get_all_directories_in(cwd);
for _ in 0..depth {
let mut next_directories: Vec<Directory> = vec![];
for dir in directories {
next_directories.append(&mut get_all_directories_in(dir.location.as_path()));
}
directories = next_directories;
}
directories
}
#[derive(Debug)]
pub struct ScoredDirectory {
directory: Directory,
score: i32,
}
impl ScoredDirectory {
pub fn new(directory: Directory, score: i32) -> Self {
Self { directory, score }
}
pub fn directory(&self) -> &Directory {
&self.directory
}
pub fn score(&self) -> i32 {
self.score
}
}
pub fn scored_directories(directories: &[Directory], query: &str) -> Vec<ScoredDirectory> {
directories
.iter()
.map(|directory| {
let score = fuzzy_match_score(directory.name(), query);
ScoredDirectory::new(directory.clone(), score)
})
.collect()
}
#[derive(Debug, Clone)]
pub struct Directory {
/// The name of the directory
name: String,
/// The actual path of the directory, with symlinks resolved
location: PathBuf,
}
impl Directory {
pub fn new(name: String, location: PathBuf) -> Self {
Self { name, location }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn location(&self) -> &PathBuf {
&self.location
}
}
impl TryFrom<&Path> for Directory {
type Error = ();
fn try_from(path: &Path) -> Result<Self, Self::Error> {
if path.is_symlink() {
return Ok(Directory::new(
path.file_name().ok_or(())?.display().to_string(),
path.to_path_buf(),
));
}
if path.is_dir() {
let Some(file_name) = path.file_name() else {
return Ok(Directory::new(String::new(), path.to_path_buf()));
};
return Ok(Directory::new(
file_name.display().to_string(),
path.to_path_buf(),
));
}
Err(())
}
}