I am trying to customize headers in the help screen generated by SAP using @OptionGroup.
Question 1. Is this the best/only way to customized headers?
Question 2. If so, how do I get rid of the OPTIONS header in the example. Or change it to, say, “OTHER OPTIONS”?
Example:
This is not what I am doing, but it illustrates the issue.
[I] release> ./repeat-phrase --help
OVERVIEW: Repeat a phrase multiple times.
USAGE: repeat-phrase [--count <count>] [--prefix <prefix>] [--include-counter] [--uppercase] [--lowercase] <phrase>
ARGUMENTS:
<phrase> The phrase to repeat.
CONTENT:
-c, --count <count> How many times to repeat 'phrase'. (default: 2)
-p, --prefix <prefix> A word or two to prefix 'phrase'.
-i, --include-counter Include a counter with each repetition.
FORMATTING OPTIONS:
-u, --uppercase Print text in upper case
-l, --lowercase Print text in lower case.
OPTIONS:
-h, --help Show help information.
Here is the code:
@main
struct RepeatPhrase: ParsableCommand {
static let configuration = CommandConfiguration(
abstract: "Repeat a phrase multiple times.")
@OptionGroup(title: "CONTENT") var c: Content
@OptionGroup(title: "FORMATTING OPTIONS") var f: Format
@Argument(help: "The phrase to repeat.")
var phrase: String
mutating func run() throws {
var text = phrase
if let prefix = c.prefix { text = "\(prefix) - \(text)" }
text = f.lowercase ? text.lowercased() : f.uppercase ? text.uppercased() : text
for i in 1...(max(c.count, 1)) {
if c.includeCounter { print("\(i): \(text)") } else { print(text) }
}
}
}
struct Format: ParsableArguments {
@Flag(name: .shortAndLong, help: "Print text in upper case")
var uppercase = false
@Flag(name: .shortAndLong, help: "Print text in lower case.")
var lowercase = false
}
struct Content: ParsableArguments {
@Option(name: .shortAndLong ,help: "How many times to repeat 'phrase'.")
var count: Int = 2
@Option(name: .shortAndLong ,help: "A word or two to prefix 'phrase'.")
var prefix: String?
@Flag(name: .shortAndLong , help: "Include a counter with each repetition.")
var includeCounter = false
}
Indeed! Anything that isn't grouped in a titled option group gets put in an ARGUMENTS or OPTIONS bucket.
...which includes the --help flag. There isn't a built-in way to move this to a different group, but you could hack it by suppressing the default flag, and then providing your own help flag inside an option group, and throwing CleanExit.helpRequest(self) from either validate() or run().
[I] release> ./repeat-phrase --help
OVERVIEW: Repeat a phrase multiple times.
USAGE: repeat-phrase [--count <count>] [--prefix <prefix>] [--include-counter] [--uppercase] [--lowercase] [--help] <phrase>
ARGUMENTS:
<phrase> The phrase to repeat.
CONTENT:
-c, --count <count> How many times to repeat 'phrase'. (default: 2)
-p, --prefix <prefix> A word or two to prefix 'phrase'.
-i, --include-counter Include a counter with each repetition.
FORMATTING OPTIONS:
-u, --uppercase Print text in upper case
-l, --lowercase Print text in lower case.
OTHER OPTIONS:
-h, --help Trigger help
OPTIONS:
-h, --help Show help information.
But I still need to suppress the default flag, and I don’t know how. Could someone please tell me how to do it?
If a phrase , say “Hi”, is added, so that there are no errors, the hacked —help is detected.
[I] release> ./repeat-phrase hi --help
OVERVIEW: Repeat a phrase multiple times.
USAGE: repeat-phrase [--count <count>] [--prefix <prefix>] [--include-counter] [--uppercase] [--lowercase] [--help] <phrase>
ARGUMENTS:
<phrase> The phrase to repeat.
CONTENT:
-c, --count <count> How many times to repeat 'phrase'. (default: 2)
-p, --prefix <prefix> A word or two to prefix 'phrase'.
-i, --include-counter Include a counter with each repetition.
FORMATTING OPTIONS:
-u, --uppercase Print text in upper case
-l, --lowercase Print text in lower case.
OTHER OPTIONS:
-h, --help Trigger help
Here’s the code:
@main
struct RepeatPhrase: ParsableCommand {
static let configuration = CommandConfiguration(
abstract: "Repeat a phrase multiple times.", helpNames: [])
@OptionGroup(title: "CONTENT") var c: Content
@OptionGroup(title: "FORMATTING OPTIONS") var f: Format
@OptionGroup(title: "OTHER OPTIONS") var o: OtherOptions
@Argument(help: "The phrase to repeat.")
var phrase: String
mutating func run() throws {
if o.help {
throw CleanExit.helpRequest(self)
}
var text = phrase
if let prefix = c.prefix { text = "\(prefix) - \(text)" }
text = f.lowercase ? text.lowercased() : f.uppercase ? text.uppercased() : text
for i in 1...(max(c.count, 1)) {
if c.includeCounter { print("\(i): \(text)") } else { print(text) }
}
}
}
struct OtherOptions: ParsableCommand {
@Flag(name: .shortAndLong, help: "Trigger help")
var help = false
}
struct Format: ParsableArguments {
@Flag(name: .shortAndLong, help: "Print text in upper case")
var uppercase = false
@Flag(name: .shortAndLong, help: "Print text in lower case.")
var lowercase = false
}
struct Content: ParsableArguments {
@Option(name: .shortAndLong ,help: "How many times to repeat 'phrase'.")
var count: Int = 2
@Option(name: .shortAndLong ,help: "A word or two to prefix 'phrase'.")
var prefix: String?
@Flag(name: .shortAndLong , help: "Include a counter with each repetition.")
var includeCounter = false
}
Where I think we are now is that SAP supports custom headers in its built-in help screen, except for the help flag (and presumably the version option).
IMO custom headers in help screens are essential. And the help flag exception is a show-stopper.
Is it possible to simply mark the help flag as not visible? It would still not be possible to put under a custom header, but that would be fine with me. (Everybody knows to enter —help to get help).
Would it be possible to add another property to Configuration, say nameOfOptionGroupToContainTheHelpFlag: String?