diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-05-09 16:42:50 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-05-09 17:13:35 +0800 |
| commit | 10bc4ca7a4b3f14cfb57bf72a6da8aaa1490acf3 (patch) | |
| tree | 8b985dad38cfcd4c88af962b3e163131b258a381 /mingling_core/src/program.rs | |
| parent | 89b5132b8c17b6eba45b1bd49aa18b0c02016387 (diff) | |
Add lifecycle hooks to program execution
Diffstat (limited to 'mingling_core/src/program.rs')
| -rw-r--r-- | mingling_core/src/program.rs | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/mingling_core/src/program.rs b/mingling_core/src/program.rs index 4d943cf..0d23770 100644 --- a/mingling_core/src/program.rs +++ b/mingling_core/src/program.rs @@ -11,6 +11,7 @@ use crate::{ AnyOutput, ChainProcess, GlobalResources, Groupped, RenderResult, asset::dispatcher::Dispatcher, error::{ChainProcessError, ProgramExecuteError}, + hook::{ProgramAnonymousHook, ProgramHook}, }; use std::{ collections::HashMap, @@ -24,6 +25,8 @@ use std::pin::Pin; #[doc(hidden)] pub mod exec; #[doc(hidden)] +pub mod hook; +#[doc(hidden)] pub mod setup; mod config; @@ -41,7 +44,7 @@ static THIS_PROGRAM: OnceLock<Option<Box<dyn std::any::Any + Send + Sync>>> = On /// Returns a reference to the current program instance, panics if not set. pub fn this<C>() -> &'static Program<C> where - C: ProgramCollect + 'static, + C: ProgramCollect<Enum = C> + 'static, { try_get_this_program().expect("Program not initialized") } @@ -49,7 +52,7 @@ where /// Returns a reference to the current program instance, if set. fn try_get_this_program<C>() -> Option<&'static Program<C>> where - C: ProgramCollect + 'static, + C: ProgramCollect<Enum = C> + 'static, { THIS_PROGRAM.get()?.as_ref()?.downcast_ref::<Program<C>>() } @@ -58,7 +61,7 @@ where #[derive(Default)] pub struct Program<C> where - C: ProgramCollect, + C: ProgramCollect<Enum = C>, { pub(crate) collect: std::marker::PhantomData<C>, @@ -73,6 +76,9 @@ where #[cfg(feature = "general_renderer")] pub general_renderer_name: GeneralRendererSetting, + pub(crate) hooks: Vec<ProgramHook<C>>, + pub(crate) anonymous_hooks: Vec<ProgramAnonymousHook>, + pub(crate) resources: GlobalResources, } @@ -113,6 +119,9 @@ where #[cfg(feature = "general_renderer")] general_renderer_name: GeneralRendererSetting::Disable, + hooks: Vec::new(), + anonymous_hooks: Vec::new(), + resources: Arc::new(Mutex::new(HashMap::new())), } } @@ -167,7 +176,7 @@ where #[cfg(feature = "async")] impl<C> Program<C> where - C: ProgramCollect<Enum = C>, + C: ProgramCollect<Enum = C> + std::fmt::Display, { /// Sets the current program instance and runs the provided async function. async fn set_instance_and_run<F, Fut>(self, f: F) -> Fut::Output @@ -237,7 +246,7 @@ where #[cfg(not(feature = "async"))] impl<C> Program<C> where - C: ProgramCollect<Enum = C>, + C: ProgramCollect<Enum = C> + Display, { /// Sets the current program instance and runs the provided function. fn set_instance_and_run<F, R>(self, f: F) -> R @@ -266,7 +275,7 @@ where } /// Run the command line program - pub fn exec(self) + pub fn exec(self) -> i32 where C: 'static + Send + Sync, { @@ -276,29 +285,44 @@ where Err(e) => match e { ProgramExecuteError::DispatcherNotFound => { eprintln!("Dispatcher not found"); - return; + return 1; } ProgramExecuteError::RendererNotFound(renderer_name) => { eprintln!("Renderer `{}` not found", renderer_name); - return; + return 1; } ProgramExecuteError::Other(e) => { eprintln!("{}", e); - return; + return 1; } }, }; // Render result if stdout_setting.render_output && !result.is_empty() { + let exit_code = result.exit_code; print!("{}", result); + if let Err(e) = std::io::Write::flush(&mut std::io::stdout()) && stdout_setting.error_output { eprintln!("{}", e); + 1 + } else { + exit_code } + } else { + 0 } } + + /// Run the command line program, then exit + pub fn exec_and_exit(self) + where + C: 'static + Send + Sync, + { + std::process::exit(self.exec()) + } } /// Collected program context |
