use clap::{Arg, Command};
use clap_complete::generate;
use clap_complete::Shell::{Bash, Elvish, Fish, PowerShell, Zsh};
use std::ffi::OsString;
use std::path::{Path, PathBuf};
use std::{env, fs};
use toml::de::from_str;
use crate::base::MmhConfig;
use crate::cmd::{add, connect, list, ping, remove, sftp};
mod base;
mod cmd;
fn get_base_path() -> PathBuf {
let config_path =
Path::new(&env::var("HOME").expect("Failed to get HOME environment variable")).join(".mmh");
if !config_path.exists() {
fs::create_dir_all(&config_path).expect("create base dir error!");
}
config_path
}
fn get_config_path() -> PathBuf {
get_base_path().join("config.toml")
}
fn get_config() -> MmhConfig {
let config_str = fs::read_to_string(get_config_path()).unwrap_or_default();
from_str(&config_str).unwrap()
}
fn cli() -> Command {
Command::new("mmh")
.version("0.1.21")
.about("my manage ssh tools!")
.subcommand_required(true)
.arg_required_else_help(true)
.allow_external_subcommands(true)
.subcommand(Command::new("add").short_flag('a').about("add ssh config"))
.subcommand(
Command::new("list")
.short_flag('l')
.about("list ssh config"),
)
.subcommand(
Command::new("remove")
.short_flag('r')
.about("remove ssh config")
.arg(Arg::new("name").help("server config name ").required(false)),
)
.subcommand(
Command::new("connect")
.short_flag('c')
.about("connect ssh config")
.arg(Arg::new("name").help("server config name ").required(false)),
)
.subcommand(
Command::new("sftp")
.short_flag('s')
.about("sftp connect ssh config")
.arg(Arg::new("name").help("server config name ").required(false))
.arg(Arg::new("remoteDir").help("remote dir").required(false)),
)
.subcommand(
Command::new("ping")
.short_flag('p')
.about("ping ssh config"),
)
.subcommand(
Command::new("copy")
.arg(Arg::new("name").help("server config name "))
.about("copy server config"),
)
.subcommand(Command::new("check").about("check tools!"))
.subcommand(Command::new("init").about("init tools!"))
}
fn main() {
let matches = cli().get_matches();
match matches.subcommand() {
Some(("add", _sub_matches)) => add(),
Some(("list", _sub_matches)) => list(),
Some(("remove", sub_matches)) => {
let name = sub_matches.get_one::<String>("name");
remove(name)
}
Some(("connect", sub_matches)) => {
let name = sub_matches.get_one::<String>("name");
connect(name)
}
Some(("sftp", sub_matches)) => {
let name = sub_matches.get_one::<String>("name");
let remote_dir = sub_matches.get_one::<String>("remoteDir");
sftp(name, remote_dir)
}
Some(("ping", _sub_matches)) => ping(),
Some(("copy", sub_matches)) => {
let name = sub_matches.get_one::<String>("name");
cmd::copy_server_config(name)
}
Some(("init", _sub_matches)) => init(),
Some(("check",_sub_matches)) => check(),
Some((ext, sub_matches)) => {
let args = sub_matches
.get_many::<OsString>("")
.into_iter()
.flatten()
.collect::<Vec<_>>();
println!("Calling out to {ext:?} with {args:?}");
}
_ => unreachable!(),
}
}
fn init() {
let mut cmd = cli();
print_completions(&mut cmd);
let path_str = get_base_path()
.canonicalize()
.unwrap()
.to_string_lossy()
.to_string();
println!(
r#"init success!
auto prompt:
zsh: source {path_str}/complete/zsh.complete
bash: source {path_str}/complete/bash.complete
fish: source {path_str}/complete/fish.complete
powerShell: source {path_str}/complete/powerShell.complete
elvish: source {path_str}/complete/elvish.complete
"#
);
}
fn check (){
let require_tools = vec!["git", "ssh","sftp","sshpass"];
let path_str = env::var("PATH").expect("Failed to get PATH environment variable");
let mut tools = vec![];
for path in path_str.split(':') {
for entry in fs::read_dir(path).expect("Failed to read directory") {
let entry = entry.expect("Failed to read directory entry");
let file_name = entry.file_name();
tools.push(file_name.to_string_lossy().to_string())
}
}
for tool in require_tools {
if tools.contains(&tool.to_string()) {
println!("{} found! \u{2705} ", tool);
}else{
println!("{} not found! \u{2717} ", tool);
}
}
}
fn print_completions(cmd: &mut Command) {
let path = get_base_path().join("complete");
if !path.exists() {
fs::create_dir_all(&path).expect("create base dir error!");
}
generate(
Zsh,
cmd,
cmd.get_name().to_string(),
&mut fs::File::create(path.join("zsh.complete")).unwrap(),
);
generate(
Bash,
cmd,
cmd.get_name().to_string(),
&mut fs::File::create(path.join("bash.complete")).unwrap(),
);
generate(
Fish,
cmd,
cmd.get_name().to_string(),
&mut fs::File::create(path.join("fish.complete")).unwrap(),
);
generate(
PowerShell,
cmd,
cmd.get_name().to_string(),
&mut fs::File::create(path.join("powerShell.complete")).unwrap(),
);
generate(
Elvish,
cmd,
cmd.get_name().to_string(),
&mut fs::File::create(path.join("elvish.complete")).unwrap(),
);
}