parent
40769ec693
commit
c57e5c2d49
17 changed files with 405 additions and 106 deletions
10
Cargo.toml
10
Cargo.toml
|
@ -3,6 +3,7 @@ resolver = "2"
|
|||
members = ["engine","subcrates/zen_core"]
|
||||
|
||||
[profile.dev]
|
||||
|
||||
rpath = false
|
||||
panic = "abort"
|
||||
lto = "off"
|
||||
|
@ -12,8 +13,9 @@ overflow-checks = false
|
|||
incremental = true
|
||||
codegen-units = 512
|
||||
|
||||
|
||||
strip = "symbols"
|
||||
debug-assertions = false
|
||||
debug-assertions = true
|
||||
|
||||
[profile.dev.package."*"]
|
||||
opt-level = 0
|
||||
|
@ -22,8 +24,9 @@ overflow-checks = false
|
|||
incremental = true
|
||||
codegen-units = 512
|
||||
|
||||
|
||||
strip = "symbols"
|
||||
debug-assertions = false
|
||||
debug-assertions = true
|
||||
[profile.dev.build-override]
|
||||
opt-level = 0
|
||||
debug = false
|
||||
|
@ -34,3 +37,6 @@ codegen-units = 512
|
|||
[workspace.dependencies]
|
||||
lazy_static = "1.5.0"
|
||||
parking_lot = "0.12.3"
|
||||
|
||||
[profile.release]
|
||||
debug-assertions = false
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
name = "engine"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
repository = "https://github.com/Zenyx-Engine/Zenyx"
|
||||
[dependencies]
|
||||
anyhow = "1.0.94"
|
||||
backtrace = "0.3.74"
|
||||
chrono = "0.4.39"
|
||||
colored = "2.2.0"
|
||||
crashreport = "1.0.1"
|
||||
dirs-next = "2.0.0"
|
||||
|
||||
lazy_static.workspace = true
|
||||
log = "0.4.22"
|
||||
|
@ -15,3 +18,9 @@ parking_lot.workspace = true
|
|||
regex = "1.11.1"
|
||||
rustyline = { version = "15.0.0", features = ["derive", "rustyline-derive"] }
|
||||
tokio = { version = "1.42.0", features = ["macros", "parking_lot", "rt", "rt-multi-thread"] }
|
||||
|
||||
[profile.dev]
|
||||
debug-assertions = true
|
||||
|
||||
[profile.release]
|
||||
debug-assertions = false
|
||||
|
|
3
engine/src/core/ecs/mod.rs
Normal file
3
engine/src/core/ecs/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
// struct ComponentRegistry {
|
||||
// components
|
||||
// }
|
|
@ -1,3 +1,6 @@
|
|||
pub mod repl;
|
||||
pub mod ecs;
|
||||
pub mod logger;
|
||||
pub mod panic;
|
||||
pub mod repl;
|
||||
pub mod splash;
|
||||
pub mod workspace;
|
||||
|
|
152
engine/src/core/panic.rs
Normal file
152
engine/src/core/panic.rs
Normal file
|
@ -0,0 +1,152 @@
|
|||
use std::fmt::Write as FmtWrite;
|
||||
use std::mem;
|
||||
|
||||
use backtrace::Backtrace;
|
||||
use parking_lot::Once;
|
||||
use regex::Regex;
|
||||
|
||||
static INIT: parking_lot::Once = Once::new();
|
||||
|
||||
//#[cfg(not(debug_assertions))]
|
||||
pub fn set_panic_hook() {
|
||||
use std::io::Write;
|
||||
|
||||
use colored::Colorize;
|
||||
|
||||
use crate::workspace;
|
||||
INIT.call_once(|| {
|
||||
let default_hook = std::panic::take_hook();
|
||||
std::panic::set_hook(Box::new(move |info| {
|
||||
let log_path = workspace::get_working_dir().unwrap_or_else(|_| {
|
||||
default_hook(info);
|
||||
std::process::exit(0);
|
||||
});
|
||||
if !log_path.exists() {
|
||||
std::fs::create_dir_all(&log_path).unwrap_or_else(|_| {
|
||||
default_hook(info);
|
||||
std::process::exit(0);
|
||||
})
|
||||
}
|
||||
let log_path = log_path.join("panic.log");
|
||||
|
||||
// human_panic::print_msg::<PathBuf>(Some(log_path), &human_panic::Metadata::new("Zenyx", env!("CARGO_PKG_VERSION"))
|
||||
// .support("https://github.com/Zenyx-Engine/Zenyx/issues")
|
||||
// .authors("Zenyx community <https://github.com/Zenyx-Engine>")).unwrap();
|
||||
// // Call the default hook for any additional actions
|
||||
|
||||
let mut file = std::fs::File::create(&log_path).unwrap_or_else(|_| {
|
||||
default_hook(info);
|
||||
std::process::exit(0);
|
||||
});
|
||||
writeln!(file, "{}", info.payload_as_str().unwrap_or_else(|| {
|
||||
default_hook(info);
|
||||
std::process::exit(0);
|
||||
})).unwrap_or_else(|_| {
|
||||
default_hook(info);
|
||||
std::process::exit(0);
|
||||
});
|
||||
writeln!(file, "{}", render_backtrace().sanitize_path()).unwrap_or_else(|_| {
|
||||
default_hook(info);
|
||||
std::process::exit(0);
|
||||
});
|
||||
let panic_msg = format!(
|
||||
"Zenyx had a problem and crashed. To help us diagnose the problem you can send us a crash report.
|
||||
|
||||
We have generated a report file at \"{}\". Submit an issue or email with the subject of \"Zenyx Crash Report\" and include the report as an attachment.
|
||||
|
||||
To submit the crash report:
|
||||
|
||||
https://github.com/Zenyx-Engine/Zenyx/issues
|
||||
|
||||
We take privacy seriously, and do not perform any automated error collection. In order to improve the software, we rely on people to submit reports.
|
||||
|
||||
Thank you kindly!",log_path.display());
|
||||
println!("{}",panic_msg.red().bold());
|
||||
println!("\nFor future reference, the error summary is as follows:\n{}",info.payload_as_str().unwrap_or_else(||{
|
||||
default_hook(info);
|
||||
std::process::exit(0);
|
||||
}).red().bold());
|
||||
std::process::exit(0); // There is nothing to be done at this point, it looks cleaner to exit instead of doing a natural panic
|
||||
}));
|
||||
});
|
||||
}
|
||||
// THIS SNIPPET IS LICENSED UNDER THE APACHE LICENSE, VERSION 2.0
|
||||
// https://github.com/rust-cli/human-panic
|
||||
// No changes were made to the original snippet
|
||||
fn render_backtrace() -> String {
|
||||
//We take padding for address and extra two letters
|
||||
//to pad after index.
|
||||
#[allow(unused_qualifications)] // needed for pre-1.80 MSRV
|
||||
const HEX_WIDTH: usize = mem::size_of::<usize>() * 2 + 2;
|
||||
//Padding for next lines after frame's address
|
||||
const NEXT_SYMBOL_PADDING: usize = HEX_WIDTH + 6;
|
||||
|
||||
let mut backtrace = String::new();
|
||||
|
||||
//Here we iterate over backtrace frames
|
||||
//(each corresponds to function's stack)
|
||||
//We need to print its address
|
||||
//and symbol(e.g. function name),
|
||||
//if it is available
|
||||
let bt = Backtrace::new();
|
||||
let symbols = bt
|
||||
.frames()
|
||||
.iter()
|
||||
.flat_map(|frame| {
|
||||
let symbols = frame.symbols();
|
||||
if symbols.is_empty() {
|
||||
vec![(frame, None, "<unresolved>".to_owned())]
|
||||
} else {
|
||||
symbols
|
||||
.iter()
|
||||
.map(|s| {
|
||||
(
|
||||
frame,
|
||||
Some(s),
|
||||
s.name()
|
||||
.map(|n| n.to_string())
|
||||
.unwrap_or_else(|| "<unknown>".to_owned()),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let begin_unwind = "rust_begin_unwind";
|
||||
let begin_unwind_start = symbols
|
||||
.iter()
|
||||
.position(|(_, _, n)| n == begin_unwind)
|
||||
.unwrap_or(0);
|
||||
for (entry_idx, (frame, symbol, name)) in symbols.iter().skip(begin_unwind_start).enumerate() {
|
||||
let ip = frame.ip();
|
||||
let _ = writeln!(backtrace, "{entry_idx:4}: {ip:HEX_WIDTH$?} - {name}");
|
||||
if let Some(symbol) = symbol {
|
||||
//See if there is debug information with file name and line
|
||||
if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) {
|
||||
let _ = writeln!(
|
||||
backtrace,
|
||||
"{:3$}at {}:{}",
|
||||
"",
|
||||
file.display(),
|
||||
line,
|
||||
NEXT_SYMBOL_PADDING
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
backtrace
|
||||
}
|
||||
|
||||
trait Sanitize {
|
||||
fn sanitize_path(&self) -> String;
|
||||
}
|
||||
|
||||
impl Sanitize for str {
|
||||
fn sanitize_path(&self) -> String {
|
||||
let username_pattern = r"(?i)(/home/|/Users/|\\Users\\)([^/\\]+)";
|
||||
let re = Regex::new(username_pattern).expect("Failed to sanitize path, aborting operation");
|
||||
|
||||
re.replace_all(self, "${1}<USER>").to_string()
|
||||
}
|
||||
}
|
|
@ -4,9 +4,8 @@ use anyhow::anyhow;
|
|||
use parking_lot::RwLock;
|
||||
use regex::Regex;
|
||||
|
||||
use crate::core::repl::handler::COMMAND_MANAGER;
|
||||
|
||||
use super::{handler::Command, input::tokenize};
|
||||
use crate::core::repl::handler::COMMAND_MANAGER;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct HelpCommand;
|
||||
|
@ -19,7 +18,7 @@ impl Command for HelpCommand {
|
|||
for (_, command) in manager.get_commands() {
|
||||
println!(
|
||||
"Command: {}\n\tDescription: {}\n\tParameters: {}\n\tHelp: {}\n",
|
||||
command.get_name(),
|
||||
command.get_name().to_lowercase(),
|
||||
command.get_description(),
|
||||
command.get_params(),
|
||||
command.get_help()
|
||||
|
@ -62,7 +61,9 @@ impl Command for ClearCommand {
|
|||
fn execute(&self, _args: Option<Vec<String>>) -> Result<(), anyhow::Error> {
|
||||
println!("Clearing screen..., running command");
|
||||
let _result = if cfg!(target_os = "windows") {
|
||||
std::process::Command::new("cmd").args(["/c", "cls"]).spawn()
|
||||
std::process::Command::new("cmd")
|
||||
.args(["/c", "cls"])
|
||||
.spawn()
|
||||
} else {
|
||||
std::process::Command::new("clear").spawn()
|
||||
};
|
||||
|
@ -97,14 +98,13 @@ impl Command for ExitCommand {
|
|||
fn execute(&self, args: Option<Vec<String>>) -> Result<(), anyhow::Error> {
|
||||
match args {
|
||||
Some(args) => {
|
||||
|
||||
let exit_code = args[0].parse()?;
|
||||
std::process::exit(exit_code);
|
||||
// Ok(())
|
||||
},
|
||||
}
|
||||
None => {
|
||||
std::process::exit(0);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,6 @@ impl Command for ExecFile {
|
|||
fn execute(&self, args: Option<Vec<String>>) -> Result<(), anyhow::Error> {
|
||||
match args {
|
||||
Some(args) => {
|
||||
|
||||
let file_path = PathBuf::from_str(&args[0])?;
|
||||
if file_path.extension().is_some() && file_path.extension().unwrap() != "zensh" {
|
||||
return Err(anyhow!("Selected file was not a zensh file"));
|
||||
|
@ -148,15 +147,22 @@ impl Command for ExecFile {
|
|||
if let Ok(command) = eval(zscript) {
|
||||
println!("{:#?}", command);
|
||||
for (cmd_name, cmd_args) in command {
|
||||
COMMAND_MANAGER.read().execute(&cmd_name, cmd_args)?
|
||||
match COMMAND_MANAGER.read().execute(&cmd_name, cmd_args) {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
println!(
|
||||
"Error executing command returned an error: {}. Aborting script",
|
||||
e
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
None => {
|
||||
Err(anyhow!("Not enough argumentss"))
|
||||
},
|
||||
}
|
||||
None => Err(anyhow!("Not enough argumentss")),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,37 +187,6 @@ impl Command for ExecFile {
|
|||
}
|
||||
}
|
||||
|
||||
fn eval(input: String) -> Result<Vec<(String,Option<Vec<String>>)>, anyhow::Error> {
|
||||
if input.trim().is_empty() {
|
||||
return Err(anyhow!("Input was empty"));
|
||||
}
|
||||
|
||||
let pattern = Regex::new(r"[;|\n]").unwrap();
|
||||
let commands: Vec<&str> = pattern.split(&input).collect();
|
||||
let mut evaluted = vec![];
|
||||
|
||||
for command in commands {
|
||||
let command = command.trim();
|
||||
if command.is_empty() {
|
||||
println!("Empty command, skipping.");
|
||||
continue;
|
||||
}
|
||||
|
||||
let tokens = tokenize(command);
|
||||
if tokens.is_empty() {
|
||||
println!("Empty command, skipping.");
|
||||
continue;
|
||||
}
|
||||
let cmd_name = &tokens[0];
|
||||
let args: Option<Vec<String>> = if tokens.len() > 1 {
|
||||
Some(tokens[1..].iter().map(|s| s.to_string()).collect())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
evaluted.push((cmd_name.to_owned(),args));
|
||||
}
|
||||
Ok(evaluted)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CounterCommand {
|
||||
|
@ -251,3 +226,72 @@ impl Command for CounterCommand {
|
|||
String::from("count")
|
||||
}
|
||||
}
|
||||
#[derive(Default)]
|
||||
pub struct PanicCommmand;
|
||||
impl Command for PanicCommmand {
|
||||
fn execute(&self, args: Option<Vec<String>>) -> Result<(), anyhow::Error> {
|
||||
if args.is_some() {
|
||||
let panic_msg = &args.unwrap()[0];
|
||||
panic!("{}", panic_msg)
|
||||
}
|
||||
let option: Option<i32> = None;
|
||||
println!("Unwrapping None: {}", option.unwrap());
|
||||
panic!("Panic command was called")
|
||||
}
|
||||
|
||||
fn undo(&self) {}
|
||||
|
||||
fn redo(&self) {}
|
||||
|
||||
fn get_description(&self) -> String {
|
||||
String::from("causes a panic with your provided message")
|
||||
}
|
||||
|
||||
fn get_name(&self) -> String {
|
||||
String::from("panic")
|
||||
}
|
||||
|
||||
fn get_help(&self) -> String {
|
||||
String::from("")
|
||||
}
|
||||
|
||||
fn get_params(&self) -> String {
|
||||
String::from("optional: panic msg")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
fn eval(input: String) -> Result<Vec<(String,Option<Vec<String>>)>, anyhow::Error> {
|
||||
if input.trim().is_empty() {
|
||||
return Err(anyhow!("Input was empty"));
|
||||
}
|
||||
|
||||
let pattern = Regex::new(r"[;|\n]").unwrap();
|
||||
let commands: Vec<&str> = pattern.split(&input).collect();
|
||||
let mut evaluted = vec![];
|
||||
|
||||
for command in commands {
|
||||
let command = command.trim();
|
||||
if command.is_empty() {
|
||||
println!("Empty command, skipping.");
|
||||
continue;
|
||||
}
|
||||
|
||||
let tokens = tokenize(command);
|
||||
if tokens.is_empty() {
|
||||
println!("Empty command, skipping.");
|
||||
continue;
|
||||
}
|
||||
let cmd_name = &tokens[0];
|
||||
let args: Option<Vec<String>> = if tokens.len() > 1 {
|
||||
Some(tokens[1..].iter().map(|s| s.to_string()).collect())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
evaluted.push((cmd_name.to_owned(),args));
|
||||
}
|
||||
Ok(evaluted)
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ macro_rules! alias {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
fn hamming_distance(a: &str, b: &str) -> Option<usize> {
|
||||
if a.len() != b.len() {
|
||||
return None;
|
||||
|
@ -92,6 +91,7 @@ fn check_similarity(target: &str) -> Option<String> {
|
|||
pub struct CommandManager {
|
||||
pub commands: HashMap<String, Box<dyn Command>>,
|
||||
pub aliases: HashMap<String, String>,
|
||||
pub categories: HashMap<String, Category>,
|
||||
}
|
||||
|
||||
impl CommandManager {
|
||||
|
@ -99,24 +99,33 @@ impl CommandManager {
|
|||
CommandManager {
|
||||
commands: HashMap::new(),
|
||||
aliases: HashMap::new(),
|
||||
categories: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_category(&mut self, category: Category) {
|
||||
self.categories.insert(category.name.clone(), category);
|
||||
}
|
||||
|
||||
pub fn get_commands(&self) -> std::collections::hash_map::Iter<'_, String, Box<dyn Command>> {
|
||||
self.commands.iter()
|
||||
}
|
||||
pub fn execute_command(&self,command: &str,args: Option<Vec<String>>) -> Result<(),anyhow::Error> {
|
||||
|
||||
pub fn execute_command(
|
||||
&self,
|
||||
command: &str,
|
||||
args: Option<Vec<String>>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
if let Some(command) = self.commands.get(command) {
|
||||
command.execute(args)?;
|
||||
Ok(())
|
||||
} else {
|
||||
println!("Command '{}' not found.", command);
|
||||
let corrected_cmd = check_similarity(command);
|
||||
if corrected_cmd.is_some() {
|
||||
println!("Command: {} was not found. Did you mean {}?",command.red().bold(),corrected_cmd
|
||||
.expect("A command was editied during execution, something has gone seriously wrong").green().bold().italic());
|
||||
return Ok(());
|
||||
}
|
||||
Ok(())
|
||||
Err(anyhow::anyhow!("Command '{}' not found.", command))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,16 +136,53 @@ impl CommandManager {
|
|||
None => {
|
||||
self.execute_command(command, args)?;
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_command(&mut self, command: Box<dyn Command>) {
|
||||
self.commands.insert(command.get_name().to_lowercase(), command);
|
||||
self.commands
|
||||
.insert(command.get_name().to_lowercase(), command);
|
||||
}
|
||||
|
||||
pub fn add_command_with_category(&mut self, command: Box<dyn Command>, category: Category) {
|
||||
if self.categories.contains_key(&category.name) {
|
||||
let mut cmd_name = command.get_name().to_lowercase();
|
||||
cmd_name.insert_str(0, &format!("{}_", &&category.uid.to_lowercase()));
|
||||
println!("{}", cmd_name);
|
||||
self.commands.insert(cmd_name, command);
|
||||
} else {
|
||||
panic!("Category {} does not exist", category.name);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_alias(&mut self, alias: &str, command: &str) {
|
||||
self.aliases.insert(alias.to_string(), command.to_string());
|
||||
self.aliases.insert(
|
||||
alias.to_string().to_lowercase(),
|
||||
command.to_string().to_lowercase(),
|
||||
);
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Category {
|
||||
// eg: Zenyx -> Z
|
||||
// eg: core -> cr
|
||||
// eg: exitcmd -> cr_exit
|
||||
// eg: echo -> z_echo
|
||||
pub uid: String,
|
||||
// eg: Zenyx
|
||||
pub name: String,
|
||||
// eg: Zenyx internal commands
|
||||
pub description: String,
|
||||
}
|
||||
|
||||
impl Category {
|
||||
pub fn new(uid: &str, name: &str, description: &str) -> Self {
|
||||
Self {
|
||||
uid: uid.to_string(),
|
||||
name: name.to_string(),
|
||||
description: description.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -163,7 +163,7 @@ pub fn evaluate_command(input: &str) -> anyhow::Result<()> {
|
|||
};
|
||||
match COMMAND_MANAGER.read().execute(cmd_name, args) {
|
||||
Ok(_) => continue,
|
||||
Err(e) => return Err(e)
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
@ -1,12 +1,23 @@
|
|||
use commands::{ClearCommand, CounterCommand, ExecFile, ExitCommand, HelpCommand};
|
||||
use commands::{ClearCommand, CounterCommand, ExecFile, ExitCommand, HelpCommand, PanicCommmand};
|
||||
use handler::{COMMAND_MANAGER, Category};
|
||||
|
||||
use crate::commands;
|
||||
|
||||
pub mod commands;
|
||||
pub mod input;
|
||||
pub mod handler;
|
||||
|
||||
pub mod input;
|
||||
|
||||
pub fn setup() {
|
||||
commands!(HelpCommand,ClearCommand,ExitCommand,ExecFile,CounterCommand);
|
||||
commands!(
|
||||
HelpCommand,
|
||||
ClearCommand,
|
||||
ExitCommand,
|
||||
CounterCommand,
|
||||
PanicCommmand
|
||||
);
|
||||
let cat = Category::new("cr", "Core", "Core commands");
|
||||
COMMAND_MANAGER.write().add_category(cat.clone());
|
||||
COMMAND_MANAGER
|
||||
.write()
|
||||
.add_command_with_category(Box::new(ExecFile), cat.clone());
|
||||
}
|
||||
|
|
17
engine/src/core/workspace/mod.rs
Normal file
17
engine/src/core/workspace/mod.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{Context, Result, anyhow};
|
||||
|
||||
pub fn get_working_dir() -> Result<PathBuf> {
|
||||
let mut dir = dirs_next::data_dir()
|
||||
.ok_or(anyhow!("Expected working directory, found: None"))
|
||||
.context("Could not fetch working dir")?;
|
||||
dir.push("Zenyx");
|
||||
Ok(dir)
|
||||
}
|
||||
|
||||
pub fn get_data_dir() -> Result<PathBuf> {
|
||||
let mut dir = get_working_dir().context("Failed to obtain working dir")?;
|
||||
dir.push("data");
|
||||
Ok(dir)
|
||||
}
|
|
@ -1,18 +1,33 @@
|
|||
use core::{repl::{handler::COMMAND_MANAGER, input::handle_repl, setup}, splash};
|
||||
#![feature(panic_payload_as_str)]
|
||||
use core::{
|
||||
panic::set_panic_hook,
|
||||
repl::{handler::COMMAND_MANAGER, setup},
|
||||
splash, workspace,
|
||||
};
|
||||
|
||||
use anyhow::Ok;
|
||||
|
||||
use colored::Colorize;
|
||||
use tokio::runtime;
|
||||
|
||||
pub mod core;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
fn main() -> anyhow::Result<()> {
|
||||
if !cfg!(debug_assertions) {
|
||||
println!("{}", "Debug mode disabled".bright_blue());
|
||||
set_panic_hook();
|
||||
}
|
||||
let runtime = runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()?;
|
||||
|
||||
runtime.block_on(async {
|
||||
setup();
|
||||
splash::print_splash();
|
||||
COMMAND_MANAGER.read().execute("help", None)?;
|
||||
let t = tokio::spawn(handle_repl());
|
||||
|
||||
let t = tokio::spawn(core::repl::input::handle_repl());
|
||||
t.await??;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
|
||||
|
|
|
@ -1,7 +1 @@
|
|||
count;count;count;count;count;count;count;count;count;count;count;count;count;count;count;count;count;count;count;count;count;count
|
||||
|
||||
count
|
||||
help
|
||||
|
||||
|
||||
exit 102
|
||||
cr_exec ./test.zensh
|
||||
|
|
1
main.zensh
Normal file
1
main.zensh
Normal file
|
@ -0,0 +1 @@
|
|||
exit "test"
|
|
@ -6,3 +6,10 @@ edition = "2024"
|
|||
[dependencies]
|
||||
anyhow = "1.0.94"
|
||||
thiserror = "2.0.8"
|
||||
parking_lot.workspace = true
|
||||
|
||||
[profile.dev]
|
||||
debug-assertions = true
|
||||
|
||||
[profile.release]
|
||||
debug-assertions = false
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use thiserror::Error;
|
||||
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug,Error)]
|
||||
enum ZError {
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error)
|
||||
|
||||
}
|
||||
|
||||
|
|
11
test.zensh
11
test.zensh
|
@ -1,11 +0,0 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
echo "Hello World"
|
||||
echo "hello world"; hello
|
Loading…
Add table
Add a link
Reference in a new issue