From 240361b240d638363346013160b0943b47769c37 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Wed, 8 Apr 2026 22:48:31 +0800 Subject: Implement mingling::this function --- mingling_core/src/program.rs | 75 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 5 deletions(-) (limited to 'mingling_core/src/program.rs') diff --git a/mingling_core/src/program.rs b/mingling_core/src/program.rs index 0a24001..8c8b4cb 100644 --- a/mingling_core/src/program.rs +++ b/mingling_core/src/program.rs @@ -4,7 +4,7 @@ use crate::{ AnyOutput, ChainProcess, RenderResult, asset::dispatcher::Dispatcher, error::ProgramExecuteError, }; -use std::{env, fmt::Display, pin::Pin}; +use std::{env, fmt::Display, pin::Pin, sync::OnceLock}; #[doc(hidden)] pub mod exec; @@ -18,6 +18,28 @@ mod flag; pub use flag::*; use tokio::io::AsyncWriteExt; +/// Global static reference to the current program instance +static THIS_PROGRAM: OnceLock>> = OnceLock::new(); + +/// Returns a reference to the current program instance, panics if not set. +pub fn this() -> &'static Program +where + C: ProgramCollect + Display + 'static, +{ + try_get_this_program().expect("Program not initialized") +} + +/// Returns a reference to the current program instance, if set. +fn try_get_this_program() -> Option<&'static Program> +where + C: ProgramCollect + Display + 'static, +{ + THIS_PROGRAM + .get()? + .as_ref()? + .downcast_ref::>() +} + /// Program, used to define the behavior of the entire command-line program #[derive(Default)] pub struct Program @@ -29,7 +51,7 @@ where pub(crate) group: std::marker::PhantomData, pub(crate) args: Vec, - pub(crate) dispatcher: Vec>>, + pub(crate) dispatcher: Vec + Send + Sync>>, pub stdout_setting: ProgramStdoutSetting, pub user_context: ProgramUserContext, @@ -58,14 +80,57 @@ where } } + /// Returns a reference to the current program instance, if set. + pub async fn this_program() -> &'static Program + where + C: 'static, + G: 'static, + { + THIS_PROGRAM + .get() + .unwrap() + .as_ref() + .unwrap() + .downcast_ref::>() + .unwrap() + } + + /// Sets the current program instance and runs the provided async function. + async fn set_instance_and_run(self, f: F) -> Fut::Output + where + C: 'static + Send + Sync, + G: 'static + Send + Sync, + F: FnOnce(&'static Program) -> Fut + Send + Sync, + Fut: Future + Send, + { + THIS_PROGRAM.get_or_init(|| Some(Box::new(self))); + let program = THIS_PROGRAM + .get() + .unwrap() + .as_ref() + .unwrap() + .downcast_ref::>() + .unwrap(); + f(program).await + } + /// Run the command line program - pub async fn exec_without_render(mut self) -> Result { + pub async fn exec_without_render(mut self) -> Result + where + C: 'static + Send + Sync, + G: 'static + Send + Sync, + { self.args = self.args.iter().skip(1).cloned().collect(); - crate::exec::exec(self).await.map_err(|e| e.into()) + self.set_instance_and_run(|p| async { crate::exec::exec(p).await.map_err(|e| e.into()) }) + .await } /// Run the command line program - pub async fn exec(self) { + pub async fn exec(self) + where + C: 'static + Send + Sync, + G: 'static + Send + Sync, + { let stdout_setting = self.stdout_setting.clone(); let result = match self.exec_without_render().await { Ok(r) => r, -- cgit