splited
This commit is contained in:
+29
-52
@@ -1,7 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use crate::cmds::{Command, args_optional, raw_args};
|
use crate::cmds::{Command, args_optional, raw_args};
|
||||||
use crate::cfg::*;
|
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 {
|
pub struct App {
|
||||||
name: String,
|
name: String,
|
||||||
@@ -18,57 +18,21 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_help_msg(&self) -> String {
|
pub fn build_help_msg(&self) -> String {
|
||||||
let author = &self.author;
|
build_app_help_msg(&self.name, &self.author, &self.license, &self.aim, &self.commands)
|
||||||
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: {} <operation> [...]\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> <required_arguments>",
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app_help_handler(&self, targets: Vec<String>) {
|
fn app_help_handler(&self, targets: Vec<String>) {
|
||||||
//考虑无参数也就是应该输出app自身的帮助信息
|
let help_msg = self.build_help_msg();
|
||||||
if targets.len() == 0 {
|
app_help_handler(&help_msg, &self.commands, targets);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 注意逻辑严谨项:依赖不存在的指令,这是有些离谱的,这种去怪神人程序员,没那本事老老实实去用ide的改名功能
|
/// 注意逻辑严谨项:依赖不存在的指令,这是有些离谱的,这种去怪神人程序员,没那本事老老实实去用ide的改名功能
|
||||||
/// 没事别写互相依赖这种,换个方式实现
|
/// 没事别写互相依赖这种,换个方式实现
|
||||||
/// 我写的逻辑可能有问题,涉及到cmd名字的地方建议用全名
|
/// 我写的逻辑可能有问题,涉及到cmd名字的地方建议用全名
|
||||||
pub fn run(self) {
|
/// 构建命令执行顺序
|
||||||
//根据依赖command的顺序运行各个command handler
|
/// 返回: (执行队列, 未找到的命令列表)
|
||||||
|
fn build_execution_order(&self) -> (Vec<String>, Vec<String>, HashMap<String, Vec<String>>) {
|
||||||
//从环境变量中获取参数
|
//从环境变量中获取参数
|
||||||
let mut args = std::env::args().collect::<Vec<String>>();
|
let mut args = std::env::args().collect::<Vec<String>>();
|
||||||
// 跳过第一个参数(程序名)
|
// 跳过第一个参数(程序名)
|
||||||
@@ -116,7 +80,7 @@ impl App {
|
|||||||
if !proced_queue.contains(cmd_name) { //这些是根部之外的
|
if !proced_queue.contains(cmd_name) { //这些是根部之外的
|
||||||
//搜索这个名为cmd_name的依赖项并确认是否满足
|
//搜索这个名为cmd_name的依赖项并确认是否满足
|
||||||
for cmd_entity in &self.commands {
|
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| {
|
if cmd_entity.critical_dep_command_list.iter().all(|dep_cmd_ref| {
|
||||||
proced_queue.iter().any(|proc_name| dep_cmd_ref.matches(proc_name))
|
proced_queue.iter().any(|proc_name| dep_cmd_ref.matches(proc_name))
|
||||||
@@ -131,14 +95,26 @@ impl App {
|
|||||||
last_round_queue = proced_queue.clone();
|
last_round_queue = proced_queue.clone();
|
||||||
loop_count += 1;
|
loop_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 提取命令参数映射
|
||||||
|
let mut cmd_args_map: HashMap<String, Vec<String>> = 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<String, Vec<String>>, notfound_queue: &[String]) {
|
||||||
//无参数则执行help
|
//无参数则执行help
|
||||||
if proced_queue.is_empty() {
|
if proced_queue.is_empty() {
|
||||||
self.app_help_handler(vec![]);
|
self.app_help_handler(vec![]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行所有已处理的命令
|
// 执行所有已处理的命令
|
||||||
for cmd_name in &proced_queue {
|
for cmd_name in proced_queue {
|
||||||
if let Some((cmd_args, _)) = whole_queue.get(cmd_name) {
|
if let Some(cmd_args) = cmd_args_map.get(cmd_name) {
|
||||||
// 查找对应的命令实体并执行handler
|
// 查找对应的命令实体并执行handler
|
||||||
for cmd_entity in &self.commands {
|
for cmd_entity in &self.commands {
|
||||||
if cmd_entity.matches(cmd_name) {
|
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 {
|
pub fn construct(author: String, license: String, aim: String, name: String) -> App {
|
||||||
App{
|
App{
|
||||||
name: name,
|
name: name,
|
||||||
@@ -178,12 +160,7 @@ impl App {
|
|||||||
println_compat(&help_msg);
|
println_compat(&help_msg);
|
||||||
}
|
}
|
||||||
for cmd in needed_help_args {
|
for cmd in needed_help_args {
|
||||||
for cmd_entity in &app.commands {
|
print_command_help(&app.commands, &cmd);
|
||||||
if cmd_entity.matches(&cmd) {
|
|
||||||
let help_msg = cmd_entity.build_help_msg();
|
|
||||||
println_compat(&help_msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+45
-1
@@ -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};
|
use crate::cmds::{args_optional, Command, CommandRef};
|
||||||
|
|
||||||
impl Command {
|
impl Command {
|
||||||
@@ -63,3 +63,47 @@ pub fn build_help(who_type: help_entity_type, help_info_prov: Box<dyn Fn(Vec<Str
|
|||||||
handler: help_info_prov
|
handler: help_info_prov
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn build_app_help_msg(name: &str, author: &str, license: &str, aim: &str, commands: &[Command]) -> 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: {} <operation> [...]\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> <required_arguments>",
|
||||||
|
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<String>) {
|
||||||
|
//考虑无参数也就是应该输出app自身的帮助信息
|
||||||
|
if targets.len() == 0 {
|
||||||
|
println_compat(app_help_msg);
|
||||||
|
}
|
||||||
|
for cmd in targets {
|
||||||
|
//这里应该根据cmd的名称拿到帮助信息
|
||||||
|
print_command_help(commands, &cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
pub mod app;
|
|
||||||
pub mod cmds;
|
pub mod cmds;
|
||||||
mod cfg;
|
mod cfg;
|
||||||
mod help;
|
mod help;
|
||||||
|
pub mod app;
|
||||||
|
|||||||
@@ -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
|
||||||
Reference in New Issue
Block a user