You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi! Recently I found Facet and am trying to use it to replace a simple CLI with a lighter weight dependancy, and ran into some issues I thought I would bring up. I'm not sure hw feasable some of these are, but I am bringing them up for discussion. Firstly I want to state how glad I am this project exists, as I have been bothered by compile times for ages now and I am hugely grateful for all the work being done here.
That being said, I have a few things I wanted to bring up from trying to integrate it into one of my projects as a replacement to serde and, as this post focus on, argument parsing (formerly I used clap, but somehow that doubles compile times on its own...)
The good:
Basic argument parsing was the simplest and most streamlined I have ever used. The attribute to simply specify if its positional or named with an optional; short = '<char>' was refreshingly simple an easy.
Parsing enums by name rather than needing to specify the exact string to turn into each variant was a nice change of pace.
Though I quickly ran into some issues and annoyances.
The first is that you need to specify a #[repr] on enums for them to work with facet. Its not a dealbreaker, it would be nice if facet could somehow infer this, but I'm not sure if thats possible. It also seems to make enum variants with fields impossible to serialize with facet-args (though enums with fields in general seem to work with #[repr(C)])
The next is what this post will primarily focus on, as I feel it is the most important: Assuming its possible, could we use enums to represent subcommands? Anything defined on the Args (or whatever its called) struct would be global, but there could be a field marked with something (#[facet(subcommand)] perhaps?) that would allow for subcommansd (for completeness, being a second action in a single binary. e.g. in cargo build the build is the subcommand).
It seems fitting, with every subcommand sharing global options (Args) and its own options (enum fields), and feels in line (so much so that it is actually one of the first things I tried, having a Subcommand fielded enum as the first and only positional argument)
// Something along the lines of:use facet::Facet;#[derive(Facet,Debug)]pubstructArgs{#[facet(subcommand)]// It could make sense with #[facet(positional)], but I feel like that// may cause issues with having multiple subcommands in a given layer.subcommand:Subcommand,#[facet(positional)]file:String,#[facet(named)]verbose:bool,}#[derive(Facet)]pubenumSubcommand{Serve{#[facet(named, short = 'p')]port:u16,},Build{// Flag P: Pedantic#[facet(named, short = 'P')]strict:bool,// Run without producing output files#[facet(named, short = 'd')]dry_run:bool,},}
This raises possible ambigities with multiple subcommands in the same "layer" if its just positional (though it could make sense?), and what order positional arguments are parsed (it could just be that subcommands/enum fields can only have flag arguments like --port / -p)
#[derive(Facet,Debug)]pubstructArgs{#[facet(positional)]subcommand:Subcommand,#[facet(named)]verbose:bool,// ISSUE: The flag is now --serve_port not --port. As far as I can tell,// there is no way to change this. There is `facet(rename = "")`, but as// far as I can tell that is to change the case, not rename the whole field.#[facet(named, short = 'p')]// ISSUE: Options everywhere, and no type-level gaurntee that all fields// in a given subcommand are available if a given subcommand is used,// possibly leading to runtime panics from `unwrap`, etc that could be// prevented with an enum.//// As for the panics, you coul `unwrap` them all at program start under// a match statement, but that feels very boilerplate-ey and like it would// get big quickly.#[facet(default)]serve_port:Option<u16>,// Both of these issues apply to these two as well, and really every// subcommand-specific flag.#[facet(named, short = 'P')]#[facet(default)]build_strict:Option<bool>,#[facet(named, short = 'd')]#[facet(default)]build_dry_run:Option<bool>,}#[derive(facet)]#[repr(u8)]enumSubcommand{Serve,Build,}
Its certinly possible that these are possible, but if they are I was unable to find any docs or make it work from my testing. None of these are strictly dealbreakers, but they do cause considerable friction.
I am well aware facet is in early early developement and things will improve, which is why I am making this discussion - I want to bring up some issues and possible solutions I foun when trying to integrate facet into a real project, which may not have been caught. If any suggestions are impossible or unrealistic, do say so - it will help me better understand what is feasable for future suggestions (I don't do much with macro authoring, so im not sure whats realistic from them).
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi! Recently I found Facet and am trying to use it to replace a simple CLI with a lighter weight dependancy, and ran into some issues I thought I would bring up. I'm not sure hw feasable some of these are, but I am bringing them up for discussion. Firstly I want to state how glad I am this project exists, as I have been bothered by compile times for ages now and I am hugely grateful for all the work being done here.
That being said, I have a few things I wanted to bring up from trying to integrate it into one of my projects as a replacement to serde and, as this post focus on, argument parsing (formerly I used
clap
, but somehow that doubles compile times on its own...)The good:
short = '<char>'
was refreshingly simple an easy.Though I quickly ran into some issues and annoyances.
The first is that you need to specify a
#[repr]
on enums for them to work with facet. Its not a dealbreaker, it would be nice if facet could somehow infer this, but I'm not sure if thats possible. It also seems to make enum variants with fields impossible to serialize with facet-args (though enums with fields in general seem to work with#[repr(C)]
)The next is what this post will primarily focus on, as I feel it is the most important: Assuming its possible, could we use enums to represent subcommands? Anything defined on the
Args
(or whatever its called) struct would be global, but there could be a field marked with something (#[facet(subcommand)]
perhaps?) that would allow for subcommansd (for completeness, being a second action in a single binary. e.g. incargo build
thebuild
is the subcommand).It seems fitting, with every subcommand sharing global options (
Args
) and its own options (enum fields), and feels in line (so much so that it is actually one of the first things I tried, having aSubcommand
fielded enum as the first and only positional argument)This raises possible ambigities with multiple subcommands in the same "layer" if its just positional (though it could make sense?), and what order positional arguments are parsed (it could just be that subcommands/enum fields can only have flag arguments like
--port / -p
)Its certinly possible that these are possible, but if they are I was unable to find any docs or make it work from my testing. None of these are strictly dealbreakers, but they do cause considerable friction.
I am well aware facet is in early early developement and things will improve, which is why I am making this discussion - I want to bring up some issues and possible solutions I foun when trying to integrate facet into a real project, which may not have been caught. If any suggestions are impossible or unrealistic, do say so - it will help me better understand what is feasable for future suggestions (I don't do much with macro authoring, so im not sure whats realistic from them).
Beta Was this translation helpful? Give feedback.
All reactions