diff --git a/src/lib.rs b/src/lib.rs index 6fc5f9d..c92cdf2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,22 +1,29 @@ +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); + pub mod session; pub mod commands; pub mod ps; pub mod rc; pub mod vm; -pub trait MapDisplay { +#[inline] +pub fn shell_error(err: E) { + color_print::ceprintln!("[!]: {err}") +} + +pub trait MapDisplay { fn map_or_display(self, f: F); fn map_or_display_none Option>(self, f: F) -> Option; } -impl MapDisplay for Result { - ///Map and display an error +impl MapDisplay for Result { + ///Map but display the error to stdout #[inline] fn map_or_display(self, f: F) { - self.map_or_else(|e| color_print::ceprintln!("[!]: {e}"), f) + self.map_or_else(|e| shell_error(e), f) } - ///Map and display an error but return `None` + ///Map but display the error to stdout and return `None` #[inline] fn map_or_display_none Option>(self, f: F) -> Option { - self.map_or_else(|e| { color_print::ceprintln!("[!]: {e}"); None }, f) + self.map_or_else(|e| { shell_error(e); None }, f) } } \ No newline at end of file diff --git a/src/ps.rs b/src/ps.rs index 34ce585..49a13bb 100644 --- a/src/ps.rs +++ b/src/ps.rs @@ -1,10 +1,17 @@ -pub const DEFAULT_PS: &str = concat!("lambdashell-", env!("CARGO_PKG_VERSION")); +pub const DEFAULT_PS: &str = concat!("lambdashell-", env!("CARGO_PKG_VERSION"), " "); +#[derive(Debug, Clone)] pub struct Ps(String); impl Ps { pub fn set(prompt: String) -> Self { Self(prompt) } + pub fn get(self) -> String { + self.0 + } + pub fn display(&self) { + print!("{}", self.0); + } pub fn working_dir_name(&self) -> String { std::env::current_dir().map_or("?".to_owned(), |path| { @@ -17,8 +24,4 @@ impl Ps { }) }) } - - pub fn display(&self) { - print!("{}", self.0); - } } \ No newline at end of file diff --git a/src/session.rs b/src/session.rs index 6a33c6b..98ab344 100644 --- a/src/session.rs +++ b/src/session.rs @@ -1,48 +1,45 @@ use std::{fs, io::{self}}; +use core::fmt; use crate::{ - vm::{LuauVm, self}, - commands, - ps, - rc, - MapDisplay, + commands, ps::{self, Ps}, rc, shell_error, vm::{self, LuauVm}, MapDisplay }; +#[derive(Debug, Clone)] pub struct Config { pub norc: bool } pub struct LambdaShell { - vm: LuauVm, - ps1: String, + terminate: bool, config: Config, - terminating: bool, + vm: LuauVm, + ps: Ps, } impl LambdaShell { pub fn create(config: Config) -> Self { + let ps = Ps::set(ps::DEFAULT_PS.to_owned()); Self { - vm: vm::LuauVm::new(), - ps1: ps::DEFAULT_PS.to_owned(), - terminating: false, + vm: vm::LuauVm::new(ps.to_owned()), + terminate: false, config, + ps } } pub fn wait(&mut self) -> Result<(), io::Error> { io::Write::flush(&mut io::stdout()).map(|()| { let mut input = String::new(); - io::stdin().read_line(&mut input).map_or_display(|_size| { - match input.trim() { - //special casey - "exit" => self.terminating = true, - trim => commands::Command::new(trim.to_owned()).exec() - }; + io::stdin().read_line(&mut input).map_or_display(|_size| match input.trim() { + "exit" => self.terminate = true, + trim => commands::Command::new(trim.to_owned()).exec() }) }) } - pub fn vm_exec(&self, source: String) { - self.vm.exec(source); + pub fn error(&mut self, err: E) { + shell_error(err); + self.terminate = true; } pub fn start(&mut self) { @@ -51,20 +48,19 @@ impl LambdaShell { fs::read_to_string(conf_file).map_or_display(|luau_conf| self.vm_exec(luau_conf)); } } - loop { - match self.terminating { - true => break, - false => { + self.ps.display(); - match self.wait() { - Ok(()) => {}, - Err(flush_error) => { - println!("{flush_error}"); - break; - } - } - }, + loop { + if self.terminate { break } else { + match self.wait() { + Ok(()) => self.ps.display(), + Err(flush_err) => self.error(flush_err), + } } } } + + pub fn vm_exec(&self, source: String) { + self.vm.exec(source); + } } diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 8086cf7..770eba1 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -3,7 +3,7 @@ use color_print::{cformat, ceprintln}; use core::fmt; use shell::Shell; -use crate::{vm::terminal::Terminal, MapDisplay}; +use crate::{ps::Ps, vm::terminal::Terminal, MapDisplay}; mod shell; mod terminal; @@ -24,20 +24,22 @@ impl LuauRuntimeErr for Result { trait Globals { const LIB_VERSION: &str; + const CONV_ERROR: &str; fn global_warn(&self, luau_globals: &Table) -> lResult<()>; fn global_version(&self, luau_globals: &Table) -> lResult<()>; } impl Globals for LuauVm { const LIB_VERSION: &str = env!("CARGO_PKG_VERSION"); + const CONV_ERROR: &str = ""; fn global_warn(&self, luau_globals: &Table) -> lResult<()> { let luau_print = luau_globals.get::("print")?; - luau_globals.set("warn", self.0.create_function(move |this, args: MultiValue| -> lResult<()> { + luau_globals.set("warn", self.vm.create_function(move |this, args: MultiValue| -> lResult<()> { let luau_multi_values = args.into_iter() - .map(|value| cformat!("{}", value.to_string().unwrap_or("".to_owned()))) + .map(|value| cformat!("{}", value.to_string().unwrap_or(Self::CONV_ERROR.to_owned()))) .map(|arg_v| Value::String(this.create_string(arg_v).unwrap())) .collect::(); - luau_print.call::<()>(luau_multi_values).unwrap(); + luau_print.call::<()>(luau_multi_values)?; Ok(()) })?) } @@ -48,27 +50,28 @@ impl Globals for LuauVm { } } -pub struct LuauVm(pub Luau); +pub struct LuauVm { + vm: Luau, + ps: Ps, +} impl LuauVm { - pub(crate) fn new() -> Self { - Self(Luau::new()) + pub(crate) fn new(ps: Ps) -> Self { + Self { vm: Luau::new(), ps } } fn set_shell_globals(&self) -> lResult<()> { - let luau_globals = self.0.globals(); + let luau_globals = self.vm.globals(); self.global_warn(&luau_globals)?; self.global_version(&luau_globals)?; self.global_terminal(&luau_globals)?; self.global_shell(&luau_globals)?; luau_globals.set("getfenv", mlua::Nil)?; luau_globals.set("setfenv", mlua::Nil)?; - self.0.sandbox(true)?; + self.vm.sandbox(true)?; Ok(()) } pub fn exec(&self, source: String) { - self.set_shell_globals().map_or_display_none(|()| { - self.0.load(source).exec().map_or_luau_rt_err(Some) - }); + self.set_shell_globals().map_or_display_none(|()| self.vm.load(source).exec().map_or_luau_rt_err(Some)); } } \ No newline at end of file diff --git a/src/vm/shell.rs b/src/vm/shell.rs index 71c2a8a..eec923f 100644 --- a/src/vm/shell.rs +++ b/src/vm/shell.rs @@ -1,24 +1,23 @@ -use mlua::{Result as lResult, Table, Value}; +use mlua::{Result as lResult, Table}; use whoami::fallible; use crate::vm::LuauVm; -const DEFAULT_HOSTNAME: &str = "hostname"; - trait PsPrompt { fn ps_prompt(&self) -> lResult; } impl PsPrompt for LuauVm { fn ps_prompt(&self) -> lResult
{ - let prompt_table = self.0.create_table()?; - let prompt_metatable = self.0.create_table()?; - prompt_metatable.set("__index", self.0.create_function(|_, (table, index): (Table, Value)| -> lResult { - table.raw_get::(index) + let prompt_table = self.vm.create_table()?; + let prompt_metatable = self.vm.create_table()?; + let ps_owned = self.ps.to_owned(); + prompt_metatable.set("__index", self.vm.create_function(move |_, (s, s1): (Table, String)| -> lResult { + Ok(ps_owned.clone().get()) })?)?; - prompt_metatable.set("__newindex", self.0.create_function(|_, _: String| -> lResult { + prompt_metatable.set("__newindex", self.vm.create_function(|_, _: String| -> lResult { Ok("placeholder".to_owned()) })?)?; - prompt_table.set("__metatable", mlua::Nil)?; + // prompt_table.set("__metatable", mlua::Nil)?; prompt_table.set_metatable(Some(prompt_metatable)); prompt_table.set_readonly(false); Ok(prompt_table) @@ -26,18 +25,21 @@ impl PsPrompt for LuauVm { } trait System { + const DEFAULT_HOSTNAME: &str; fn sys_details(&self) -> lResult
; } impl System for LuauVm { + const DEFAULT_HOSTNAME: &str = "hostname"; + fn sys_details(&self) -> lResult
{ - let system = self.0.create_table()?; + let system = self.vm.create_table()?; system.set("DESKTOP_ENV", whoami::desktop_env().to_string())?; system.set("DEVICENAME", whoami::devicename().to_string())?; system.set("USERNAME", whoami::username().to_string())?; system.set("REALNAME", whoami::realname().to_string())?; system.set("PLATFORM", whoami::platform().to_string())?; system.set("DISTRO", whoami::distro().to_string())?; - system.set("HOSTNAME", fallible::hostname().unwrap_or(DEFAULT_HOSTNAME.to_owned()))?; + system.set("HOSTNAME", fallible::hostname().unwrap_or(Self::DEFAULT_HOSTNAME.to_owned()))?; Ok(system) } } @@ -47,10 +49,9 @@ pub trait Shell { } impl Shell for LuauVm { fn global_shell(&self, luau_globals: &Table) -> lResult<()> { - let shell = self.0.create_table()?; - let ps_prompt = self.ps_prompt()?; + let shell = self.vm.create_table()?; shell.set("SYSTEM", self.sys_details()?)?; - shell.set("PROMPT", ps_prompt)?; + shell.set("PROMPT", self.ps_prompt()?)?; luau_globals.set("SHELL", shell)?; Ok(()) } diff --git a/src/vm/terminal.rs b/src/vm/terminal.rs index e7a0a63..9cb24b0 100644 --- a/src/vm/terminal.rs +++ b/src/vm/terminal.rs @@ -7,7 +7,7 @@ use crate::vm::LuauVm; macro_rules! foreground_styles_luau { ($self:expr, $style_table:expr, $($color:ident)+) => { $( - $style_table.set(stringify!($color).to_ascii_uppercase(), $self.0.create_function(|_, text: String| -> lResult { + $style_table.set(stringify!($color).to_ascii_uppercase(), $self.vm.create_function(|_, text: String| -> lResult { Ok(text.$color().to_string()) })?)?; )+ @@ -18,7 +18,7 @@ macro_rules! background_styles_luau { $( $style_table.set( str_split!(stringify!($color), "_")[1..].join("_").to_ascii_uppercase(), - $self.0.create_function(|_, text: String| -> lResult { + $self.vm.create_function(|_, text: String| -> lResult { Ok(text.$color().to_string()) })?)?; )+ @@ -31,7 +31,7 @@ trait Colors { } impl Colors for LuauVm { fn background(&self, term_out_table: &Table) -> lResult<()> { - let foreground_table = self.0.create_table()?; + let foreground_table = self.vm.create_table()?; foreground_styles_luau!(self, foreground_table, dark_grey dark_red dark_green dark_cyan dark_yellow dark_magenta dark_blue @@ -48,7 +48,7 @@ impl Colors for LuauVm { } fn foreground(&self, term_out_table: &Table) -> lResult<()> { - let background_table = self.0.create_table()?; + let background_table = self.vm.create_table()?; background_styles_luau!(self, background_table, on_dark_grey on_dark_red on_dark_green on_dark_cyan on_dark_yellow on_dark_magenta on_dark_blue @@ -68,21 +68,21 @@ trait Write { } impl Write for LuauVm { fn write(&self) -> lResult { - self.0.create_function(|_, s: String| -> lResult<()> { + self.vm.create_function(|_, s: String| -> lResult<()> { print!("{s}"); Ok(()) }) } fn write_error(&self) -> lResult { - self.0.create_function(|_, s: String| -> lResult<()> { + self.vm.create_function(|_, s: String| -> lResult<()> { eprint!("{s}"); Ok(()) }) } fn write_error_ln(&self) -> lResult { - self.0.create_function(|_, s: String| -> lResult<()> { + self.vm.create_function(|_, s: String| -> lResult<()> { eprintln!("{s}"); Ok(()) }) @@ -95,14 +95,14 @@ pub trait Terminal { } impl Terminal for LuauVm { fn out(&self) -> lResult
{ - let term_out_table = self.0.create_table()?; + let term_out_table = self.vm.create_table()?; self.background(&term_out_table)?; self.foreground(&term_out_table)?; Ok(term_out_table) } fn global_terminal(&self, luau_globals: &Table) -> lResult<()> { - let term_table = self.0.create_table()?; + let term_table = self.vm.create_table()?; term_table.set("OUT", self.out()?)?; term_table.set("WRITE", self.write()?)?; term_table.set("WRITE_ERROR", self.write_error()?)?;