use crate::action::Action;
use crate::args::{Args, ArgsNew};
use crate::cmd::subc::ExternSubc;
use std::collections::HashMap;
use std::env;
pub mod subc;
pub struct ActionApp {
pub command: String, pub alias: Vec<String>,
pub action: Box<dyn Action>,
}
pub type CmdCallOption = Option<Box<dyn FnMut(&Args)>>;
pub type CmdCallMap = HashMap<String, Box<dyn FnMut(&Args)>>;
pub struct Cmd {
raw_args: Vec<String>, calls: CmdCallMap, actions: Vec<ActionApp>, action_default: CmdCallOption, action_no_handler: CmdCallOption, args: Option<Args>,
cmd_alias: Option<HashMap<String, Vec<String>>>, }
pub fn get_os_args() -> Vec<String> {
let mut args: Vec<String> = Vec::new();
let mut idx = 0;
for arg in env::args() {
if idx < 1 {
idx += 1;
continue;
}
args.push(arg);
}
args
}
pub trait CmdRunOs {
fn run(&mut self);
}
pub trait CmdRunArgs {
fn run(&mut self, param: Vec<&str>);
fn register_multi<F>(&mut self, names: Vec<&str>, action: F) -> &mut Self
where
F: FnMut(&Args) + 'static;
}
pub trait CmdRunStr {
fn run(&mut self, param: &str);
}
pub trait CmdRunString {
fn run(&mut self, param: Vec<String>);
fn register_multi<F>(&mut self, names: Vec<String>, action: F) -> &mut Self
where
F: FnMut(&Args) + 'static;
}
impl Cmd {
pub fn new() -> Cmd {
Cmd {
..Default::default()
}
}
fn get_os_args(&mut self) {
self.raw_args = get_os_args();
}
fn parse_args(&mut self) {
if self.raw_args.is_empty() {
self.get_os_args()
}
if self.args.is_none() {
let args = Args::new(&self.raw_args);
self.args = Some(args);
}
}
fn set_args(&mut self, args: Args) -> &mut Cmd {
self.args = Some(args);
self
}
pub fn register<F>(&mut self, name: &str, action: F) -> &mut Cmd
where
F: FnMut(&Args) + 'static,
{
self.calls.insert(String::from(name), Box::new(action));
self
}
pub fn registers<F>(&mut self, names: Vec<&str>, action: F) -> &mut Self
where
F: FnMut(&Args) + 'static,
{
self.try_register_multi(names, action)
}
pub fn register_action(&mut self, app: ActionApp) -> &mut Cmd {
self.actions.push(app);
self
}
pub fn empty<F>(&mut self, action: F) -> &mut Cmd
where
F: FnMut(&Args) + 'static,
{
self.action_default = Some(Box::new(action));
self
}
pub fn un_found<F>(&mut self, action: F) -> &mut Cmd
where
F: FnMut(&Args) + 'static,
{
self.action_no_handler = Some(Box::new(action));
self
}
pub fn start(&mut self) {
self.parse_args();
self.try_router();
}
fn try_router(&mut self) {
if self.args.is_none() {
println!("因无Args参数,Cmd 运行失败");
return;
}
let args = self.args.as_ref().unwrap();
for (v_key, v_fn) in &mut self.calls {
if args.command == *v_key {
v_fn(args);
return;
}
}
if let Some(cmd_alias) = &self.cmd_alias {
for (ca_key, ca_val) in cmd_alias {
let mut is_match = args.command == *ca_key.as_str();
if !is_match {
for cv in ca_val {
if args.command == *cv.as_str() {
is_match = true;
break;
}
}
}
if is_match {
if let Some(v_fn) = self.calls.get_mut(ca_key.as_str()) {
v_fn(args);
return;
}
}
}
}
for action in &self.actions {
if action.command == args.command {
action.action.as_ref().run(args);
return;
} else {
for alias in &action.alias {
if *alias == args.command {
action.action.as_ref().run(args);
return;
}
}
}
}
if !args.command.is_empty() {
let es = ExternSubc::new(args.command.clone());
if es.is_valid() {
let raw = args.raw.clone();
let count = raw.len();
let raw = &raw[1..count].to_vec();
let (is_ok, content) = es.run(raw);
if is_ok {
println!("{}", content);
let mut args_chg = args.clone();
args_chg.is_extern_subc = true;
self.args = Some(args_chg);
return;
}
}
}
if let Some(action_no_hdl) = &mut self.action_no_handler {
if !args.command.is_empty() {
action_no_hdl(args);
return;
}
}
if let Some(action_default) = &mut self.action_default {
action_default(args);
} else {
println!("请您至少为 Cmd 应用注册默认方法");
}
}
fn try_register_multi<F>(&mut self, names: Vec<&str>, action: F) -> &mut Self
where
F: FnMut(&Args) + 'static,
{
let v_len = names.len();
if v_len < 1 {
return self;
}
let key = names[0];
self.register(key, action);
let mut cmd_alias: HashMap<String, Vec<String>> = HashMap::new();
if let Some(v_cmd_alias) = &self.cmd_alias {
cmd_alias = v_cmd_alias.clone();
}
let mut values: Vec<String> = Vec::from_iter(names.iter().map(|x| String::from(*x)));
if let Some(old_val) = cmd_alias.get(key) {
for old in old_val {
values.push(old.to_string())
}
}
cmd_alias.insert(String::from(key), values);
self.cmd_alias = Some(cmd_alias);
self
}
}
impl CmdRunOs for Cmd {
fn run(&mut self) {
let args = Args::from_os();
self.set_args(args).start();
}
}
impl CmdRunArgs for Cmd {
fn run(&mut self, param: Vec<&str>) {
let args = Args::new(param);
self.set_args(args).start();
}
fn register_multi<F>(&mut self, names: Vec<&str>, action: F) -> &mut Self
where
F: FnMut(&Args) + 'static,
{
self.try_register_multi(names, action)
}
}
impl CmdRunStr for Cmd {
fn run(&mut self, param: &str) {
let args = Args::from_str(param);
self.set_args(args).start();
}
}
impl CmdRunString for Cmd {
fn run(&mut self, param: Vec<String>) {
let args = Args::new(param);
self.set_args(args).start();
}
fn register_multi<F>(&mut self, names: Vec<String>, action: F) -> &mut Self
where
F: FnMut(&Args) + 'static,
{
let values: Vec<&str> = Vec::from_iter(names.iter().map(|x| x.as_str()));
self.try_register_multi(values, action)
}
}
impl Default for Cmd {
fn default() -> Self {
Cmd {
raw_args: vec![],
calls: Default::default(),
actions: vec![],
action_default: None,
action_no_handler: None,
args: None,
cmd_alias: None,
}
}
}