Skip to content

Commit

Permalink
value hints in completions
Browse files Browse the repository at this point in the history
  • Loading branch information
tertsdiepraam committed Dec 7, 2023
1 parent 987041c commit 65af447
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 3 deletions.
1 change: 1 addition & 0 deletions complete/src/fish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ fn render_value_hint(value: &ValueHint) -> String {
let joined = s.join(", ");
format!(" -a {{ {joined} }}")
}
ValueHint::Unknown => String::new(),
_ => todo!(),
}
}
Expand Down
2 changes: 2 additions & 0 deletions derive/src/argument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{

pub struct Argument {
pub ident: Ident,
pub field: Option<syn::Type>,
pub name: String,
pub arg_type: ArgType,
pub help: String,
Expand Down Expand Up @@ -105,6 +106,7 @@ pub fn parse_argument(v: Variant) -> Vec<Argument> {
};
Argument {
ident: ident.clone(),
field: field.clone(),
name: name.clone(),
arg_type,
help: arg_help,
Expand Down
18 changes: 16 additions & 2 deletions derive/src/complete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ use quote::quote;
pub fn complete(args: &[Argument]) -> TokenStream {
let mut arg_specs = Vec::new();

for Argument { help, arg_type, .. } in args {
for Argument {
help,
field,
arg_type,
..
} in args
{
let ArgType::Option {
flags,
hidden: false,
Expand All @@ -25,21 +31,29 @@ pub fn complete(args: &[Argument]) -> TokenStream {
if short.is_empty() && long.is_empty() {
continue;
}

let short: Vec<_> = short
.iter()
.map(|Flag { flag, .. }| quote!(String::from(#flag)))
.collect();

let long: Vec<_> = long
.iter()
.map(|Flag { flag, .. }| quote!(String::from(#flag)))
.collect();

let hint = if let Some(ty) = field {
quote!(Some(<#ty>::value_hint()))
} else {
quote!(None)
};

arg_specs.push(quote!(
Arg {
short: vec![#(#short),*],
long: vec![#(#long),*],
help: String::from(#help),
value: None,
value: #hint,
}
))
}
Expand Down
2 changes: 1 addition & 1 deletion derive/src/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub struct Flags {
pub dd_style: Vec<(String, String)>,
}

#[derive(Clone)]
#[derive(Clone, PartialEq, Eq)]
pub enum Value {
No,
Optional(String),
Expand Down
13 changes: 13 additions & 0 deletions derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ pub fn arguments(input: TokenStream) -> TokenStream {
#[cfg(feature = "complete")]
fn complete() -> ::uutils_args_complete::Command {
use ::uutils_args_complete::{Command, Arg, ValueHint};
use ::uutils_args::Value;
#completion
}
}
Expand All @@ -137,6 +138,7 @@ pub fn value(input: TokenStream) -> TokenStream {
let mut options = Vec::new();

let mut match_arms = vec![];
let mut all_keys = Vec::new();
for variant in data.variants {
let variant_name = variant.ident.to_string();
let attrs = variant.attrs.clone();
Expand All @@ -153,6 +155,7 @@ pub fn value(input: TokenStream) -> TokenStream {
keys
};

all_keys.extend(keys.clone());
options.push(quote!(&[#(#keys),*]));

let stmt = if let Some(v) = value {
Expand Down Expand Up @@ -201,6 +204,16 @@ pub fn value(input: TokenStream) -> TokenStream {
_ => unreachable!("Should be caught by (None, []) case above.")
})
}

#[cfg(feature = "complete")]
fn value_hint() -> ::uutils_args_complete::ValueHint {
::uutils_args_complete::ValueHint::Strings(
[#(#all_keys),*]
.into_iter()
.map(ToString::to_string)
.collect()
)
}
}
);

Expand Down
38 changes: 38 additions & 0 deletions examples/value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use uutils_args::{Arguments, Initial, Options, Value};

#[derive(Arguments)]
#[arguments(file = "examples/hello_world_help.md")]
enum Arg {
/// Color!
#[arg("-c NAME", "--color=NAME")]
Color(Color),
}

#[derive(Value, Debug, Default)]
enum Color {
#[value("never")]
Never,
#[default]
#[value("auto")]
Auto,
#[value("always")]
Always,
}

#[derive(Initial)]
struct Settings {
color: Color,
}

impl Options<Arg> for Settings {
fn apply(&mut self, arg: Arg) {
match arg {
Arg::Color(c) => self.color = c,
}
}
}

fn main() {
let color = Settings::parse(std::env::args_os()).color;
println!("{:?}", color);
}

0 comments on commit 65af447

Please sign in to comment.