Help: Cmdliner mutually exclusive argument that is a string

I need add a mutually exclusive argument that is a string using Cmdliner lib.

Example

./program --suppress dir_a,dir_b

## or

./program --unsuppress dir_a,dir_b

The examples I found take a boolean indicating which argument was used, but beyond that I need the value.

open Cmdliner

let suppress_unsuppress =
  Arg.(
    value & vflag None
    & [
        ( Some true,
          info
            ~doc:
              "Don't report on files whose path has a prefix in the list. \
               Comma-separated-path-prefixes"
            ["suppress"] );
        ( Some false,
          info ~doc:"Report on files whose path has a prefix in the list"
            ["unsuppress"] );
      ])
in

Couldn’t you supply both flags at the same time if they specify disjoint sets of prefixes?

I would approach that behavior by adding a validation step after the args had been parsed that ensures the sets of prefixes are disjoint.

Maybe you have no choice how to design the flags but if you do, here are some alternatives:

  • make suppress and unsuppress` sub commands (like in Git), which is supported by Cmdliner.
  • make one behaviour the default and use just one flag to revert to the other. This is what commands like gzip do.

You can make that work at the Term level.

Here’s an example: 4 mutually exclusive arguments, which are assembled into a single term that checks for exclusivity.

4 Likes