mirror of
https://github.com/lune-org/lune.git
synced 2025-05-04 10:43:57 +01:00
feat: initial context preservation
This allows the REPL to now preserve context, such as previously declared variables which can be used in future eval steps. Currently is only supported for variables, support for other types to be included soon.
This commit is contained in:
parent
508c2836e3
commit
f9919a40aa
3 changed files with 80 additions and 11 deletions
26
Cargo.lock
generated
26
Cargo.lock
generated
|
@ -198,6 +198,21 @@ version = "0.21.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
|
||||
dependencies = [
|
||||
"bit-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
|
@ -634,6 +649,16 @@ dependencies = [
|
|||
"str-buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fancy-regex"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.0.0"
|
||||
|
@ -1087,6 +1112,7 @@ dependencies = [
|
|||
"directories",
|
||||
"dunce",
|
||||
"env_logger 0.10.0",
|
||||
"fancy-regex",
|
||||
"futures-util",
|
||||
"glam",
|
||||
"home",
|
||||
|
|
|
@ -132,6 +132,7 @@ regex = { optional = true, version = "1.7", default-features = false, features =
|
|||
"std",
|
||||
"unicode-perl",
|
||||
] }
|
||||
fancy-regex = "0.11.0"
|
||||
rustyline = "12.0.0"
|
||||
|
||||
### ROBLOX
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::{
|
||||
env,
|
||||
fmt::Write,
|
||||
io::ErrorKind,
|
||||
path::PathBuf,
|
||||
process::{exit, ExitCode},
|
||||
|
@ -7,19 +8,17 @@ use std::{
|
|||
|
||||
use anyhow::Error;
|
||||
use clap::Command;
|
||||
use lune::{Lune, LuneError};
|
||||
use fancy_regex::Regex;
|
||||
use lune::lua::stdio::formatting::{pretty_format_luau_error, pretty_format_value};
|
||||
use lune::Lune;
|
||||
use mlua::ExternalError;
|
||||
use once_cell::sync::Lazy;
|
||||
use rustyline::{error::ReadlineError, history::FileHistory, DefaultEditor, Editor};
|
||||
|
||||
use lune::lua::stdio::formatting::pretty_format_luau_error;
|
||||
|
||||
fn env_var_bool(value: String) -> Option<bool> {
|
||||
match value.to_lowercase().as_str() {
|
||||
"true" => Some(true),
|
||||
"1" => Some(true),
|
||||
"0" => Some(false),
|
||||
"false" => Some(false),
|
||||
"true" | "1" => Some(true),
|
||||
"false" | "0" => Some(false),
|
||||
&_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -73,18 +72,36 @@ pub async fn show_interface(cmd: Command) -> Result<ExitCode, Error> {
|
|||
let no_color = env::var("NO_COLOR").unwrap_or_else(|_| "false".to_string());
|
||||
|
||||
if no_color.is_empty() {
|
||||
false
|
||||
true
|
||||
} else {
|
||||
!env_var_bool(no_color).unwrap_or_else(|| false)
|
||||
}
|
||||
});
|
||||
|
||||
// Group 2 of this match pattern is the variable contents
|
||||
|
||||
// We're using fancy_regex instead of regex for backreferences
|
||||
// and lookaround. I'm not too good at regex, so if there's a
|
||||
// way to do this without backreferences and lookarounds,
|
||||
// please let me know.
|
||||
const VARIABLE_DECLARATION_PAT: &str = r#"(?!local.*)(?!\s)(=\s*)(.*)"#;
|
||||
|
||||
// HACK: Prepend this "context" to the source code provided,
|
||||
// so that the variable is preserved even the following steps
|
||||
let mut source_code_context: Option<String> = None;
|
||||
|
||||
loop {
|
||||
let mut source_code = String::new();
|
||||
|
||||
match repl.readline("> ") {
|
||||
Ok(code) => {
|
||||
source_code = code.clone();
|
||||
if let Some(ref ctx) = source_code_context {
|
||||
// If something breaks, blame this
|
||||
source_code = format!("{} {}", ctx, code);
|
||||
} else {
|
||||
source_code.push_str(code.as_str());
|
||||
}
|
||||
|
||||
repl.add_history_entry(code.as_str())?;
|
||||
|
||||
// If source code eval was requested, we reset the counter
|
||||
|
@ -117,10 +134,35 @@ pub async fn show_interface(cmd: Command) -> Result<ExitCode, Error> {
|
|||
}
|
||||
};
|
||||
|
||||
let eval_result = lune_instance.run("REPL", source_code).await;
|
||||
let eval_result = lune_instance.run("REPL", source_code.clone()).await;
|
||||
|
||||
match eval_result {
|
||||
Ok(_) => (),
|
||||
Ok(_) => {
|
||||
if Regex::new(VARIABLE_DECLARATION_PAT)?.is_match(&source_code)?
|
||||
&& !&source_code.contains("\n")
|
||||
{
|
||||
let declaration = source_code.split("=").collect::<Vec<&str>>()[1]
|
||||
.trim()
|
||||
.replace("\"", "");
|
||||
|
||||
let mut formatted_output = String::new();
|
||||
pretty_format_value(
|
||||
&mut formatted_output,
|
||||
&mlua::IntoLua::into_lua(declaration, &mlua::Lua::new())?,
|
||||
1,
|
||||
)?;
|
||||
|
||||
source_code_context = (|| -> Result<Option<String>, Error> {
|
||||
let mut ctx = String::new();
|
||||
write!(&mut ctx, "{}\n", &source_code)?;
|
||||
|
||||
Ok(Some(ctx))
|
||||
})()?;
|
||||
|
||||
println!("{}", formatted_output);
|
||||
}
|
||||
}
|
||||
|
||||
Err(err) => {
|
||||
eprintln!(
|
||||
"{}",
|
||||
|
|
Loading…
Add table
Reference in a new issue