ladies and gentlemen, we have Luau running

This commit is contained in:
rhpidfyre 2024-12-28 23:22:30 -05:00
parent 03a5b064e5
commit c4559b8aa1
5 changed files with 102 additions and 51 deletions

View File

@ -11,6 +11,11 @@ enum ValidStatus {
TryExists(io::Error) TryExists(io::Error)
} }
fn display_none<T>(e: io::Error) -> Option<T> {
println!("{e}");
None
}
trait PathBufIsValid { trait PathBufIsValid {
fn is_valid(&self) -> Result<PathBuf, ValidStatus>; fn is_valid(&self) -> Result<PathBuf, ValidStatus>;
fn is_valid_or_home(&self) -> Option<PathBuf>; fn is_valid_or_home(&self) -> Option<PathBuf>;
@ -50,7 +55,7 @@ impl PathBufIsValid for PathBuf {
impl ChangeDirectory for Command { impl ChangeDirectory for Command {
fn set_current_dir(&self, new_path: &Path) -> Option<PathBuf> { fn set_current_dir(&self, new_path: &Path) -> Option<PathBuf> {
std::env::set_current_dir(new_path).map_or_else(|cd_err| {println!("{cd_err}"); None}, |()| Some(new_path.to_path_buf())) std::env::set_current_dir(new_path).map_or_else(|cd_err| display_none(cd_err), |()| Some(new_path.to_path_buf()))
} }
fn home_dir(&self) -> Option<PathBuf> { fn home_dir(&self) -> Option<PathBuf> {
@ -124,10 +129,7 @@ impl Command {
pub fn spawn(&self, command_process: io::Result<process::Child>) -> ProcessExitStatus { pub fn spawn(&self, command_process: io::Result<process::Child>) -> ProcessExitStatus {
match command_process { match command_process {
Err(e) => { Err(e) => display_none(e),
println!("{e}");
None
},
Ok(mut child) => Some(match child.wait() { Ok(mut child) => Some(match child.wait() {
Ok(exit_status) => exit_status, Ok(exit_status) => exit_status,
Err(exit_status_err) => { Err(exit_status_err) => {

View File

@ -1,10 +1,11 @@
pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub mod shell; pub mod shell;
mod commands; mod commands;
mod ps; mod ps;
mod rc; mod rc;
#[path = "./luau/vm.rs"] #[path = "./luau/vm.rs"]
mod vm; mod vm;
#[path = "./luau/alias.rs"]
mod alias;

View File

@ -1,26 +1,33 @@
use mlua::{ use mlua::{
Lua as Luau, Lua as Luau,
Result as lResult, Result as lResult,
MultiValue MultiValue,
}; };
use core::fmt;
use color_print::cprintln;
fn new_instance() -> lResult<Luau> { fn display_none<T, E>(err: E) -> Option<T>
let instance = Luau::new(); where
instance.sandbox(true)?; E: fmt::Display
instance.globals().set("getfenv", mlua::Nil)?; {
instance.globals().set("setfenv", mlua::Nil)?; println!("{err}");
Ok(instance) None
} }
fn out(args: MultiValue) -> String { fn luau_error<T>(err: mlua::Error) -> Option<T> {
cprintln!("<bold>====</>\n<r>{err}</>\n<bold>====</>");
None
}
fn luau_out(luau_args: MultiValue) -> String {
let mut print: Vec<String> = Vec::new(); let mut print: Vec<String> = Vec::new();
args.iter() luau_args.iter()
.map(|arg| arg.to_string().unwrap_or("<SHELL CONVERSION ERROR>".to_owned())) .map(|arg| arg.to_string().unwrap_or("<SHELL CONVERSION ERROR>".to_owned()))
.for_each(|v| { .for_each(|arg| {
if !print.is_empty() { if !print.is_empty() {
print.push(" ".to_owned()); print.push('\u{0009}'.to_string());
} };
print.push(v); print.push(arg);
} }
); );
print.concat() print.concat()
@ -28,31 +35,45 @@ fn out(args: MultiValue) -> String {
trait Globals { trait Globals {
fn print(&self) -> lResult<()>; fn print(&self) -> lResult<()>;
fn printraw(&self) -> lResult<()>;
} }
impl Globals for Vm { impl Globals for Vm {
fn print(&self) -> lResult<()> { fn print(&self) -> lResult<()> {
self.0.globals().set("print", self.0.create_function(|_, args: MultiValue| -> lResult<()> { self.0.globals().set("print", self.0.create_function(|_this, args: MultiValue| -> lResult<()> {
color_print::cprintln!("{}", out(args)); cprintln!("{}", luau_out(args));
Ok(()) Ok(())
})?)?; })?)
self.0.globals().set("printraw", self.0.create_function(|_, args: MultiValue| -> lResult<()> { }
println!("{}", out(args)); fn printraw(&self) -> lResult<()> {
self.0.globals().set("printraw", self.0.create_function(|_this, args: MultiValue| -> lResult<()> {
println!("{}", luau_out(args));
Ok(()) Ok(())
})?) })?)
} }
} }
struct Vm(Luau); pub struct Vm(Luau);
impl Vm { impl Vm {
pub fn new() -> Option<Self> { pub fn new() -> Option<Self> {
new_instance().map_or(None, |l| Some(Self(l))) let spawn_luau = || -> lResult<Luau> {
let instance = Luau::new();
instance.sandbox(true)?;
instance.globals().set("getfenv", mlua::Nil)?;
instance.globals().set("setfenv", mlua::Nil)?;
Ok(instance)
};
spawn_luau().map_or_else(|e| display_none(e), |l| Some(Self(l)))
} }
fn set_shell_globals(&self) -> mlua::Result<()> { fn set_shell_globals(&self) -> mlua::Result<()> {
todo!() self.print()?;
self.printraw()?;
Ok(())
} }
pub fn exec(&self, source: String) -> mlua::Result<()> { pub fn exec(&self, source: String) -> Option<()> {
self.set_shell_globals().and(self.0.load(source).exec()) self.set_shell_globals().map_or_else(|e| display_none(e), |()| {
self.0.load(source).exec().map_or_else(|e| luau_error(e), |()| Some(()))
})
} }
} }

View File

@ -25,6 +25,11 @@ enum CreateErr {
Passable Passable
} }
fn display_none<T>(e: io::Error) -> Option<T> {
println!("{e}");
None
}
#[allow(dead_code)] #[allow(dead_code)]
trait IsValid { trait IsValid {
fn is_valid(&self, is_dir_or_file: bool) -> Result<PathBuf, IsValidDirErr>; fn is_valid(&self, is_dir_or_file: bool) -> Result<PathBuf, IsValidDirErr>;
@ -68,10 +73,7 @@ impl IsValid for PathBuf {
self.is_valid_or(self.is_dir(), || { self.is_valid_or(self.is_dir(), || {
match fs::create_dir(self) { match fs::create_dir(self) {
Ok(()) => Some(self.to_path_buf()), Ok(()) => Some(self.to_path_buf()),
Err(create_e) => { Err(create_e) => display_none(create_e),
println!("{create_e}");
None
},
} }
}) })
} }
@ -79,17 +81,11 @@ impl IsValid for PathBuf {
fn is_valid_file_or_create(&self, default_file_bytes: &[u8]) -> Option<PathBuf> { fn is_valid_file_or_create(&self, default_file_bytes: &[u8]) -> Option<PathBuf> {
self.is_valid_or(self.is_file(), || { self.is_valid_or(self.is_file(), || {
match File::create(self) { match File::create(self) {
Err(create_e) => {
println!("{create_e}");
None
},
Ok(mut file) => match file.write_all(default_file_bytes) { Ok(mut file) => match file.write_all(default_file_bytes) {
Ok(()) => Some(self.to_path_buf()), Ok(()) => Some(self.to_path_buf()),
Err(write_e) => { Err(write_e) => display_none(write_e),
println!("{write_e}");
None
},
}, },
Err(create_e) => display_none(create_e)
} }
}) })
} }
@ -113,6 +109,13 @@ pub fn config_file() -> Option<PathBuf> {
config_file.is_valid_file_or_create(DEFAULT_CONFIG_CONTENT.as_bytes()) config_file.is_valid_file_or_create(DEFAULT_CONFIG_CONTENT.as_bytes())
} }
//TODO: history.rs
pub fn history_file() -> Option<PathBuf> {
let mut config_file = config_dir()?;
config_file.push(".history");
config_file.is_valid_file_or_create("".as_bytes())
}
pub fn none() -> Option<PathBuf> { pub fn none() -> Option<PathBuf> {
None None
} }

View File

@ -1,21 +1,38 @@
use crate::{ps, commands, rc}; use crate::{ps, commands, rc, vm};
use std::{fs, io::{self}}; use std::{fs, io::{self}};
use core::fmt;
fn display_none<T, E>(err: E) -> Option<T>
where
E: fmt::Display
{
println!("{err}");
None
}
pub struct Config { pub struct Config {
pub norc: bool pub norc: bool
} }
pub struct LambdaShell {
terminating: bool,
storage: Storage,
config: Config,
}
struct Storage { struct Storage {
pub command_exit_status: commands::ProcessExitStatus, pub command_exit_status: commands::ProcessExitStatus,
pub ps1: String, pub ps1: String,
} }
trait ShellLuauVm {
fn shell_vm_exec(&self, source: String) -> Option<()>;
}
impl ShellLuauVm for LambdaShell {
fn shell_vm_exec(&self, source: String) -> Option<()> {
vm::Vm::new().map_or(None, |vm| vm.exec(source))
}
}
pub struct LambdaShell {
terminating: bool,
storage: Storage,
config: Config,
}
impl LambdaShell { impl LambdaShell {
pub fn create(config: Config) -> Self { pub fn create(config: Config) -> Self {
Self { Self {
@ -47,11 +64,18 @@ impl LambdaShell {
}) })
} }
pub fn start(&mut self) { fn rc_parse(&self) {
let rc_file = match self.config.norc { let rc_file = match self.config.norc {
true => rc::none(), true => rc::none(),
false => rc::config_file(), false => rc::config_file(),
}; };
rc_file.map(|conf_file| fs::read_to_string(conf_file)
.map_or_else(|read_err| display_none(read_err), |conf| self.shell_vm_exec(conf))
);
}
pub fn start(&mut self) {
self.rc_parse();
ps::display(&self.storage.ps1); ps::display(&self.storage.ps1);