diff --git a/yazi-plugin/src/fs/fs.rs b/yazi-plugin/src/fs/fs.rs index ca6544ca..61ba5464 100644 --- a/yazi-plugin/src/fs/fs.rs +++ b/yazi-plugin/src/fs/fs.rs @@ -1,9 +1,16 @@ +use std::collections::{HashMap, HashSet}; + use globset::GlobBuilder; use mlua::{ExternalError, ExternalResult, IntoLuaMulti, Lua, Table, Value}; use tokio::fs; -use yazi_shared::fs::remove_dir_clean; +use yazi_shared::fs::{maybe_exists, ok_or_not_found, realname, remove_dir_clean, FilesOp, UrnBuf}; -use crate::{bindings::Cast, cha::Cha, file::File, url::{Url, UrlRef}}; +use crate::{ + bindings::Cast, + cha::Cha, + file::File, + url::{Url, UrlRef}, +}; pub fn install(lua: &Lua) -> mlua::Result<()> { lua.globals().raw_set( @@ -33,6 +40,50 @@ pub fn install(lua: &Lua) -> mlua::Result<()> { } })?, ), + ( + "create", + lua.create_async_function( + |lua, (url, is_dir, overwrite): (UrlRef, Option, Option)| async move { + let Some(parent_dir) = url.parent_url() else { + let error_msg = format!("{} has no parent directory", url.to_string()); + return (false, error_msg.into_lua_err()).into_lua_multi(lua); + }; + + if !overwrite.unwrap_or(false) && maybe_exists(&*url).await { + let error_msg = format!("{} already exists", url.to_string()); + return (false, error_msg.into_lua_err()).into_lua_multi(lua); + } + + let outcome = if is_dir.unwrap_or(false) { + fs::create_dir_all(&*url).await + } else if let Some(real) = realname(&url).await { + ok_or_not_found(fs::remove_file(&*url).await)?; + FilesOp::Deleting(parent_dir.clone(), HashSet::from_iter([UrnBuf::from(real)])) + .emit(); + match fs::File::create(&*url).await { + Ok(_) => Ok(()), + Err(e) => Err(e), + } + } else { + fs::create_dir_all(&parent_dir).await.ok(); + ok_or_not_found(fs::remove_file(&*url).await)?; + match fs::File::create(&*url).await { + Ok(_) => Ok(()), + Err(e) => Err(e), + } + }; + + if let Ok(f) = yazi_shared::fs::File::from(url.clone()).await { + FilesOp::Upserting(parent_dir, HashMap::from_iter([(f.urn_owned(), f)])).emit(); + }; + + match outcome { + 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 {