Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Sketch] Supplemental discussion #479

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions [email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ var package = Package(
name: "ArgumentParser",
targets: ["ArgumentParser"]),
.plugin(
name: "GenerateManualPlugin",
targets: ["Generate Manual"]),
name: "GenerateManual",
targets: ["GenerateManual"]),
],
dependencies: [],
targets: [
Expand All @@ -40,13 +40,12 @@ var package = Package(

// Plugins
.plugin(
name: "Generate Manual",
name: "GenerateManual",
capability: .command(
intent: .custom(
verb: "generate-manual",
description: "Generate a manual entry for a specified target.")),
dependencies: ["generate-manual"],
path: "Plugins/GenerateManualPlugin"),
dependencies: ["generate-manual"]),

// Examples
.executableTarget(
Expand Down
1 change: 1 addition & 0 deletions Sources/ArgumentParser/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ add_library(ArgumentParser
Usage/DumpHelpGenerator.swift
Usage/HelpCommand.swift
Usage/HelpGenerator.swift
Usage/HelpOptions.swift
Usage/MessageInfo.swift
Usage/UsageGenerator.swift

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Customizing Help for Commands

Define your command's abstract, extended discussion, or usage string, and set the flags used to invoke the help display.
Define your command's abstract, discussion, or usage string, and set the flags used to invoke the help display.

## Overview

Expand Down
67 changes: 40 additions & 27 deletions Sources/ArgumentParser/Parsable Properties/ArgumentHelp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ public struct ArgumentHelp {

/// An expanded description of the argument, in plain text form.
public var discussion: String = ""


/// Additional detailed description of the argument, in plain text form.
///
/// This discussion is shown in the detailed help display and supplemental
/// content such as generated manuals.
public var detailedDiscussion: String = ""

/// An alternative name to use for the argument's value when showing usage
/// information.
///
Expand All @@ -28,41 +34,17 @@ public struct ArgumentHelp {
/// the extended help display.
public var visibility: ArgumentVisibility = .default

/// A Boolean value indicating whether this argument should be shown in
/// the extended help display.
@available(*, deprecated, message: "Use visibility level instead.")
public var shouldDisplay: Bool {
get {
return visibility.base == .default
}
set {
visibility = newValue ? .default : .hidden
}
}

/// Creates a new help instance.
@available(*, deprecated, message: "Use init(_:discussion:valueName:visibility:) instead.")
public init(
_ abstract: String = "",
discussion: String = "",
valueName: String? = nil,
shouldDisplay: Bool)
{
self.abstract = abstract
self.discussion = discussion
self.valueName = valueName
self.shouldDisplay = shouldDisplay
}

/// Creates a new help instance.
public init(
_ abstract: String = "",
discussion: String = "",
detailedDiscussion: String = "",
valueName: String? = nil,
visibility: ArgumentVisibility = .default)
{
self.abstract = abstract
self.discussion = discussion
self.detailedDiscussion = detailedDiscussion
self.valueName = valueName
self.visibility = visibility
}
Expand All @@ -83,3 +65,34 @@ extension ArgumentHelp: ExpressibleByStringInterpolation {
self.abstract = value
}
}

// MARK: - Deprecated API
extension ArgumentHelp {
/// A Boolean value indicating whether this argument should be shown in
/// the extended help display.
@available(*, deprecated, message: "Use visibility level instead.")
public var shouldDisplay: Bool {
get {
return visibility.base == .default
}
set {
visibility = newValue ? .default : .hidden
}
}

/// Creates a new help instance.
@available(*, deprecated, message: "Use init(_:discussion:detailedDiscussion:valueName:visibility:) instead.")
public init(
_ abstract: String = "",
discussion: String = "",
valueName: String? = nil,
shouldDisplay: Bool)
{
self.init(
abstract,
discussion: discussion,
detailedDiscussion: "",
valueName: valueName,
visibility: shouldDisplay ? .default : .hidden)
}
}
39 changes: 38 additions & 1 deletion Sources/ArgumentParser/Parsable Types/CommandConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ public struct CommandConfiguration {
/// A longer description of this command, to be shown in the extended help
/// display.
public var discussion: String

/// Additional detailed description of the argument to be shown in the
/// detailed help display and supplemental content such as generated manuals.
public var detailedDiscussion: String

/// Version information for this command.
public var version: String
Expand Down Expand Up @@ -67,6 +71,9 @@ public struct CommandConfiguration {
/// automatically generating a usage description. Passing an empty string
/// hides the usage string altogether.
/// - discussion: A longer description of the command.
/// - detailedDiscussion: Additional detailed description to be shown in the
/// detailed help display and supplemental content such as generated
/// manuals.
/// - version: The version number for this command. When you provide a
/// non-empty string, the argument parser prints it if the user provides
/// a `--version` flag.
Expand All @@ -85,6 +92,7 @@ public struct CommandConfiguration {
abstract: String = "",
usage: String? = nil,
discussion: String = "",
detailedDiscussion: String = "",
version: String = "",
shouldDisplay: Bool = true,
subcommands: [ParsableCommand.Type] = [],
Expand All @@ -95,6 +103,7 @@ public struct CommandConfiguration {
self.abstract = abstract
self.usage = usage
self.discussion = discussion
self.detailedDiscussion = detailedDiscussion
self.version = version
self.shouldDisplay = shouldDisplay
self.subcommands = subcommands
Expand All @@ -110,6 +119,7 @@ public struct CommandConfiguration {
abstract: String = "",
usage: String? = nil,
discussion: String = "",
detailedDiscussion: String = "",
version: String = "",
shouldDisplay: Bool = true,
subcommands: [ParsableCommand.Type] = [],
Expand All @@ -121,6 +131,7 @@ public struct CommandConfiguration {
self.abstract = abstract
self.usage = usage
self.discussion = discussion
self.detailedDiscussion = ""
self.version = version
self.shouldDisplay = shouldDisplay
self.subcommands = subcommands
Expand All @@ -130,7 +141,7 @@ public struct CommandConfiguration {
}

extension CommandConfiguration {
@available(*, deprecated, message: "Use the memberwise initializer with the usage parameter.")
@available(*, deprecated, message: "Use the member-wise initializer with the usage parameter.")
public init(
commandName: String?,
abstract: String,
Expand All @@ -146,6 +157,32 @@ extension CommandConfiguration {
abstract: abstract,
usage: "",
discussion: discussion,
detailedDiscussion: "",
version: version,
shouldDisplay: shouldDisplay,
subcommands: subcommands,
defaultSubcommand: defaultSubcommand,
helpNames: helpNames)
}

@available(*, deprecated, message: "Use the member-wise initializer with the detailedDiscussion parameter.")
public init(
commandName: String?,
abstract: String,
usage: String,
discussion: String,
version: String,
shouldDisplay: Bool,
subcommands: [ParsableCommand.Type],
defaultSubcommand: ParsableCommand.Type?,
helpNames: NameSpecification?
) {
self.init(
commandName: commandName,
abstract: abstract,
usage: usage,
discussion: discussion,
detailedDiscussion: "",
version: version,
shouldDisplay: shouldDisplay,
subcommands: subcommands,
Expand Down
8 changes: 6 additions & 2 deletions Sources/ArgumentParser/Parsable Types/ParsableArguments.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ extension ParsableArguments {
// Parse the command and unwrap the result if necessary.
switch try self.asCommand.parseAsRoot(arguments) {
case let helpCommand as HelpCommand:
throw ParserError.helpRequested(visibility: helpCommand.visibility)
throw ParserError.helpRequested(options: helpCommand.options)
case let result as _WrappedParsableCommand<Self>:
return result.options
case var result as Self:
Expand Down Expand Up @@ -142,7 +142,11 @@ extension ParsableArguments {
includeHidden: Bool = false,
columns: Int? = nil
) -> String {
HelpGenerator(self, visibility: includeHidden ? .hidden : .default)
HelpGenerator(
self,
options: .init(
visibility: includeHidden ? .hidden : .default,
detailed: false))
.rendered(screenWidth: columns)
}

Expand Down
4 changes: 3 additions & 1 deletion Sources/ArgumentParser/Parsable Types/ParsableCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ extension ParsableCommand {
) -> String {
HelpGenerator(
commandStack: CommandParser(self).commandStack(for: subcommand),
visibility: includeHidden ? .hidden : .default)
options: .init(
visibility: includeHidden ? .hidden : .default,
detailed: false))
.rendered(screenWidth: columns)
}

Expand Down
2 changes: 2 additions & 0 deletions Sources/ArgumentParser/Parsing/ArgumentDefinition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ struct ArgumentDefinition {
var isComposite: Bool
var abstract: String
var discussion: String
var detailedDiscussion: String
var valueName: String
var visibility: ArgumentVisibility
var parentTitle: String
Expand All @@ -71,6 +72,7 @@ struct ArgumentDefinition {
self.isComposite = isComposite
self.abstract = help?.abstract ?? ""
self.discussion = help?.discussion ?? ""
self.detailedDiscussion = help?.detailedDiscussion ?? ""
self.valueName = help?.valueName ?? ""
self.visibility = help?.visibility ?? .default
self.parentTitle = ""
Expand Down
21 changes: 11 additions & 10 deletions Sources/ArgumentParser/Parsing/CommandParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct CommandError: Error {
}

struct HelpRequested: Error {
var visibility: ArgumentVisibility
var options: HelpOptions
}

struct CommandParser {
Expand Down Expand Up @@ -85,15 +85,16 @@ extension CommandParser {
requireSoloArgument: Bool = false
) throws {
guard !requireSoloArgument || split.count == 1 else { return }

// Look for help flags
guard !split.contains(anyOf: self.commandStack.getHelpNames(visibility: .default)) else {
throw HelpRequested(visibility: .default)
}

// Look for help-hidden flags
guard !split.contains(anyOf: self.commandStack.getHelpNames(visibility: .hidden)) else {
throw HelpRequested(visibility: .hidden)
// Search for various help flags [.default, .hidden] x [standard, detailed]
for visibility in [ArgumentVisibility.default, .hidden] {
for detailed in [false, true] {
let options = HelpOptions(visibility: visibility, detailed: detailed)
let helpNames = self.commandStack.getHelpNames(options: options)
if split.contains(anyOf: helpNames) {
throw HelpRequested(options: options)
}
}
}

// Look for dump-help flag
Expand Down Expand Up @@ -254,7 +255,7 @@ extension CommandParser {
} catch let helpRequest as HelpRequested {
return .success(HelpCommand(
commandStack: commandStack,
visibility: helpRequest.visibility))
options: helpRequest.options))
} catch {
return .failure(CommandError(commandStack: commandStack, parserError: .invalidState))
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/ArgumentParser/Parsing/ParserError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

/// Gets thrown while parsing and will be handled by the error output generation.
enum ParserError: Error {
case helpRequested(visibility: ArgumentVisibility)
case helpRequested(options: HelpOptions)
case versionRequested
case dumpHelpRequested

Expand Down
4 changes: 3 additions & 1 deletion Sources/ArgumentParser/Usage/DumpHelpGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ fileprivate extension CommandInfoV0 {
commandName: command._commandName,
abstract: command.configuration.abstract,
discussion: command.configuration.discussion,
detailedDiscussion: command.configuration.detailedDiscussion,
defaultSubcommand: defaultSubcommand,
subcommands: subcommands,
arguments: arguments)
Expand All @@ -135,7 +136,8 @@ fileprivate extension ArgumentInfoV0 {
defaultValue: argument.help.defaultValue,
allValues: argument.help.allValues,
abstract: argument.help.abstract,
discussion: argument.help.discussion)
discussion: argument.help.discussion,
detailedDiscussion: argument.help.detailedDiscussion)
}
}

Expand Down
Loading