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.