diff --git a/yazi-plugin/src/fs/fs.rs b/yazi-plugin/src/fs/fs.rs
index 46ada698..447dc63f 100644
--- a/yazi-plugin/src/fs/fs.rs
+++ b/yazi-plugin/src/fs/fs.rs
@@ -1,9 +1,40 @@
use globset::GlobBuilder;
-use mlua::{ExternalError, ExternalResult, Function, IntoLua, IntoLuaMulti, Lua, MetaMethod, Table, Value};
+use mlua::{
+ ExternalError, ExternalResult, Function, IntoLua, IntoLuaMulti, Lua, MetaMethod, Table, Value,
+};
use tokio::fs;
use yazi_fs::remove_dir_clean;
-use crate::{Error, bindings::{Cast, Cha}, file::File, url::{Url, UrlRef}};
+use crate::{
+ Error,
+ bindings::{Cast, Cha},
+ file::File,
+ url::{Url, UrlRef},
+};
+
+const READ: u8 = 1;
+const WRITE: u8 = 2;
+const APPEND: u8 = 4;
+const TRUNCATE: u8 = 8;
+const CREATE: u8 = 16;
+const CREATE_NEW: u8 = 32;
+
+pub struct OpenOpts;
+
+impl OpenOpts {
+ pub fn install(lua: &Lua) -> mlua::Result<()> {
+ let open_options = lua.create_table_from([
+ ("READ", READ),
+ ("WRITE", WRITE),
+ ("APPEND", APPEND),
+ ("TRUNCATE", TRUNCATE),
+ ("CREATE", CREATE),
+ ("CREATE_NEW", CREATE_NEW),
+ ])?;
+
+ lua.globals().raw_set("OpenOpts", open_options)
+ }
+}
pub fn compose(lua: &Lua) -> mlua::Result
{
let index = lua.create_function(|lua, (ts, key): (Table, mlua::String)| {
@@ -12,6 +43,7 @@ pub fn compose(lua: &Lua) -> mlua::Result {
b"cha" => cha(lua)?,
b"write" => write(lua)?,
b"remove" => remove(lua)?,
+ b"create_dir" => create_dir(lua)?,
b"read_dir" => read_dir(lua)?,
b"unique_name" => unique_name(lua)?,
_ => return Ok(Value::Nil),
@@ -50,6 +82,50 @@ fn cha(lua: &Lua) -> mlua::Result {
})
}
+fn open(lua: &Lua) -> mlua::Result {
+ lua.create_async_function(|lua, (url, opts): (UrlRef, Option)| async move {
+ let given_options = opts.unwrap_or(READ as i64);
+ let given_options = given_options as u8;
+ let mut write_flag = false;
+ let mut requires_write = false;
+ let mut open_opts = fs::OpenOptions::new();
+
+ if given_options & READ != 0 {
+ open_opts.read(true);
+ }
+ if given_options & WRITE != 0 {
+ write_flag = true;
+ open_opts.write(true);
+ }
+ if given_options & APPEND != 0 {
+ open_opts.append(true);
+ }
+ if given_options & TRUNCATE != 0 {
+ requires_write = true;
+ open_opts.truncate(true);
+ }
+ if given_options & CREATE != 0 {
+ requires_write = true;
+ open_opts.create(true);
+ }
+ if given_options & CREATE_NEW != 0 {
+ requires_write = true;
+ open_opts.create_new(true);
+ }
+
+ if requires_write && !write_flag {
+ open_opts.write(true);
+ }
+
+ let result = open_opts.open(&*url).await;
+
+ match result {
+ Ok(file) => (File::cast(&lua, file)?, Value::Nil).into_lua_multi(&lua),
+ Err(e) => (Value::Nil, Error::Io(e)).into_lua_multi(&lua),
+ }
+ })
+}
+
fn write(lua: &Lua) -> mlua::Result {
lua.create_async_function(|lua, (url, data): (UrlRef, mlua::String)| async move {
match fs::write(&*url, data.as_bytes()).await {
@@ -76,6 +152,18 @@ fn remove(lua: &Lua) -> mlua::Result {
})
}
+fn create_dir(lua: &Lua) -> mlua::Result {
+ lua.create_async_function(|lua, (dir, recursive): (UrlRef, Option)| async move {
+ let is_recursive = recursive.unwrap_or(false);
+ let result =
+ if is_recursive { fs::create_dir_all(&*dir).await } else { fs::create_dir(&*dir).await };
+ match result {
+ Ok(_) => (true, Value::Nil).into_lua_multi(&lua),
+ Err(e) => (false, Error::Io(e)).into_lua_multi(&lua),
+ }
+ })
+}
+
fn read_dir(lua: &Lua) -> mlua::Result {
lua.create_async_function(|lua, (dir, options): (UrlRef, Table)| async move {
let glob = if let Ok(s) = options.raw_get::("glob") {