refactor(cli): simplify applet detection and remove feature-based defaults
This commit is contained in:
1 parent
dc65daec75
commit
efaa60cbd4
2 files changed
+78
-37
No files matched your search
@@ -1,4 +1,6 @@
|
||||
use std::path::Path;
|
||||
use std::{ffi::OsString, path::Path};
|
||||
|
||||
use clap::Command;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum RequestedApplet {
|
||||
@@ -7,20 +9,17 @@ pub enum RequestedApplet {
|
||||
Server,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum AppletAvailability {
|
||||
Client,
|
||||
Tui,
|
||||
Server,
|
||||
None,
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum AppletDispatch {
|
||||
Run {
|
||||
applet: RequestedApplet,
|
||||
argv: Vec<OsString>,
|
||||
},
|
||||
Help(String),
|
||||
}
|
||||
|
||||
pub fn detect_applet_from_argv0(argv0: &str) -> Option<RequestedApplet> {
|
||||
match Path::new(argv0)
|
||||
.file_name()
|
||||
.and_then(|name| name.to_str())
|
||||
.unwrap_or(argv0)
|
||||
{
|
||||
match applet_basename(argv0) {
|
||||
"irtt-cli" => Some(RequestedApplet::Client),
|
||||
"irtt-tui" => Some(RequestedApplet::Tui),
|
||||
"irttd" | "irtt-server" => Some(RequestedApplet::Server),
|
||||
@@ -29,20 +28,73 @@ pub fn detect_applet_from_argv0(argv0: &str) -> Option<RequestedApplet> {
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn default_applet_for_features(
|
||||
client_enabled: bool,
|
||||
tui_enabled: bool,
|
||||
server_enabled: bool,
|
||||
) -> AppletAvailability {
|
||||
if client_enabled {
|
||||
AppletAvailability::Client
|
||||
} else if tui_enabled {
|
||||
AppletAvailability::Tui
|
||||
} else if server_enabled {
|
||||
AppletAvailability::Server
|
||||
} else {
|
||||
AppletAvailability::None
|
||||
pub fn dispatch_from_argv(argv: Vec<OsString>) -> Result<AppletDispatch, String> {
|
||||
let argv0 = argv
|
||||
.first()
|
||||
.and_then(|arg| arg.to_str())
|
||||
.unwrap_or("irtt-rs");
|
||||
|
||||
if let Some(applet) = detect_applet_from_argv0(argv0) {
|
||||
return Ok(AppletDispatch::Run { applet, argv });
|
||||
}
|
||||
|
||||
let basename = applet_basename(argv0);
|
||||
if basename.starts_with("irtt-") && basename != "irtt-rs" {
|
||||
return Err(format!(
|
||||
"unknown applet name '{basename}'. Known applet names: irtt-rs, irtt-cli, irtt-tui, irtt-server"
|
||||
));
|
||||
}
|
||||
|
||||
let Some(command) = argv.get(1).and_then(|arg| arg.to_str()) else {
|
||||
return Err(format!(
|
||||
"choose an applet: client, tui, or server\n\n{}",
|
||||
dispatcher_help()
|
||||
));
|
||||
};
|
||||
|
||||
match command {
|
||||
"-h" | "--help" => Ok(AppletDispatch::Help(dispatcher_help())),
|
||||
"client" => Ok(AppletDispatch::Run {
|
||||
applet: RequestedApplet::Client,
|
||||
argv: applet_argv("irtt-cli", &argv[2..]),
|
||||
}),
|
||||
"tui" => Ok(AppletDispatch::Run {
|
||||
applet: RequestedApplet::Tui,
|
||||
argv: applet_argv("irtt-tui", &argv[2..]),
|
||||
}),
|
||||
"server" => Ok(AppletDispatch::Run {
|
||||
applet: RequestedApplet::Server,
|
||||
argv: applet_argv("irtt-server", &argv[2..]),
|
||||
}),
|
||||
_ => Err(format!(
|
||||
"unknown applet '{command}'. Choose one of: client, tui, server\n\n{}",
|
||||
dispatcher_help()
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dispatcher_help() -> String {
|
||||
let mut command = Command::new("irtt-rs")
|
||||
.about("IRTT-compatible multi-applet dispatcher")
|
||||
.subcommand(Command::new("client").about("Run the stream client applet"))
|
||||
.subcommand(Command::new("tui").about("Run the terminal UI applet"))
|
||||
.subcommand(Command::new("server").about("Run the server applet"))
|
||||
.after_help("Applet binary names: irtt-cli, irtt-tui, irtt-server");
|
||||
command.render_help().to_string()
|
||||
}
|
||||
|
||||
fn applet_basename(argv0: &str) -> &str {
|
||||
Path::new(argv0)
|
||||
.file_name()
|
||||
.and_then(|name| name.to_str())
|
||||
.unwrap_or(argv0)
|
||||
}
|
||||
|
||||
fn applet_argv(applet_name: &str, args: &[OsString]) -> Vec<OsString> {
|
||||
let mut argv = Vec::with_capacity(args.len() + 1);
|
||||
argv.push(OsString::from(applet_name));
|
||||
argv.extend(args.iter().cloned());
|
||||
argv
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -6,9 +6,7 @@ use std::{
|
||||
};
|
||||
|
||||
use irtt_cli::{
|
||||
applet::{
|
||||
default_applet_for_features, detect_applet_from_argv0, AppletAvailability, RequestedApplet,
|
||||
},
|
||||
applet::{dispatch_from_argv, AppletDispatch, RequestedApplet},
|
||||
signal::install_signal_handler,
|
||||
};
|
||||
|
||||
@@ -44,15 +42,6 @@ fn run_from_env() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
}
|
||||
|
||||
fn default_requested_applet() -> Result<RequestedApplet, Box<dyn std::error::Error>> {
|
||||
match default_applet_for_features(cfg!(feature = "client"), cfg!(feature = "tui"), false) {
|
||||
AppletAvailability::Client => Ok(RequestedApplet::Client),
|
||||
AppletAvailability::Tui => Ok(RequestedApplet::Tui),
|
||||
AppletAvailability::Server => Ok(RequestedApplet::Server),
|
||||
AppletAvailability::None => Err("no runnable applet is available in this build".into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
fn run_client_applet(
|
||||
argv: Vec<OsString>,
|
||||
|
||||
Reference in new issue
Block a user