From 4e688729e6cf4acbd7191a547bfb33f71d5079dd Mon Sep 17 00:00:00 2001 From: eatmynerds Date: Thu, 5 Dec 2024 01:33:44 -0600 Subject: [PATCH] Control logging using key events --- Cargo.toml | 1 - engine/Cargo.toml | 5 +- engine/src/core/repl/commands.rs | 3 - engine/src/core/repl/repl.rs | 99 ++++++++++++++++++++++++++------ engine/src/main.rs | 31 ++-------- engine/src/utils/logger.rs | 7 ++- 6 files changed, 94 insertions(+), 52 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1a67ef2..3d77c9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,5 +32,4 @@ incremental = true codegen-units = 512 [workspace.dependencies] -anyhow = "1.0.93" zephyr = { path = "./subcrates/zephyr" } diff --git a/engine/Cargo.toml b/engine/Cargo.toml index de1bd1a..ac4eabe 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -6,16 +6,15 @@ edition = "2021" [dependencies] anyhow = "1.0.93" chrono = "0.4.38" -clap = { version = "4.5.21", features = ["derive"] } colored = "2.1.0" lazy_static = "1.5.0" log = "0.4.22" once_cell = "1.20.2" parking_lot = "0.12.3" regex = "1.11.1" -rustyline = "15.0.0" +rustyline = { version = "15.0.0", features = ["derive", "rustyline-derive"] } thiserror = "2.0.3" tokio = { version = "1.41.1", features = ["macros", "rt", "rt-multi-thread"] } wgpu = "23.0.1" winit = "0.30.5" -zephyr.workspace = true \ No newline at end of file +zephyr.workspace = true diff --git a/engine/src/core/repl/commands.rs b/engine/src/core/repl/commands.rs index d500ca8..97b95c8 100644 --- a/engine/src/core/repl/commands.rs +++ b/engine/src/core/repl/commands.rs @@ -1,6 +1,5 @@ use super::COMMAND_LIST; use std::process::Command; -use log::debug; pub(crate) fn say_hello() { println!("Hello, World!"); @@ -18,10 +17,8 @@ pub(crate) fn exit() { pub(crate) fn clear() { println!("Clearing screen..., running command"); let _result = if cfg!(target_os = "windows") { - debug!("target_os is windows"); Command::new("cmd").args(["/c", "cls"]).spawn() } else { - debug!("target_os is unix"); Command::new("clear").spawn() }; } diff --git a/engine/src/core/repl/repl.rs b/engine/src/core/repl/repl.rs index 8ac6710..0b983a3 100644 --- a/engine/src/core/repl/repl.rs +++ b/engine/src/core/repl/repl.rs @@ -1,10 +1,68 @@ -use super::{commands, Callable, COMMAND_LIST}; +use crate::{ + core::repl::{commands, Callable, COMMAND_LIST}, + utils::logger::LOGGER, +}; use anyhow::Result; use chrono::Local; use colored::Colorize; use log::debug; use regex::Regex; -use rustyline::DefaultEditor; +use rustyline::{ + error::ReadlineError, highlight::Highlighter, hint::HistoryHinter, history::DefaultHistory, + Cmd, Completer, ConditionalEventHandler, Editor, Event, EventContext, EventHandler, Helper, + Hinter, KeyEvent, RepeatCount, Validator, +}; +use std::{ + borrow::Cow::{self, Borrowed, Owned}, + sync::{Arc, Mutex}, +}; + +#[derive(Completer, Helper, Hinter, Validator)] +struct MyHelper(#[rustyline(Hinter)] HistoryHinter); + +impl Highlighter for MyHelper { + fn highlight_prompt<'b, 's: 'b, 'p: 'b>( + &'s self, + prompt: &'p str, + default: bool, + ) -> Cow<'b, str> { + if default { + Owned(prompt.bright_black().bold().to_string()) + } else { + Borrowed(prompt) + } + } + + fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { + Owned(hint.bold().to_string()) + } +} + +#[derive(Clone)] +struct BacktickEventHandler { + toggle_state: Arc>, // Tracks whether logging is enabled or disabled +} + +impl ConditionalEventHandler for BacktickEventHandler { + fn handle(&self, evt: &Event, _: RepeatCount, _: bool, _: &EventContext) -> Option { + if let Some(k) = evt.get(0) { + if *k == KeyEvent::from('`') { + let mut state = self.toggle_state.lock().unwrap(); + if *state { + LOGGER.write_to_stdout(); + } else { + LOGGER.write_to_file("z.log"); + } + *state = !*state; + Some(Cmd::Noop) + } else { + None + } + } else { + unreachable!() + } + } +} fn register_commands() { COMMAND_LIST.add_command( @@ -42,13 +100,10 @@ fn register_commands() { None, ); - // EXAMPLE - // Adding aliases for commands + // Example of adding aliases for commands COMMAND_LIST.add_alias("clear".to_string(), "cls".to_string()); } - - fn evaluate_command(input: &str) { if input.trim().is_empty() { return; @@ -79,35 +134,43 @@ fn evaluate_command(input: &str) { } } -pub async fn handle_repl() -> rustyline::Result<()> { - let mut line_editor = DefaultEditor::new()?; - if line_editor.load_history("history.txt").is_err() { +pub async fn handle_repl() -> Result<()> { + let mut rl = Editor::::new()?; + rl.set_helper(Some(MyHelper(HistoryHinter::new()))); + + rl.bind_sequence( + KeyEvent::from('`'), + EventHandler::Conditional(Box::new(BacktickEventHandler { + toggle_state: Arc::new(Mutex::new(false)), + })), + ); + + if rl.load_history("history.txt").is_err() { debug!("No previous history."); } - let time = Local::now().format("%H:%M:%S.%3f").to_string(); - let prompt = format!("[{}/{}] {}", time,"SHELL", ">>\t"); + register_commands(); loop { - let sig = line_editor.readline( - &prompt.bright_white() - ); + let time = Local::now().format("%H:%M:%S.%3f").to_string(); + let prompt = format!("[{}/{}] {}", time, "SHELL", ">>\t"); + let sig = rl.readline(&prompt.bright_white()); + match sig { Ok(line) => { - line_editor.add_history_entry(line.as_str())?; + rl.add_history_entry(line.as_str())?; evaluate_command(line.as_str()); } - Err(rustyline::error::ReadlineError::Interrupted) => { + Err(ReadlineError::Interrupted) => { println!("CTRL+C received, exiting..."); std::process::exit(0); } - Err(rustyline::error::ReadlineError::Eof) => { + Err(ReadlineError::Eof) => { println!("Error: CTRL+D pressed. Exiting..."); std::process::exit(0); } Err(err) => { println!("Error: {}", err); - } } } diff --git a/engine/src/main.rs b/engine/src/main.rs index 923c56e..fb575b6 100644 --- a/engine/src/main.rs +++ b/engine/src/main.rs @@ -1,48 +1,27 @@ use anyhow::Result; -use clap::Parser; -use log::{info, warn, LevelFilter}; +use log::LevelFilter; pub mod core; pub mod utils; use utils::{logger::LOGGER, splash::print_splash}; -#[derive(Parser)] -struct Cli { - #[arg(long, short, help = "Enable logging output")] - log: bool, -} - #[tokio::main] async fn main() -> Result<()> { let t = zephyr::add(0, 2); println!("{}", t); - let cli = Cli::parse(); log::set_logger(&*LOGGER).unwrap(); log::set_max_level(LevelFilter::Debug); print_splash(); - if cli.log { - info!("Initializing Engine with logging to stdout enabled"); - - core::init_renderer()?; - } else { - LOGGER.write_to_stdout(); - info!("Initializing Engine with logging to stdout disabled"); - info!("Writing all logs to file z.log"); - - LOGGER.write_to_file("z.log"); - info!("Logging back to file z.log"); + LOGGER.write_to_stdout(); - let shell_thread = tokio::task::spawn(async { - core::repl::repl::handle_repl().await - }); + let shell_thread = tokio::task::spawn(async { core::repl::repl::handle_repl().await }); - core::init_renderer()?; - shell_thread.await??; // LOL - Caz - } + core::init_renderer()?; + let _ = shell_thread.await?; Ok(()) } diff --git a/engine/src/utils/logger.rs b/engine/src/utils/logger.rs index c542396..1830a45 100644 --- a/engine/src/utils/logger.rs +++ b/engine/src/utils/logger.rs @@ -47,7 +47,12 @@ impl DynamicLogger { impl Log for DynamicLogger { fn enabled(&self, metadata: &Metadata) -> bool { - metadata.level() <= Level::Debug + let target = metadata.target(); + let is_relevant_target = target.starts_with("wgpu") + || target.starts_with("winit") + || target.starts_with(env!("CARGO_PKG_NAME")); // Current crate name + + is_relevant_target && metadata.level() <= Level::Debug } fn log(&self, record: &Record) {