-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Re-evaluate proc macro approach #3
Comments
Any standardization that sandboxes proc macros might kill this. |
I think that after cutting man page generation out from build script, this may be better, but we have to implement some kind of scanning. dtolnay/proc-macro2#213 may be a blocker for this. |
@Kixunil I've got a proposal written up for this, do you want it here or in a separate issue? The TL;DR is that |
Sounds interesting, feel free to write it here! I also had an idea recently to do something similar to |
TL;DR
What to do:Add a ExampleImagine a code structure like this:
We have a config struct which (preferably) sits alone in #[derive(::configure_me::Config)]
struct Config {
#[cfg_optional(true), cfg_doc("Port to listen on."]
port: u16,
#[cfg_default(::std::Ipv4Addr::new(0, 0, 0, 0)), cfg_doc("IP address to bind to."]
bind_addr: ::std::net::Ipv4Addr,
#[cfg_doc("IP address to bind to."]
tls_cert: String,
} With use configure_me_codegen::ConfigExt;
#[path = "src/config.rs"] mod my_app_config;
fn main() {
my_app_config::generate_configure_toml();
} The [[param]]
name = "port"
type = "u16"
optional = false
doc = "Port to listen on."
[[param]]
name = "bind_addr"
type = "::std::net::Ipv4Addr" # Yes, this works and you can use your own types as well! (impl. Deserialize and ParseArg)
default = "::std::net::Ipv4Addr::new(0, 0, 0, 0)" # Rust expression that creates the value.
doc = "IP address to bind to."
[[param]]
name = "tls_cert"
type = "String"
doc = "Path to the TLS certificate. The connections will be unsecure if it isn't provided." The DownsideAnd it's a big one: this requires somehow importing the config struct in There is an alternative approach with moving the configs to a separate (sub)crate, but that probably has even more downsides (publishing?) than the mod approach. DiscussionWhat I'm relying on heavily is the compiler - to be precise, the fact that it will drop unused functions from resulting binaries. So, if If further separation is desired, an extension trait to be imported only in As a bonus including additional outputs should be fairly trivial at that point. Closing thoughtsThis is just an idea, here for discussion. To state the obvious, it is not intended to replace the the current All the details like API, generated names, etc, are temporary. |
My thinking is completely the other way around - make the struct Rust, allow making everything that's possible with just Re: Prost, it's one of the tools which call an external process to generate stuff. Taking a page from their book adding a nice wrapper around calling |
(Sorry for multiple comments, I don't feel comfortable editing in stuff in issue comments). While Prost is a good example, I wouldn't go too far in how they do things - the use case is entirely different. My main pain points with |
Hmm, the idea of generating Toml from .rs sounds interesting! I see one problem with it that's probably fixable: the module may contain types that are not available in The fix would be to use a proc macro that prevents rustc seeing the struct - NOT derive macro. I will think about this more and write my thoughts. |
True, although that could be worked around by separating the config struct in a separate module. Personally I find the idea of 1k+ line files abhorrent (I try to stick to under a hundred, five hundred max), but I've seen a few crates where the whole thing is stuffed into One thing I probably have forgotten to mention earlier, as an intermediary step in the implementation, toml could be generated and the rest of the process happen like it did before. |
@Kixunil you may be interested in checking |
@Kixunil for now, to avoid the hassle of generated code, I'm testing an option of doing My use case does not need debconf or a manpage, so this feels like it should be enough if everything works as intended. So far this seems to require a lot of boilerplate, due in part to structopt's maintainer's refusal to support the |
Interesting, the So it seems you'd need some way of generating the secondary struct with those three derives and then generating some code that does the final processing. There's one more issue though. To work properly all arguments must behave as optional but if some fields are mandatory |
Pros:
Cons:
The text was updated successfully, but these errors were encountered: