-
Notifications
You must be signed in to change notification settings - Fork 13
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
clap
derive
support missing/broken
#15
Comments
hmm yes I think the clap arguments are dropped, do you use the function provided by twelf to declare your clap commands and arguments ? Or do you use directly clap ? I need to fix it ASAP, if you have a smal reproductible main to copy paste me here it would be helpful for me :) |
The |
Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com>
Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com>
A new version of If you need something else feel free :) |
Please reopen this. I think you really need to test with all (or a lot more) It seems the Specifically #[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Config {
#[clap(
long,
default_value_t = String::from("localhost"),
help = "Documentation inside clap, to specifiy db_host",
)]
db_host: String,
...
} Here Adding one line to
|
Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com>
Fixed and published as |
Tell me if it fixes your project. |
I'm sorry I'm just getting to testing this now. |
Here is another example that doesn't work as expected: use clap::{CommandFactory, Parser, Subcommand};
use serde::{Deserialize, Serialize};
use std::{
fs::File,
path::PathBuf,
ffi::OsStr,
};
use twelf::{config, Layer};
pub const HELP_TEMPLATE: &str = "{bin} {version}
{about}
USAGE:
{usage}
{all-args}
";
#[config]
#[derive(Parser, Debug)]
#[clap(
help_template = HELP_TEMPLATE,
version,
about = "Twelf Test",
)]
pub struct CliOptions {
#[clap(flatten)]
pub global: GlobalOptions,
#[clap(subcommand)]
pub command: Command,
}
#[derive(Parser, Debug, Deserialize, Serialize)]
#[clap(rename_all = "kebab-case")]
pub struct GlobalOptions {
/// Host name or IP address
#[clap(display_order = 0, short = 'o', long, default_value_t = String::from("localhost"), env = "TB_HOST")]
pub host: String,
/// Port number
#[clap(
display_order = 1,
short,
long,
default_value_t = 4242u16,
env = "TB_PORT"
)]
pub port: u16,
}
#[derive(Subcommand, Debug, Deserialize, Serialize)]
#[clap(rename_all = "kebab-case")]
pub enum Command {
/// Place an order
#[clap(display_order = 0, alias("p"))]
Place(Place),
/// Flatten all positions
#[clap(display_order = 1, alias("f"))]
Flatten(Flatten),
}
#[derive(Parser, Debug, Deserialize, Serialize)]
pub struct Flatten {
#[clap(display_order = 0, long, short)]
pub urgent: bool,
#[clap(display_order = 1, long, short, conflicts_with = "urgent")]
pub percentage: Option<f64>,
#[clap(display_order = 2, long, short, conflicts_with = "urgent")]
pub force_absolute_spread: Option<f64>,
}
#[derive(Parser, Debug, Deserialize, Serialize)]
pub struct Place {
#[clap(short, long, parse(from_os_str), validator_os = path_readable_file, env = "TB_CONTRACT")]
pub contract: Option<PathBuf>,
#[clap(short, long, parse(from_os_str), validator_os = path_readable_file, env = "TB_ORDER")]
pub order: Option<PathBuf>,
#[clap(long)]
pub execute: bool,
}
const TOML_CONFIG_FILE: &str = "config.toml";
fn main() {
let matches = CliOptions::command().get_matches();
let mut config_layers = Vec::with_capacity(2);
if std::path::Path::new(TOML_CONFIG_FILE).exists() {
config_layers.push(Layer::Toml(TOML_CONFIG_FILE.into()));
}
config_layers.push(Layer::Clap(matches));
let _config = CliOptions::with_layers(&config_layers).unwrap();
}
fn path_readable_file(value: &OsStr) -> Result<(), String> {
let path = PathBuf::from(value);//.as_ref();
if path.is_dir() {
return Err(format!("{}: Input path must be a file, not a directory",
path.display()));
}
File::open(&path).map(|_| ()).map_err(|e| format!("{}: {}", path.display(), e))
} Running this with e.g.:
Gives me:
When I remove the Also note that I need I would very much like to only have some stuff in a config file. Not all. Specifically in the example code above only the On that note: I do not understand why After all, I only want to read from a config file, not write to it. |
@virtualritz thx for a good example. I noticed you used |
I'm not the author of t |
@nyurik Yes it would be possible by directly using |
|
👋 I don't have answers for the features that are unsupported, but I did come through this thread while I was working on setting up Twelf for a project so it might provide some value to show on the implementation I landed on, even if it isn't perfect. First, I have my struct defined with clap derive (options.rs L6 -> L49), and have all fields marked as Next I detect any config files and build up my layers with them and the environment (main.rs L24 -> L52). Below that I finalize using The only non-ideal aspect is that I then have to validate an argument that is required manually — but I don't mind doing that in my use case, and I'm quite happy maintaining this setup going forward. Apologies if this is slightly off topic for this issue, but it might help someone looking to get up and running with a clap derive implementation 🙂 |
Update: clap-rs/clap#1206 has just been fixed, so you can iterate over args now. |
I have this:
I expect a help like this:
But I get this:
I.e. it seems all
clap-derive
macro-related info is somehow ignored/lost.I presume one key issue is that
#[config]
also creates aparse()
method that somehow clashes with the one the#[derive(Parser)]
wants to generate.The text was updated successfully, but these errors were encountered: