Skip to content
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
266 changes: 266 additions & 0 deletions Schemas/tool-info-v1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ToolInfo V1 Schema",
"description": "JSON schema for Swift Argument Parser ToolInfo V1 structure",
"type": "object",
"required": ["serializationVersion", "command"],
"properties": {
"serializationVersion": {
"type": "integer",
"const": 1,
"description": "A sentinel value indicating the version of the ToolInfo struct used to generate the serialized form"
},
"command": {
"$ref": "#/definitions/CommandInfo"
}
},
"definitions": {
"CommandInfo": {
"type": "object",
"required": ["commandName"],
"properties": {
"superCommands": {
"type": "array",
"items": {
"type": "string"
},
"description": "Super commands and tools"
},
"shouldDisplay": {
"type": "boolean",
"default": true,
"description": "Command should appear in help displays"
},
"commandName": {
"type": "string",
"description": "Name used to invoke the command"
},
"abstract": {
"type": "string",
"description": "Short description of the command's functionality"
},
"discussion": {
"type": "string",
"description": "Extended description of the command's functionality"
},
"defaultSubcommand": {
"type": "string",
"description": "Optional name of the subcommand invoked when the command is invoked with no arguments"
},
"subcommands": {
"type": "array",
"items": {
"$ref": "#/definitions/CommandInfo"
},
"description": "List of nested commands"
},
"arguments": {
"type": "array",
"items": {
"$ref": "#/definitions/ArgumentInfo"
},
"description": "List of supported arguments"
}
}
},
"ArgumentInfo": {
"type": "object",
"required": ["kind", "shouldDisplay", "isOptional", "isRepeating", "parsingStrategy"],
"properties": {
"kind": {
"$ref": "#/definitions/ArgumentKind"
},
"shouldDisplay": {
"type": "boolean",
"description": "Argument should appear in help displays"
},
"sectionTitle": {
"type": "string",
"description": "Custom name of argument's section"
},
"isOptional": {
"type": "boolean",
"description": "Argument can be omitted"
},
"isRepeating": {
"type": "boolean",
"description": "Argument can be specified multiple times"
},
"parsingStrategy": {
"$ref": "#/definitions/ParsingStrategy"
},
"names": {
"type": "array",
"items": {
"$ref": "#/definitions/NameInfo"
},
"description": "All names of the argument"
},
"preferredName": {
"$ref": "#/definitions/NameInfo",
"description": "The best name to use when referring to the argument in help displays"
},
"valueName": {
"type": "string",
"description": "Name of argument's value"
},
"defaultValue": {
"type": "string",
"description": "Default value of the argument is none is specified on the command line"
},
"allValues": {
"type": "array",
"items": {
"type": "string"
},
"description": "List of all valid values"
},
"allValueDescriptions": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Mapping of valid values to descriptions of the value"
},
"completionKind": {
"$ref": "#/definitions/CompletionKind",
"description": "The type of completion to use for an argument or an option value"
},
"abstract": {
"type": "string",
"description": "Short description of the argument's functionality"
},
"discussion": {
"type": "string",
"description": "Extended description of the argument's functionality"
}
}
},
"NameInfo": {
"type": "object",
"required": ["kind", "name"],
"properties": {
"kind": {
"$ref": "#/definitions/NameInfoKind"
},
"name": {
"type": "string",
"description": "Single or multi-character name of the argument"
}
}
},
"NameInfoKind": {
"type": "string",
"enum": ["long", "short", "longWithSingleDash"],
"description": "Kind of prefix of an argument's name"
},
"ArgumentKind": {
"type": "string",
"enum": ["positional", "option", "flag"],
"description": "Kind of argument"
},
"ParsingStrategy": {
"type": "string",
"enum": ["default", "scanningForValue", "unconditional", "upToNextOption", "allRemainingInput", "postTerminator", "allUnrecognized"],
"description": "Parsing strategy of the ArgumentInfo"
},
"CompletionKind": {
"oneOf": [
{
"type": "object",
"required": ["list"],
"properties": {
"list": {
"type": "object",
"required": ["values"],
"properties": {
"values": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
},
"description": "Use the specified list of completion strings"
},
{
"type": "object",
"required": ["file"],
"properties": {
"file": {
"type": "object",
"required": ["extensions"],
"properties": {
"extensions": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
},
"description": "Complete file names with the specified extensions"
},
{
"type": "object",
"required": ["directory"],
"properties": {
"directory": {
"type": "object"
}
},
"description": "Complete directory names that match the specified pattern"
},
{
"type": "object",
"required": ["shellCommand"],
"properties": {
"shellCommand": {
"type": "object",
"required": ["command"],
"properties": {
"command": {
"type": "string"
}
}
}
},
"description": "Call the given shell command to generate completions"
},
{
"type": "object",
"required": ["custom"],
"properties": {
"custom": {
"type": "object"
}
},
"description": "Generate completions using the given three-parameter closure"
},
{
"type": "object",
"required": ["customAsync"],
"properties": {
"customAsync": {
"type": "object"
}
},
"description": "Generate completions using the given async three-parameter closure"
},
{
"type": "object",
"required": ["customDeprecated"],
"properties": {
"customDeprecated": {
"type": "object"
}
},
"description": "Generate completions using the given one-parameter closure (deprecated)"
}
]
}
}
}
3 changes: 2 additions & 1 deletion Sources/ArgumentParser/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ add_library(ArgumentParser
Parsing/ParserError.swift
Parsing/SplitArguments.swift

Usage/DumpHelpGenerator.swift
Usage/DumpHelpGeneratorV0.swift
Usage/DumpHelpGeneratorV1.swift
Usage/HelpCommand.swift
Usage/HelpGenerator.swift
Usage/MessageInfo.swift
Expand Down
4 changes: 2 additions & 2 deletions Sources/ArgumentParser/Parsable Properties/Errors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public struct CleanExit: Error, CustomStringConvertible {
internal enum Representation {
case helpRequest(ParsableCommand.Type? = nil)
case message(String)
case dumpRequest(ParsableCommand.Type? = nil)
case dumpRequest(ParsableCommand.Type? = nil, DumpHelpVersion)
}

internal var base: Representation
Expand Down Expand Up @@ -113,7 +113,7 @@ public struct CleanExit: Error, CustomStringConvertible {
switch self.base {
case .helpRequest: return "--help"
case .message(let message): return message
case .dumpRequest: return "--experimental-dump-help"
case .dumpRequest(_, let version): return "--\(version.flagName)"
}
}
}
10 changes: 8 additions & 2 deletions Sources/ArgumentParser/Parsable Types/ParsableArguments.swift
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,15 @@ extension ParsableArguments {
.rendered(screenWidth: columns)
}

/// Returns the JSON representation of this type.
/// Returns the JSON representation of this type using the tool-info v0 (experimental-dump-help) schema.
@available(*, deprecated, renamed: "_dumpToolInfo(version:)")
public static func _dumpHelp() -> String {
DumpHelpGenerator(self).rendered()
DumpHelpVersion.v0.render(self)
}

/// Returns the JSON representation of the tool-info of this type using the provided version of the schema.
public static func _dumpToolInfo(version: DumpHelpVersion) -> String {
version.render(self)
}

/// Returns the exit code for the given error.
Expand Down
10 changes: 6 additions & 4 deletions Sources/ArgumentParser/Parsing/CommandParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,12 @@ extension CommandParser {
throw HelpRequested(visibility: .hidden)
}

// Look for dump-help flag
guard !split.contains(Name.long("experimental-dump-help")) else {
throw CommandError(
commandStack: commandStack, parserError: .dumpHelpRequested)
// Look for dump-help flags
for version in DumpHelpVersion.allCases {
guard !split.contains(Name.long(version.flagName)) else {
throw CommandError(
commandStack: commandStack, parserError: .dumpHelpRequested(version))
}
}

// Look for a version flag if any commands in the stack define a version
Expand Down
38 changes: 37 additions & 1 deletion Sources/ArgumentParser/Parsing/ParserError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,47 @@
//
//===----------------------------------------------------------------------===//

/// Represents supported OpenCLI schema versions.
public enum DumpHelpVersion: String, CaseIterable, Sendable {
// swift-format-ignore: AlwaysUseLowerCamelCase
case v0 = "v0"

// swift-format-ignore: AlwaysUseLowerCamelCase
case v1 = "v1"

public var flagName: String {
switch self {
case .v0:
"experimental-dump-help"
default:
"help-dump-tool-info-\(self.rawValue)"
}
}

public func render(commandStack: [ParsableCommand.Type]) -> String {
switch self {
case .v0:
DumpHelpGeneratorV0(commandStack: commandStack).rendered()
case .v1:
DumpHelpGeneratorV1(commandStack: commandStack).rendered()
}
}

public func render(_ type: any ParsableArguments.Type) -> String {
switch self {
case .v0:
DumpHelpGeneratorV0(type).rendered()
case .v1:
DumpHelpGeneratorV1(type).rendered()
}
}
}

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

case completionScriptRequested(shell: String?)
case completionScriptCustomResponse(String)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal import ArgumentParserToolInfo
import ArgumentParserToolInfo
#endif

internal struct DumpHelpGenerator {
internal struct DumpHelpGeneratorV0 {
private var toolInfo: ToolInfoV0

init(_ type: ParsableArguments.Type) {
Expand Down
Loading