From 505ff977f0af36007cb010eb17860c9fa9a2cbbe Mon Sep 17 00:00:00 2001 From: highflowey Date: Fri, 23 Aug 2024 03:11:53 +0330 Subject: [PATCH] require impl (no caching) --- .../lune-std/src/globals/require/context.rs | 25 ++++++++- crates/lune-std/src/globals/require/mod.rs | 53 ++++++++++++++++--- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/crates/lune-std/src/globals/require/context.rs b/crates/lune-std/src/globals/require/context.rs index fcaeb36..7072c41 100644 --- a/crates/lune-std/src/globals/require/context.rs +++ b/crates/lune-std/src/globals/require/context.rs @@ -1,7 +1,10 @@ use crate::{library::StandardLibrary, luaurc::RequireAlias}; use mlua::prelude::*; use std::{collections::HashMap, path::PathBuf, sync::Arc}; -use tokio::sync::{broadcast::Sender, Mutex}; +use tokio::{ + fs, + sync::{broadcast::Sender, Mutex}, +}; /// The private struct that's stored in mlua's app data container #[derive(Debug, Default)] @@ -70,6 +73,26 @@ impl RequireContext { Ok(multi) } + pub async fn require( + lua: &Lua, + path_rel: PathBuf, + path_abs: PathBuf, + ) -> LuaResult { + if !fs::try_exists(&path_abs).await? { + return Err(LuaError::runtime(format!( + "Can not require '{}' as it does not exist", + path_rel.to_string_lossy() + ))); + } + + let content = fs::read_to_string(&path_abs).await?; + + lua.load(content) + .set_name(path_abs.to_string_lossy()) + .eval_async() + .await + } + pub fn inject_std( lua: &Lua, alias: &'static str, diff --git a/crates/lune-std/src/globals/require/mod.rs b/crates/lune-std/src/globals/require/mod.rs index 30cc04f..27ed019 100644 --- a/crates/lune-std/src/globals/require/mod.rs +++ b/crates/lune-std/src/globals/require/mod.rs @@ -1,9 +1,36 @@ use crate::{luaurc::path_to_alias, path::get_parent_path, LuneStandardLibrary}; use mlua::prelude::*; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; +use tokio::fs; pub mod context; +/// tries these alternatives on given path: +/// +/// * .lua and .luau extension +/// * path.join("init.luau") and path.join("init.lua") +pub async fn resolve_path(path: &Path) -> LuaResult { + let init_path = &path.join("init"); + + for ext in ["lua", "luau"] { + // try extension on given path + let path = append_extension(path, ext); + + if fs::try_exists(&path).await? { + return Ok(path); + }; + + // try extension on given path's init + let init_path = append_extension(init_path, ext); + + if fs::try_exists(&init_path).await? { + return Ok(init_path); + }; + } + + Err(LuaError::runtime("Could not resolve path")) +} + pub async fn lua_require(lua: &Lua, path: String) -> LuaResult { let require_path_rel = PathBuf::from(path); let require_alias = path_to_alias(&require_path_rel)?; @@ -19,12 +46,16 @@ pub async fn lua_require(lua: &Lua, path: String) -> LuaResult { } } else { let parent_path = get_parent_path(lua)?; - let require_path_abs = parent_path.join(&require_path_rel); + let require_path_abs = resolve_path(&parent_path.join(&require_path_rel)) + .await + .map_err(|_| { + LuaError::runtime(format!( + "Can not require '{}' as it does not exist", + require_path_rel.to_string_lossy(), + )) + })?; - Err(LuaError::runtime(format!( - "Tried requiring '{}'\nbut requires are not implemented yet.", - require_path_abs.to_string_lossy(), - ))) + context::RequireContext::require(lua, require_path_rel, require_path_abs).await } } @@ -39,3 +70,13 @@ pub fn create(lua: &Lua) -> LuaResult { f.into_lua(lua) } + +fn append_extension(path: impl Into, ext: &'static str) -> PathBuf { + let mut new = path.into(); + match new.extension() { + // FUTURE: There's probably a better way to do this than converting to a lossy string + Some(e) => new.set_extension(format!("{}.{ext}", e.to_string_lossy())), + None => new.set_extension(ext), + }; + new +}