Skip to content

Commit

Permalink
Update tiny-cli bool parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcusGrass committed Aug 20, 2024
1 parent 99fac85 commit 9352a9f
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 24 deletions.
66 changes: 46 additions & 20 deletions tiny-cli/src/derive_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ fn parse_group(name: &str, metadata: &StructMetadata, g: &Group) -> TokenStream
ArgsParsedTreeParseState::WantsSubcommand => {
let mem = parse_member(ident, &mut stream);
let field_ty = match mem.ty {
FieldTy::UnixStr | FieldTy::Str => {
FieldTy::UnixStr | FieldTy::Str | FieldTy::Bool => {
panic!("[ArgParse derive] Invalid type for subcommand");
}
FieldTy::Unknown(ty) => ty,
Expand All @@ -215,29 +215,29 @@ fn parse_group(name: &str, metadata: &StructMetadata, g: &Group) -> TokenStream
}
ArgsParsedTreeParseState::Ready => {
let mem = parse_member(ident, &mut stream);
let pf = ParsedField {
doc_comments: core::mem::take(&mut doc_comments_for_next),
name: mem.name.clone(),
ty: mem.ty,
is_ref: mem.is_ref,
package: mem.package,
long_match: mem.name,
short_match: None,
};
let pf = ParsedField::new_check_consistency(
core::mem::take(&mut doc_comments_for_next),
mem.name.clone(),
mem.ty,
mem.is_ref,
mem.package,
mem.name,
None,
);
c.push_field(&pf);
members.push(pf);
}
ArgsParsedTreeParseState::WantsMember(p) => {
let mem = parse_member(ident, &mut stream);
let pf = ParsedField {
doc_comments: core::mem::take(&mut doc_comments_for_next),
name: mem.name.clone(),
ty: mem.ty,
is_ref: mem.is_ref,
package: mem.package,
long_match: p.long.unwrap_or(mem.name),
short_match: p.short,
};
let pf = ParsedField::new_check_consistency(
core::mem::take(&mut doc_comments_for_next),
mem.name.clone(),
mem.ty,
mem.is_ref,
mem.package,
p.long.unwrap_or(mem.name),
p.short,
);
c.push_field(&pf);
members.push(pf);
state = ArgsParsedTreeParseState::Ready;
Expand Down Expand Up @@ -539,6 +539,7 @@ impl ParsedField {
ty.clone()
}
}
FieldTy::Bool => "bool".to_string(),
}
}

Expand Down Expand Up @@ -568,12 +569,36 @@ impl ParsedField {
}
let _ = help_row.write_char('\n');
}

pub(crate) fn new_check_consistency(
doc_comments: Vec<String>,
name: String,
ty: FieldTy,
is_ref: bool,
package: FieldPackageKind,
long_match: String,
short_match: Option<String>,
) -> Self {
if ty == FieldTy::Bool && matches!(package, FieldPackageKind::Option) {
panic!("[ArgParse Derive] Failed to derive, got field with name={name} specified as Option<bool> bool defaults to false and are always optional")
}
Self {
doc_comments,
name,
ty,
is_ref,
package,
long_match,
short_match,
}
}
}

#[derive(Clone, Debug)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) enum FieldTy {
UnixStr,
Str,
Bool,
Unknown(String),
}

Expand All @@ -583,6 +608,7 @@ impl FieldTy {
match trimmed_ident.as_str() {
"UnixStr" => Self::UnixStr,
"str" => Self::Str,
"bool" => Self::Bool,
&_ => Self::Unknown(trimmed_ident),
}
}
Expand Down
23 changes: 20 additions & 3 deletions tiny-cli/src/derive_struct/impl_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ impl CodeWriter {
struct_out: String::new(),
}
}

pub(crate) fn push_field(&mut self, field: &ParsedField) {
self.field_push_const_match(field);
self.field_push_var_decl(field);
Expand Down Expand Up @@ -80,6 +81,12 @@ impl CodeWriter {
}

fn field_push_var_decl(&mut self, field: &ParsedField) {
if matches!(field.ty, FieldTy::Bool) {
let _ = self
.var_decl_head
.write_fmt(format_args!("\t\tlet mut {}: bool = false;\n", field.name,));
return;
}
match field.package {
FieldPackageKind::None | FieldPackageKind::Option => {
let _ = self.var_decl_head.write_fmt(format_args!(
Expand Down Expand Up @@ -130,7 +137,7 @@ impl CodeWriter {
}

fn field_push_to_out(&mut self, field: &ParsedField) {
if matches!(field.package, FieldPackageKind::None) {
if matches!(field.package, FieldPackageKind::None) && !matches!(field.ty, FieldTy::Bool) {
let _ = self.struct_out.write_fmt(format_args!("\
{}: {{
if let Some(found_arg) = {} {{
Expand Down Expand Up @@ -245,13 +252,22 @@ impl tiny_std::unix::cli::ArgParse for {name} {{
fn arg_parse(args: &mut impl Iterator<Item=&'static tiny_std::UnixStr>) -> core::result::Result<Self, tiny_std::unix::cli::ArgParseError> {{
")
}

fn member_try_assign(m: &ParsedField) -> String {
match m.package {
FieldPackageKind::None | FieldPackageKind::Option => {
format!("{} = Some({})", m.name, member_as_convert(m))
if matches!(m.ty, FieldTy::Bool) {
format!("{} = true", m.name)
} else {
format!("{} = Some({})", m.name, member_as_convert(m))
}
}
FieldPackageKind::Vec => {
format!("{}.push({})", m.name, member_as_convert(m))
if matches!(m.ty, FieldTy::Bool) {
format!("{}.push(true)", m.name)
} else {
format!("{}.push({})", m.name, member_as_convert(m))
}
}
}
}
Expand Down Expand Up @@ -282,6 +298,7 @@ fn member_as_convert(m: &ParsedField) -> String {
let _ = out.write_str("\t\t\t\t\t\t}\n");
let _ = out.write_str("\t\t\t\t\t}");
}
FieldTy::Bool => {}
FieldTy::Unknown(ty) => {
let _ = out.write_str("\t\t\t\t\t\tlet next_str_arg = match next_arg.as_str() {\n");
let _ = out.write_str("\t\t\t\t\t\t\tOk(s) => s,\n");
Expand Down
18 changes: 17 additions & 1 deletion tiny-cli/tests/derive_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::panic;
use std::sync::{Arc, Mutex};
use tiny_cli::{ArgParse, Subcommand};
use tiny_std::unix::cli::ArgParse;
use tiny_std::{UnixStr, UnixString};
use tiny_std::{unix_lit, UnixStr, UnixString};

#[derive(ArgParse)]
#[cli(help_path = "tiny-cli")]
Expand Down Expand Up @@ -64,6 +64,22 @@ fn aliases_work() {
assert_eq!(15, ss.one_req_field);
}

#[derive(ArgParse)]
pub struct SimplStructWithBool {
#[cli(short = "b")]
my_opt: bool,
}

#[test]
fn bool_parsing_works() {
let mut values = [unix_lit!("-b")];
let b = SimplStructWithBool::arg_parse(&mut values.into_iter()).unwrap();
assert!(b.my_opt);
let mut no_value = [];
let b = SimplStructWithBool::arg_parse(&mut no_value.into_iter()).unwrap();
assert!(!b.my_opt);
}

#[derive(ArgParse)]
pub struct StructWithDifferentPackaging {
req_field: i32,
Expand Down

0 comments on commit 9352a9f

Please sign in to comment.