From d19e5d84ee21502fd3440511d4ffb1ee1f49d3b2 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Wed, 4 Feb 2026 00:27:16 +0800 Subject: Refactor build system and implement complete renderer system - Split monolithic build.rs into modular async generators - Add renderer override system with type-safe dispatch - Implement command template macro for consistent command definitions - Add proc-macro crates for command and renderer systems - Reorganize directory structure for better separation of concerns - Update documentation to reflect new architecture --- src/systems/cmd/cmd_system.rs | 106 ++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 44 deletions(-) (limited to 'src/systems/cmd/cmd_system.rs') diff --git a/src/systems/cmd/cmd_system.rs b/src/systems/cmd/cmd_system.rs index 20f5aef..030e711 100644 --- a/src/systems/cmd/cmd_system.rs +++ b/src/systems/cmd/cmd_system.rs @@ -1,64 +1,88 @@ -use serde::Serialize; - use crate::{ r_println, - systems::cmd::{ - errors::{CmdExecuteError, CmdPrepareError, CmdProcessError, CmdRenderError}, - renderer::{JVRenderResult, JVResultRenderer}, + systems::{ + cmd::errors::{CmdExecuteError, CmdPrepareError, CmdProcessError, CmdRenderError}, + render::{render_system::render, renderer::JVRenderResult}, }, }; -use std::future::Future; +use std::{ + any::{Any, TypeId}, + collections::HashMap, + future::Future, +}; pub struct JVCommandContext { pub help: bool, pub confirmed: bool, } -pub trait JVCommand +pub trait JVCommand where Argument: clap::Parser + Send, Input: Send, - Output: Serialize + Send + Sync, Collect: Send, - Renderer: JVResultRenderer + Send + Sync, { /// Get help string for the command fn get_help_str() -> String; - /// Process the command with a specified renderer, performing any necessary post-execution processing - fn process_with_renderer_flag( + /// Run the command and convert the result into type-agnostic serialized information, + /// then hand it over to the universal renderer for rendering. + /// Universal renderer: uses the renderer specified by the `--renderer` flag. + fn process_to_renderer_override( args: Vec, ctx: JVCommandContext, - renderer: String, - ) -> impl Future> + Send - where - Self: Sync, - { + renderer_override: String, + ) -> impl Future> + Send { async move { - let renderer_str = renderer.as_str(); - include!("_renderers.rs") + // If the `--help` flag is used, + // skip execution and return an error, + // unlike `process_to_render_system`, + // when the `--renderer` flag specifies a renderer, `--help` output is not allowed + if ctx.help { + return Err(CmdProcessError::RendererOverrideButRequestHelp); + } + + let (data, type_name) = Self::process(args, ctx).await?; + + let renderer_override = renderer_override.as_str(); + + // Serialize the data based on its concrete type + let render_result = include!("../render/_override_renderer_entry.rs"); + + match render_result { + Ok(r) => Ok(r), + Err(e) => Err(CmdProcessError::Render(e)), + } } } - /// performing any necessary post-execution processing - fn process( + /// Run the command and hand it over to the rendering system + /// to select the appropriate renderer for the result + fn process_to_render_system( args: Vec, ctx: JVCommandContext, - ) -> impl Future> + Send - where - Self: Sync, - { - Self::process_with_renderer::(args, ctx) + ) -> impl Future> + Send { + async { + // If the `--help` flag is used, + // skip execution and directly render help information + if ctx.help { + let mut r = JVRenderResult::default(); + r_println!(r, "{}", Self::get_help_str()); + return Ok(r); + } + + let (data, id_str) = Self::process(args, ctx).await?; + match render(data, id_str).await { + Ok(r) => Ok(r), + Err(e) => Err(CmdProcessError::Render(e)), + } + } } - /// Process the command output with a custom renderer, - /// performing any necessary post-execution processing - fn process_with_renderer + Send>( + fn process( args: Vec, ctx: JVCommandContext, - ) -> impl Future> + Send - where - Self: Sync, + ) -> impl Future, String), CmdProcessError>> + Send { async move { let mut full_args = vec!["jv".to_string()]; @@ -70,13 +94,6 @@ where Err(_) => return Err(CmdProcessError::ParseError(Self::get_help_str())), }; - // If the help flag is used, skip execution and directly print help - if ctx.help { - let mut r = JVRenderResult::default(); - r_println!(r, "{}", Self::get_help_str()); - return Ok(r); - } - let (input, collect) = match tokio::try_join!( Self::prepare(&parsed_args, &ctx), Self::collect(&parsed_args, &ctx) @@ -85,17 +102,15 @@ where Err(e) => return Err(CmdProcessError::from(e)), }; - let output = match Self::exec(input, collect).await { + let data = match Self::exec(input, collect).await { Ok(output) => output, Err(e) => return Err(CmdProcessError::from(e)), }; - match R::render(&output).await { - Ok(r) => Ok(r), - Err(e) => Err(CmdProcessError::from(e)), - } + Ok(data) } } + /// Prepare /// Converts Argument input into parameters readable during the execution phase fn prepare( @@ -116,5 +131,8 @@ where fn exec( input: Input, collect: Collect, - ) -> impl Future> + Send; + ) -> impl Future, String), CmdExecuteError>> + Send; + + /// Get output type mapping + fn get_output_type_mapping() -> HashMap; } -- cgit