diff --git a/src/app.rs b/src/app.rs index dd21da9..c03ce08 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use crate::cmds::{Command, args_optional, raw_args}; use crate::cfg::*; -use crate::help::{build_help, help_entity_type}; +use crate::help::{build_help, build_app_help_msg, help_entity_type, app_help_handler, print_command_help}; pub struct App { name: String, @@ -18,57 +18,21 @@ impl App { } pub fn build_help_msg(&self) -> String { - let author = &self.author; - let license = &self.license; - let aim = &self.aim; - let name = &self.name; - - let mut help_msg = String::new(); - help_msg.push_str(&format!("{}\n", family_statement)); - help_msg.push_str(&format!("This App is developed by {} and distributed under {}.\n", author, license)); - help_msg.push_str(&format!("aim: {}\n", aim)); - help_msg.push_str(&format!("usage: {} [...]\n", name)); - help_msg.push_str("operations:\n"); - - for cmd in &self.commands { - let cmd_short_name = cmd.short_name(); - let cmd_long_name = cmd.long_name(); - let args_info = match &cmd.args_optional { - args_optional::Optional => " [args] [optional_arguments]", - args_optional::Required => " ", - args_optional::NoArgs => "", - }; - help_msg.push_str(&format!(" {} {{{} {}}}{} {}\n", - name, cmd_short_name, cmd_long_name, args_info, cmd.description)); - } - - help_msg.push_str("\nuse 'Command {-h --help}' with an operation for available options.\n"); - help_msg + build_app_help_msg(&self.name, &self.author, &self.license, &self.aim, &self.commands) } fn app_help_handler(&self, targets: Vec) { - //考虑无参数也就是应该输出app自身的帮助信息 - if targets.len() == 0 { - let help_msg = self.build_help_msg(); - println_compat(&help_msg); - } - for cmd in targets { - //这里应该根据cmd的名称拿到帮助信息 - for cmd_entity in &self.commands { - if cmd_entity.matches(&cmd) { // [AI修改-需学习] 使用matches方法统一匹配 - let help_msg = cmd_entity.build_help_msg(); - println_compat(&help_msg); - } - } - } + let help_msg = self.build_help_msg(); + app_help_handler(&help_msg, &self.commands, targets); } /// 注意逻辑严谨项:依赖不存在的指令,这是有些离谱的,这种去怪神人程序员,没那本事老老实实去用ide的改名功能 /// 没事别写互相依赖这种,换个方式实现 /// 我写的逻辑可能有问题,涉及到cmd名字的地方建议用全名 - pub fn run(self) { - //根据依赖command的顺序运行各个command handler + /// 构建命令执行顺序 + /// 返回: (执行队列, 未找到的命令列表) + fn build_execution_order(&self) -> (Vec, Vec, HashMap>) { //从环境变量中获取参数 let mut args = std::env::args().collect::>(); // 跳过第一个参数(程序名) @@ -116,7 +80,7 @@ impl App { if !proced_queue.contains(cmd_name) { //这些是根部之外的 //搜索这个名为cmd_name的依赖项并确认是否满足 for cmd_entity in &self.commands { - if cmd_entity.matches(cmd_name) { // [AI修改-需学习] 使用matches方法 + if cmd_entity.matches(cmd_name) { // 确认依赖项是否满足 if cmd_entity.critical_dep_command_list.iter().all(|dep_cmd_ref| { proced_queue.iter().any(|proc_name| dep_cmd_ref.matches(proc_name)) @@ -131,14 +95,26 @@ impl App { last_round_queue = proced_queue.clone(); loop_count += 1; } + + // 提取命令参数映射 + let mut cmd_args_map: HashMap> = HashMap::new(); + for (cmd_name, (cmd_args, _)) in &whole_queue { + cmd_args_map.insert(cmd_name.clone(), cmd_args.clone()); + } + + (proced_queue, notfound_queue, cmd_args_map) + } + + /// 执行命令队列 + fn execute_commands(&self, proced_queue: &[String], cmd_args_map: &HashMap>, notfound_queue: &[String]) { //无参数则执行help if proced_queue.is_empty() { self.app_help_handler(vec![]); } // 执行所有已处理的命令 - for cmd_name in &proced_queue { - if let Some((cmd_args, _)) = whole_queue.get(cmd_name) { + for cmd_name in proced_queue { + if let Some(cmd_args) = cmd_args_map.get(cmd_name) { // 查找对应的命令实体并执行handler for cmd_entity in &self.commands { if cmd_entity.matches(cmd_name) { @@ -155,6 +131,12 @@ impl App { } } + pub fn run(self) { + //根据依赖command的顺序运行各个command handler + let (proced_queue, notfound_queue, cmd_args_map) = self.build_execution_order(); + self.execute_commands(&proced_queue, &cmd_args_map, ¬found_queue); + } + pub fn construct(author: String, license: String, aim: String, name: String) -> App { App{ name: name, @@ -178,12 +160,7 @@ impl App { println_compat(&help_msg); } for cmd in needed_help_args { - for cmd_entity in &app.commands { - if cmd_entity.matches(&cmd) { - let help_msg = cmd_entity.build_help_msg(); - println_compat(&help_msg); - } - } + print_command_help(&app.commands, &cmd); } }; diff --git a/src/help.rs b/src/help.rs index 57d7813..43e972d 100644 --- a/src/help.rs +++ b/src/help.rs @@ -1,4 +1,4 @@ -use crate::cfg::{cmd_flag, display_in_a_line_args}; +use crate::cfg::{cmd_flag, display_in_a_line_args, family_statement, println_compat}; use crate::cmds::{args_optional, Command, CommandRef}; impl Command { @@ -63,3 +63,47 @@ pub fn build_help(who_type: help_entity_type, help_info_prov: Box String { + let mut help_msg = String::new(); + help_msg.push_str(&format!("{}\n", family_statement)); + help_msg.push_str(&format!("This App is developed by {} and distributed under {}.\n", author, license)); + help_msg.push_str(&format!("aim: {}\n", aim)); + help_msg.push_str(&format!("usage: {} [...]\n", name)); + help_msg.push_str("operations:\n"); + + for cmd in commands { + let cmd_short_name = cmd.short_name(); + let cmd_long_name = cmd.long_name(); + let args_info = match &cmd.args_optional { + args_optional::Optional => " [args] [optional_arguments]", + args_optional::Required => " ", + args_optional::NoArgs => "", + }; + help_msg.push_str(&format!(" {} {{{} {}}}{} {}\n", + name, cmd_short_name, cmd_long_name, args_info, cmd.description)); + } + + help_msg.push_str("\nuse 'Command {-h --help}' with an operation for available options.\n"); + help_msg +} + +pub fn print_command_help(commands: &[Command], cmd_name: &str) { + for cmd_entity in commands { + if cmd_entity.matches(cmd_name) { + let help_msg = cmd_entity.build_help_msg(); + println_compat(&help_msg); + } + } +} + +pub fn app_help_handler(app_help_msg: &str, commands: &[Command], targets: Vec) { + //考虑无参数也就是应该输出app自身的帮助信息 + if targets.len() == 0 { + println_compat(app_help_msg); + } + for cmd in targets { + //这里应该根据cmd的名称拿到帮助信息 + print_command_help(commands, &cmd); + } +} diff --git a/src/lib.rs b/src/lib.rs index 660cc2f..9ec1f75 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -pub mod app; pub mod cmds; mod cfg; mod help; +pub mod app; diff --git a/src/source.rs b/src/source.rs new file mode 100644 index 0000000..057745f --- /dev/null +++ b/src/source.rs @@ -0,0 +1,15 @@ +//Copyright (c) [2026] [S.A. @SNOWARE SALflake@aliyun.com] +// [swpk::CmdEngine] is licensed under Mulan PubL v2. +// You can use this software according to the terms and conditions of the Mulan PubL v2. +// You may obtain a copy of Mulan PubL v2 at: +// http://license.coscl.org.cn/MulanPubL-2.0 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PubL v2 for more details + +// This file has been split into separate modules: +// - cfg.rs: Configuration constants +// - cmds.rs: Command and CommandRef definitions +// - help.rs: Help system implementation +// - app.rs: App structure and logic \ No newline at end of file