use clap::{CommandFactory, Parser, ValueEnum};
use clap_complete::{generate, Shell};
use crate::serial::{DataBits, FlowControl, NewlineEncoding, Parity, PortConfig, StopBits};
#[derive(Clone, ValueEnum)]
enum DataBitsArg {
#[value(name = "5")]
Five,
#[value(name = "6")]
Six,
#[value(name = "7")]
Seven,
#[value(name = "8")]
Eight,
}
#[derive(Clone, ValueEnum)]
enum StopBitsArg {
#[value(name = "1")]
One,
#[value(name = "2")]
Two,
}
#[derive(Clone, ValueEnum)]
enum ParityArg {
None,
Even,
Odd,
}
#[derive(Clone, ValueEnum)]
enum FlowControlArg {
None,
Software,
Hardware,
}
#[derive(Parser)]
#[command(
version,
about,
long_about = None,
next_display_order = None,
disable_help_flag = true,
disable_version_flag = true,
)]
struct Cli {
#[arg()]
port: Option<String>,
#[arg(
short,
long,
value_name = "BAUDRATE",
default_value = "115200",
help_heading = "Serial Settings",
display_order = 1
)]
baud: u32,
#[arg(
short,
long,
value_name = "BITS",
default_value = "8",
help_heading = "Serial Settings",
display_order = 2
)]
data_bits: DataBitsArg,
#[arg(
short,
long,
value_name = "BITS",
default_value = "1",
help_heading = "Serial Settings",
display_order = 3
)]
stop_bits: StopBitsArg,
#[arg(
short,
long,
value_name = "PARITY",
default_value = "none",
help_heading = "Serial Settings",
display_order = 4
)]
parity: ParityArg,
#[arg(
short,
long,
value_name = "FLOW",
default_value = "none",
help_heading = "Serial Settings",
display_order = 5
)]
flow_control: FlowControlArg,
#[arg(
short = 'e',
long = "local-echo",
help_heading = "Behavior",
display_order = 6
)]
local_echo: bool,
#[arg(
long = "outgoing-newline",
value_name = "NEWLINE_ENCODING",
default_value = "cr",
help_heading = "Behavior",
display_order = 7
)]
outgoing_newline: NewlineEncoding,
#[cfg(unix)]
#[arg(long = "no-lock", help_heading = "Behavior", display_order = 8)]
no_lock: bool,
#[arg(
short = 'k',
long = "keep-open",
default_value = "true",
overrides_with = "no_keep_open",
help_heading = "Behavior",
display_order = 9
)]
keep_open: bool,
#[arg(
long = "no-keep-open",
overrides_with = "keep_open",
help_heading = "Behavior",
display_order = 10
)]
no_keep_open: bool,
#[arg(long, value_name = "SHELL", help_heading = "Extra", display_order = 11)]
completions: Option<Shell>,
#[arg(short, long, action = clap::ArgAction::Help, help_heading = "Options", display_order = 12)]
help: Option<bool>,
#[arg(short = 'V', long, action = clap::ArgAction::Version, help_heading = "Options", display_order = 13)]
version: Option<bool>,
}
pub struct Args {
pub port: Option<String>,
pub config: PortConfig,
pub hold: bool,
pub local_echo: bool,
pub outgoing_newline: NewlineEncoding,
}
pub fn parse() -> Option<Args> {
let cli = Cli::parse();
if let Some(shell) = cli.completions {
generate(shell, &mut Cli::command(), "stuart", &mut std::io::stdout());
return None;
}
Some(Args {
port: cli.port,
config: PortConfig {
baud: cli.baud,
data_bits: match cli.data_bits {
DataBitsArg::Five => DataBits::Five,
DataBitsArg::Six => DataBits::Six,
DataBitsArg::Seven => DataBits::Seven,
DataBitsArg::Eight => DataBits::Eight,
},
stop_bits: match cli.stop_bits {
StopBitsArg::One => StopBits::One,
StopBitsArg::Two => StopBits::Two,
},
parity: match cli.parity {
ParityArg::None => Parity::None,
ParityArg::Even => Parity::Even,
ParityArg::Odd => Parity::Odd,
},
flow_control: match cli.flow_control {
FlowControlArg::None => FlowControl::None,
FlowControlArg::Software => FlowControl::Software,
FlowControlArg::Hardware => FlowControl::Hardware,
},
#[cfg(unix)]
no_lock: cli.no_lock,
},
hold: !cli.no_keep_open,
local_echo: cli.local_echo,
outgoing_newline: cli.outgoing_newline,
})
}