-
Notifications
You must be signed in to change notification settings - Fork 460
/
Copy pathfs.rs
121 lines (109 loc) · 3.41 KB
/
fs.rs
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
use globset::GlobBuilder;
use mlua::{ExternalError, ExternalResult, IntoLuaMulti, Lua, Table, Value};
use tokio::fs;
use yazi_shared::fs::remove_dir_clean;
use crate::{bindings::Cast, cha::Cha, file::File, url::{Url, UrlRef}};
pub fn install(lua: &Lua) -> mlua::Result<()> {
lua.globals().raw_set(
"fs",
lua.create_table_from([
(
"cha",
lua.create_async_function(|lua, (url, follow): (UrlRef, Option<bool>)| async move {
let meta = if follow.unwrap_or(false) {
fs::metadata(&*url).await
} else {
fs::symlink_metadata(&*url).await
};
match meta {
Ok(m) => (Cha::cast(lua, m)?, Value::Nil).into_lua_multi(lua),
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
}
})?,
),
(
"write",
lua.create_async_function(|lua, (url, data): (UrlRef, mlua::String)| async move {
match fs::write(&*url, data).await {
Ok(_) => (true, Value::Nil).into_lua_multi(lua),
Err(e) => (false, e.raw_os_error()).into_lua_multi(lua),
}
})?,
),
(
"remove",
lua.create_async_function(|lua, (type_, url): (mlua::String, UrlRef)| async move {
let result = match type_.to_str()? {
"file" => fs::remove_file(&*url).await,
"dir" => fs::remove_dir(&*url).await,
"dir_all" => fs::remove_dir_all(&*url).await,
"dir_clean" => Ok(remove_dir_clean(&url).await),
_ => {
Err("Removal type must be 'file', 'dir', 'dir_all', or 'dir_clean'".into_lua_err())?
}
};
match result {
Ok(_) => (true, Value::Nil).into_lua_multi(lua),
Err(e) => (false, e.raw_os_error()).into_lua_multi(lua),
}
})?,
),
(
"read_dir",
lua.create_async_function(|lua, (url, options): (UrlRef, Table)| async move {
let glob = if let Ok(s) = options.raw_get::<_, mlua::String>("glob") {
Some(
GlobBuilder::new(s.to_str()?)
.case_insensitive(true)
.literal_separator(false)
.backslash_escape(false)
.empty_alternates(true)
.build()
.into_lua_err()?
.compile_matcher(),
)
} else {
None
};
let limit = options.raw_get("limit").unwrap_or(usize::MAX);
let resolve = options.raw_get("resolve").unwrap_or(false);
let mut it = match fs::read_dir(&*url).await {
Ok(it) => it,
Err(e) => return (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
};
let mut files = vec![];
while let Ok(Some(next)) = it.next_entry().await {
if files.len() >= limit {
break;
}
let path = next.path();
if glob.as_ref().is_some_and(|g| !g.is_match(&path)) {
continue;
}
let url = yazi_shared::fs::Url::from(path);
let file = if !resolve {
yazi_shared::fs::File::from_dummy(url, next.file_type().await.ok())
} else if let Ok(meta) = next.metadata().await {
yazi_shared::fs::File::from_meta(url, meta).await
} else {
yazi_shared::fs::File::from_dummy(url, next.file_type().await.ok())
};
files.push(File::cast(lua, file)?);
}
let tbl = lua.create_table_with_capacity(files.len(), 0)?;
for f in files {
tbl.raw_push(f)?;
}
(tbl, Value::Nil).into_lua_multi(lua)
})?,
),
(
"unique_name",
lua.create_async_function(|lua, url: UrlRef| async move {
// FIXME: handle errors
Url::cast(lua, yazi_shared::fs::unique_name(url.clone()).await)
})?,
),
])?,
)
}