#1537·clap

How can I handle this case which requires any group

Author: obliqueCreated Aug 28, 2019Updated Aug 28, 2026
LabelsC-enhancementA-validators:money_with_wings: $20S-waiting-on-design

I have a special flag which when it is set I want always one of two groups to match. This special flag should never passed alone.

To be more clear I created a simple example on what I want to achieve:

rust
use clap::{App, Arg, ArgGroup};

fn main() {
    let mut app = App::new("my-app")
        .arg(Arg::with_name("special").long("special"))
        .arg(Arg::with_name("opt-a1").long("opt-a1"))
        .arg(Arg::with_name("opt-a2").long("opt-a2"))
        .arg(Arg::with_name("opt-b1").long("opt-b1"))
        .arg(Arg::with_name("opt-b2").long("opt-b2"))
        .group(
            ArgGroup::with_name("special-and-opt-a")
                .args(&["opt-a1", "opt-a2"])
                .requires_all(&["special", "opt-a1", "opt-a2"])
                .conflicts_with("special-and-opt-b")
                .multiple(true)
                .required(false),
        )
        .group(
            ArgGroup::with_name("special-and-opt-b")
                .args(&["opt-b1", "opt-b2"])
                .requires_all(&["special", "opt-b1", "opt-b2"])
                .conflicts_with("special-and-opt-a")
                .multiple(true)
                .required(false),
        );

    let valid_cases = vec![
        vec!["my-app"],
        vec!["my-app", "--special", "--opt-a1", "--opt-a2"],
        vec!["my-app", "--special", "--opt-b1", "--opt-b2"],
    ];

    let invalid_cases = vec![
        vec!["my-app", "--opt-a1", "--opt-a2"],
        vec!["my-app", "--opt-b1", "--opt-b2"],
        vec!["my-app", "--special"],
        vec!["my-app", "--special", "--opt-a1"],
        vec!["my-app", "--special", "--opt-b1"],
        vec!["my-app", "--special", "--opt-a1", "--opt-a2", "--opt-b1"],
        vec!["my-app", "--special", "--opt-b1", "--opt-b2", "--opt-a1"],
        vec!["my-app", "--special", "--opt-a1", "--opt-a2", "--opt-b1", "-opt-b2"],
    ];

    for x in valid_cases {
        assert!(app.get_matches_from_safe_borrow(x).is_ok());
    }

    for x in invalid_cases {
        assert!(app.get_matches_from_safe_borrow(x).is_err());
    }
}

The case which I can not find how to handle is ["my-app", "--special"]. Of-course I can workaround this with is_present, but I'm curious if there is a solution via groups. Maybe this is a valid case where requires_any is needed.