mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-10-28 00:19:28 +00:00
Support short only options and switches
This commit is contained in:
@@ -175,23 +175,29 @@ impl<'a> StructField<'a> {
|
||||
}
|
||||
|
||||
// Determine the "long" name of options and switches.
|
||||
// Defaults to the kebab-case'd field name if `#[argh(long = "...")]` is omitted.
|
||||
// Defaults to the kebab-cased field name if `#[argh(long = "...")]` is omitted.
|
||||
// If `#[argh(long = none)]` is explicitly set, no long name will be set.
|
||||
let long_name = match kind {
|
||||
FieldKind::Switch | FieldKind::Option => {
|
||||
let long_name = attrs
|
||||
.long
|
||||
.as_ref()
|
||||
.map(syn::LitStr::value)
|
||||
.unwrap_or_else(|| {
|
||||
let long_name = match &attrs.long {
|
||||
None => {
|
||||
let kebab_name = to_kebab_case(&name.unraw().to_string());
|
||||
check_long_name(errors, name, &kebab_name);
|
||||
kebab_name
|
||||
});
|
||||
if long_name == "help" {
|
||||
errors.err(field, "Custom `--help` flags are not supported.");
|
||||
Some(kebab_name)
|
||||
}
|
||||
Some(None) => None,
|
||||
Some(Some(long)) => Some(long.value()),
|
||||
}
|
||||
let long_name = format!("--{}", long_name);
|
||||
Some(long_name)
|
||||
.map(|long_name| {
|
||||
if long_name == "help" {
|
||||
errors.err(field, "Custom `--help` flags are not supported.");
|
||||
}
|
||||
format!("--{}", long_name)
|
||||
});
|
||||
if let (None, None) = (&attrs.short, &long_name) {
|
||||
errors.err(field, "At least one of `short` or `long` has to be set.")
|
||||
};
|
||||
long_name
|
||||
}
|
||||
FieldKind::SubCommand | FieldKind::Positional => None,
|
||||
};
|
||||
@@ -214,6 +220,15 @@ impl<'a> StructField<'a> {
|
||||
.map(LitStr::value)
|
||||
.unwrap_or_else(|| self.name.to_string().trim_matches('_').to_owned())
|
||||
}
|
||||
|
||||
fn option_arg_name(&self) -> String {
|
||||
match (&self.attrs.short, &self.long_name) {
|
||||
(None, None) => unreachable!("short and long cannot both be None"),
|
||||
(Some(short), None) => format!("-{}", short.value()),
|
||||
(None, Some(long)) => long.clone(),
|
||||
(Some(short), Some(long)) => format!("-{},{long}", short.value()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn to_kebab_case(s: &str) -> String {
|
||||
@@ -228,22 +243,6 @@ fn to_kebab_case(s: &str) -> String {
|
||||
res
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kebabs() {
|
||||
#[track_caller]
|
||||
fn check(s: &str, want: &str) {
|
||||
let got = to_kebab_case(s);
|
||||
assert_eq!(got.as_str(), want)
|
||||
}
|
||||
check("", "");
|
||||
check("_", "");
|
||||
check("foo", "foo");
|
||||
check("__foo_", "foo");
|
||||
check("foo_bar", "foo-bar");
|
||||
check("foo__Bar", "foo-Bar");
|
||||
check("foo_bar__baz_", "foo-bar-baz");
|
||||
}
|
||||
|
||||
/// Implements `FromArgs` and `TopLevelCommand` or `SubCommand` for a `#[derive(FromArgs)]` struct.
|
||||
fn impl_from_args_struct(
|
||||
errors: &Errors,
|
||||
@@ -620,17 +619,15 @@ fn unwrap_from_args_fields<'a>(
|
||||
/// to an index in the output table.
|
||||
fn flag_str_to_output_table_map_entries<'a>(fields: &'a [StructField<'a>]) -> Vec<TokenStream> {
|
||||
let mut flag_str_to_output_table_map = vec![];
|
||||
for (i, (field, long_name)) in fields
|
||||
.iter()
|
||||
.filter_map(|field| field.long_name.as_ref().map(|long_name| (field, long_name)))
|
||||
.enumerate()
|
||||
{
|
||||
|
||||
for (i, field) in fields.iter().enumerate() {
|
||||
if let Some(short) = &field.attrs.short {
|
||||
let short = format!("-{}", short.value());
|
||||
flag_str_to_output_table_map.push(quote! { (#short, #i) });
|
||||
}
|
||||
|
||||
flag_str_to_output_table_map.push(quote! { (#long_name, #i) });
|
||||
if let Some(long) = &field.long_name {
|
||||
flag_str_to_output_table_map.push(quote! { (#long, #i) });
|
||||
}
|
||||
}
|
||||
flag_str_to_output_table_map
|
||||
}
|
||||
@@ -658,10 +655,7 @@ fn append_missing_requirements<'a>(
|
||||
}
|
||||
}
|
||||
FieldKind::Option => {
|
||||
let name = field
|
||||
.long_name
|
||||
.as_ref()
|
||||
.expect("options always have a long name");
|
||||
let name = field.option_arg_name();
|
||||
quote! {
|
||||
if #field_name.slot.is_none() {
|
||||
#mri.missing_option(#name)
|
||||
|
||||
@@ -16,7 +16,7 @@ pub struct FieldAttrs {
|
||||
pub description: Option<Description>,
|
||||
pub from_str_fn: Option<syn::ExprPath>,
|
||||
pub field_type: Option<FieldType>,
|
||||
pub long: Option<syn::LitStr>,
|
||||
pub long: Option<Option<syn::LitStr>>,
|
||||
pub short: Option<syn::LitChar>,
|
||||
pub arg_name: Option<syn::LitStr>,
|
||||
pub greedy: Option<syn::Path>,
|
||||
@@ -179,10 +179,20 @@ impl FieldAttrs {
|
||||
}
|
||||
|
||||
fn parse_attr_long(&mut self, errors: &Errors, m: &syn::MetaNameValue) {
|
||||
parse_attr_single_string(errors, m, "long", &mut self.long);
|
||||
let long = self.long.as_ref().unwrap();
|
||||
let value = long.value();
|
||||
check_long_name(errors, long, &value);
|
||||
if let Some(first) = &self.long {
|
||||
errors.duplicate_attrs("long", first, m);
|
||||
} else if let syn::Expr::Path(syn::ExprPath { path, .. }) = &m.value
|
||||
&& let Some(ident) = path.get_ident()
|
||||
&& ident.to_string().eq_ignore_ascii_case("none")
|
||||
{
|
||||
self.long = Some(None);
|
||||
} else if let Some(lit_str) = errors.expect_lit_str(&m.value) {
|
||||
self.long = Some(Some(lit_str.clone()));
|
||||
}
|
||||
if let Some(Some(long)) = &self.long {
|
||||
let value = long.value();
|
||||
check_long_name(errors, long, &value);
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_attr_short(&mut self, errors: &Errors, m: &syn::MetaNameValue) {
|
||||
|
||||
@@ -43,9 +43,9 @@ enum Action {
|
||||
#[derive(FromArgs)]
|
||||
#[argh(subcommand, name = "unpack")]
|
||||
struct Unpack {
|
||||
#[argh(switch, short = 'n')]
|
||||
#[argh(switch, short = 'n', long = none)]
|
||||
no_decompress: bool,
|
||||
#[argh(switch, short = 'h')]
|
||||
#[argh(switch, short = 'h', long = none)]
|
||||
dump_header: bool,
|
||||
#[argh(positional)]
|
||||
img: Utf8CString,
|
||||
@@ -54,7 +54,7 @@ struct Unpack {
|
||||
#[derive(FromArgs)]
|
||||
#[argh(subcommand, name = "repack")]
|
||||
struct Repack {
|
||||
#[argh(switch, short = 'n')]
|
||||
#[argh(switch, short = 'n', long = none)]
|
||||
no_compress: bool,
|
||||
#[argh(positional)]
|
||||
img: Utf8CString,
|
||||
@@ -136,7 +136,7 @@ struct Dtb {
|
||||
#[derive(FromArgs)]
|
||||
#[argh(subcommand, name = "split")]
|
||||
struct Split {
|
||||
#[argh(switch, short = 'n')]
|
||||
#[argh(switch, short = 'n', long = none)]
|
||||
no_decompress: bool,
|
||||
#[argh(positional)]
|
||||
file: Utf8CString,
|
||||
|
||||
@@ -18,7 +18,7 @@ pub(crate) enum DtbAction {
|
||||
#[derive(FromArgs)]
|
||||
#[argh(subcommand, name = "print")]
|
||||
pub(crate) struct Print {
|
||||
#[argh(switch, short = 'f')]
|
||||
#[argh(switch, short = 'f', long = none)]
|
||||
fstab: bool,
|
||||
}
|
||||
|
||||
|
||||
@@ -17,21 +17,21 @@ use std::io::BufReader;
|
||||
struct ResetProp {
|
||||
#[argh(switch, short = 'v')]
|
||||
verbose: bool,
|
||||
#[argh(switch, short = 'w')]
|
||||
#[argh(switch, short = 'w', long = none)]
|
||||
wait_mode: bool,
|
||||
#[argh(switch, short = 'p')]
|
||||
#[argh(switch, short = 'p', long = none)]
|
||||
persist: bool,
|
||||
#[argh(switch, short = 'P')]
|
||||
#[argh(switch, short = 'P', long = none)]
|
||||
persist_only: bool,
|
||||
#[argh(switch, short = 'Z')]
|
||||
#[argh(switch, short = 'Z', long = none)]
|
||||
context: bool,
|
||||
#[argh(switch, short = 'n')]
|
||||
#[argh(switch, short = 'n', long = none)]
|
||||
skip_svc: bool,
|
||||
#[argh(option, short = 'f')]
|
||||
file: Option<Utf8CString>,
|
||||
#[argh(option, long = "delete", short = 'd')]
|
||||
#[argh(option, short = 'd', long = "delete")]
|
||||
delete_key: Option<Utf8CString>,
|
||||
#[argh(positional)]
|
||||
#[argh(positional, greedy = true)]
|
||||
args: Vec<Utf8CString>,
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ Wait mode arguments (toggled with -w):
|
||||
|
||||
General flags:
|
||||
-h,--help show this message
|
||||
-v print verbose output to stderr
|
||||
-v,--verbose print verbose output to stderr
|
||||
-w switch to wait mode
|
||||
|
||||
Read mode flags:
|
||||
|
||||
Reference in New Issue
Block a user