Skip to content

Commit e7765e1

Browse files
authored
Replace createHelp and includeHidden (#405)
- Replaces `ArgumentSet.init(_:creatingHelp:includeHidden:)` with `ArgumentSet.init(_:visibility:)`. `visibility` intentionally does not have a default value to ensure that callers only have the correct arguments. As part of this change `includeHidden` has been replaced throughout the codebase with `visibility`. This change also fixes a bug where arguments with hidden `visibility` were being displayed in the generated command usage string.
1 parent e344426 commit e7765e1

14 files changed

+94
-43
lines changed

Sources/ArgumentParser/Completions/BashCompletionsGenerator.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,14 +122,16 @@ struct BashCompletionsGenerator {
122122

123123
/// Returns the option and flag names that can be top-level completions.
124124
fileprivate static func generateArgumentWords(_ commands: [ParsableCommand.Type]) -> [String] {
125-
commands.argumentsForHelp().flatMap { $0.bashCompletionWords() }
125+
commands
126+
.argumentsForHelp(visibility: .default)
127+
.flatMap { $0.bashCompletionWords() }
126128
}
127129

128130
/// Returns additional top-level completions from positional arguments.
129131
///
130132
/// These consist of completions that are defined as `.list` or `.custom`.
131133
fileprivate static func generateArgumentCompletions(_ commands: [ParsableCommand.Type]) -> [String] {
132-
ArgumentSet(commands.last!)
134+
ArgumentSet(commands.last!, visibility: .default)
133135
.compactMap { arg -> String? in
134136
guard arg.isPositional else { return nil }
135137

@@ -156,7 +158,7 @@ struct BashCompletionsGenerator {
156158

157159
/// Returns the case-matching statements for supplying completions after an option or flag.
158160
fileprivate static func generateOptionHandlers(_ commands: [ParsableCommand.Type]) -> String {
159-
ArgumentSet(commands.last!)
161+
ArgumentSet(commands.last!, visibility: .default)
160162
.compactMap { arg -> String? in
161163
let words = arg.bashCompletionWords()
162164
if words.isEmpty { return nil }

Sources/ArgumentParser/Completions/FishCompletionsGenerator.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ struct FishCompletionsGenerator {
5656
}
5757

5858
let argumentCompletions = commands
59-
.argumentsForHelp()
59+
.argumentsForHelp(visibility: .default)
6060
.flatMap { $0.argumentSegments(commandChain) }
6161
.map { complete(ancestors: $0, suggestion: $1) }
6262

Sources/ArgumentParser/Completions/ZshCompletionsGenerator.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ struct ZshCompletionsGenerator {
103103
}
104104

105105
static func generateCompletionArguments(_ commands: [ParsableCommand.Type]) -> [String] {
106-
commands.argumentsForHelp().compactMap { $0.zshCompletionString(commands) }
106+
commands
107+
.argumentsForHelp(visibility: .default)
108+
.compactMap { $0.zshCompletionString(commands) }
107109
}
108110
}
109111

Sources/ArgumentParser/Parsable Properties/ArgumentVisibility.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,27 @@ public enum ArgumentVisibility {
2020
/// Never show help for this argument.
2121
case `private`
2222
}
23+
24+
extension ArgumentVisibility {
25+
/// A raw Integer value that represents each visibility level.
26+
///
27+
/// `_comparableLevel` can be used to test if a Visibility case is more or
28+
/// less visible than another, without committing this behavior to API.
29+
/// A lower `_comparableLevel` indicates that the case is less visible (more
30+
/// secret).
31+
private var _comparableLevel: Int {
32+
switch self {
33+
case .default:
34+
return 2
35+
case .hidden:
36+
return 1
37+
case .private:
38+
return 0
39+
}
40+
}
41+
42+
/// - Returns: true if `self` is at least as visible as the supplied argument.
43+
func isAtLeastAsVisible(as other: Self) -> Bool {
44+
self._comparableLevel >= other._comparableLevel
45+
}
46+
}

Sources/ArgumentParser/Parsable Properties/OptionGroup.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public struct OptionGroup<Value: ParsableArguments>: Decodable, ParsedWrapper {
6464
/// Creates a property that represents another parsable type.
6565
public init() {
6666
self.init(_parsedValue: .init { _ in
67-
ArgumentSet(Value.self)
67+
ArgumentSet(Value.self, visibility: .private)
6868
})
6969
}
7070

Sources/ArgumentParser/Parsable Types/ParsableArguments.swift

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ extension ParsableArguments {
163163
includeHidden: Bool = false,
164164
columns: Int? = nil
165165
) -> String {
166-
HelpGenerator(self, includeHidden: includeHidden)
166+
HelpGenerator(self, visibility: includeHidden ? .hidden : .default)
167167
.rendered(screenWidth: columns)
168168
}
169169

@@ -269,7 +269,7 @@ extension ArgumentSetProvider {
269269
}
270270

271271
extension ArgumentSet {
272-
init(_ type: ParsableArguments.Type, creatingHelp: Bool = false, includeHidden: Bool = false) {
272+
init(_ type: ParsableArguments.Type, visibility: ArgumentVisibility) {
273273

274274
#if DEBUG
275275
do {
@@ -285,13 +285,8 @@ extension ArgumentSet {
285285
guard var codingKey = child.label else { return nil }
286286

287287
if let parsed = child.value as? ArgumentSetProvider {
288-
if creatingHelp {
289-
if includeHidden {
290-
guard parsed._visibility != .private else { return nil }
291-
} else {
292-
guard parsed._visibility == .default else { return nil }
293-
}
294-
}
288+
guard parsed._visibility.isAtLeastAsVisible(as: visibility)
289+
else { return nil }
295290

296291
// Property wrappers have underscore-prefixed names
297292
codingKey = String(codingKey.first == "_"

Sources/ArgumentParser/Parsable Types/ParsableCommand.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ extension ParsableCommand {
108108
) -> String {
109109
HelpGenerator(
110110
commandStack: CommandParser(self).commandStack(for: subcommand),
111-
includeHidden: includeHidden)
111+
visibility: includeHidden ? .hidden : .default)
112112
.rendered(screenWidth: columns)
113113
}
114114

@@ -141,7 +141,7 @@ extension ParsableCommand {
141141
/// `true` if this command contains any array arguments that are declared
142142
/// with `.unconditionalRemaining`.
143143
internal static var includesUnconditionalArguments: Bool {
144-
ArgumentSet(self).contains(where: {
144+
ArgumentSet(self, visibility: .private).contains(where: {
145145
$0.isRepeatingPositional && $0.parsingStrategy == .allRemainingInput
146146
})
147147
}

Sources/ArgumentParser/Parsing/CommandParser.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ extension CommandParser {
130130
/// possible.
131131
fileprivate mutating func parseCurrent(_ split: inout SplitArguments) throws -> ParsableCommand {
132132
// Build the argument set (i.e. information on how to parse):
133-
let commandArguments = ArgumentSet(currentNode.element)
133+
let commandArguments = ArgumentSet(currentNode.element, visibility: .private)
134134

135135
// Parse the arguments, ignoring anything unexpected
136136
let values = try commandArguments.lenientParse(
@@ -315,7 +315,7 @@ extension CommandParser {
315315
let completionValues = Array(args)
316316

317317
// Generate the argument set and parse the argument to find in the set
318-
let argset = ArgumentSet(current.element)
318+
let argset = ArgumentSet(current.element, visibility: .private)
319319
let parsedArgument = try! parseIndividualArg(argToMatch, at: 0).first!
320320

321321
// Look up the specified argument and retrieve its custom completion function

Sources/ArgumentParser/Usage/DumpHelpGenerator.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ fileprivate extension BidirectionalCollection where Element == ParsableCommand.T
3838
/// Returns the ArgumentSet for the last command in this stack, including
3939
/// help and version flags, when appropriate.
4040
func allArguments() -> ArgumentSet {
41-
guard var arguments = self.last.map({ ArgumentSet($0, creatingHelp: false) })
41+
guard var arguments = self.last.map({ ArgumentSet($0, visibility: .private) })
4242
else { return ArgumentSet() }
4343
self.versionArgumentDefinition().map { arguments.append($0) }
4444
self.helpArgumentDefinition().map { arguments.append($0) }

Sources/ArgumentParser/Usage/HelpCommand.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ struct HelpCommand: ParsableCommand {
1919
@Argument var subcommands: [String] = []
2020

2121
/// Capture and ignore any extra help flags given by the user.
22-
@Flag(name: [.short, .long, .customLong("help", withSingleDash: true)], help: .hidden)
22+
@Flag(name: [.short, .long, .customLong("help", withSingleDash: true)], help: .private)
2323
var help = false
2424

2525
private(set) var commandStack: [ParsableCommand.Type] = []
@@ -39,7 +39,10 @@ struct HelpCommand: ParsableCommand {
3939

4040
/// Used for testing.
4141
func generateHelp(screenWidth: Int) -> String {
42-
HelpGenerator(commandStack: commandStack).rendered(screenWidth: screenWidth)
42+
HelpGenerator(
43+
commandStack: commandStack,
44+
visibility: visibility)
45+
.rendered(screenWidth: screenWidth)
4346
}
4447

4548
enum CodingKeys: CodingKey {

0 commit comments

Comments
 (0)