Can one set up groups of options that "shadow" each other?

Once you get past very simple CLIs, it is common to have conflicting options, especially flags.

Here is how ls handles it:

The -1, -C, -x, and -l options all override each other; the last one specified
determines the format used.

The -c, -u, and -U options all override each other; the last one specified
determines the file time used.

Here is rm

The -f option overrides any previous -i options.

The -i option overrides any previous -f options.

I haven't figured out how to do this in Argument Parser. Am I missing something?

You might want to look into Custom Enumerable Flags. It lets you support non-binary Flags.

This should reimplement the rm command’s -f,-i and -I flags with Swift Argument Parser

enum PromptMode {
    case never
    case always
    case once
    case unassigned
}

extension PromptMode: EnumerableFlag {
    static func name(for value: Self) -> NameSpecification {
        switch value {
        case .never:  return [.customShort("f"),.customLong("force")]
        case .once:   return .customShort("I")
        case .always: return .customShort("i")
        default:      return [] // No Flags for internal modes
        }
    }
    
    static func help(for value: Self) -> ArgumentHelp? {
        switch value {
        case .never:  return "ignore nonexistent files, never prompt"
        case .once:   return "prompt once before removing more than three files or when removing recursively"
        case .always: return "prompt before every removal"
        default:      return .init("This is an internal mode and has no flags", visibility: .private)
        }
    }
}

You can put it in your ParsableCommand with

@Flag(exclusivity: .chooseLast)
var promptMode: PromptMode = .unassigned
2 Likes

Thanks. Especially for writing out the example.