diff --git a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testColorDoccReference().md b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testColorDoccReference().md index 77ea1653..3c93125d 100644 --- a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testColorDoccReference().md +++ b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testColorDoccReference().md @@ -6,19 +6,21 @@ color --fav= [--second=] [--help] ``` -- term **--fav=\**: +### Options + +- term **--fav=\:** *Your favorite color.* -- term **--second=\**: +- term **--second=\:** *Your second favorite color.* This is optional. -- term **--help**: +- term **--help:** *Show help information.* @@ -31,9 +33,8 @@ Show subcommand help information. color help [...] ``` -- term **subcommands**: - - - +### Arguments +- term **subcommands:** +*The subcommand(s) you want help for.* diff --git a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testColorMarkdownReference().md b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testColorMarkdownReference().md index 966fd9cd..e2e944b9 100644 --- a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testColorMarkdownReference().md +++ b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testColorMarkdownReference().md @@ -6,6 +6,8 @@ color --fav= [--second=] [--help] ``` +### Options + **--fav=\:** *Your favorite color.* @@ -31,9 +33,8 @@ Show subcommand help information. color help [...] ``` -**subcommands:** - - - +### Arguments +**subcommands:** +*The subcommand(s) you want help for.* diff --git a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testCountLinesDoccReference().md b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testCountLinesDoccReference().md index 77b80fe5..797b73c2 100644 --- a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testCountLinesDoccReference().md +++ b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testCountLinesDoccReference().md @@ -6,22 +6,26 @@ count-lines [] [--prefix=] [--verbose] [--help] ``` -- term **input-file**: +### Arguments + +- term **input-file:** *A file to count lines in. If omitted, counts the lines of stdin.* -- term **--prefix=\**: +### Options + +- term **--prefix=\:** *Only count lines with this prefix.* -- term **--verbose**: +- term **--verbose:** *Include extra information in the output.* -- term **--help**: +- term **--help:** *Show help information.* @@ -34,9 +38,8 @@ Show subcommand help information. count-lines help [...] ``` -- term **subcommands**: - - - +### Arguments +- term **subcommands:** +*The subcommand(s) you want help for.* diff --git a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testCountLinesMarkdownReference().md b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testCountLinesMarkdownReference().md index 88b97b53..3146ee17 100644 --- a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testCountLinesMarkdownReference().md +++ b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testCountLinesMarkdownReference().md @@ -6,11 +6,15 @@ count-lines [] [--prefix=] [--verbose] [--help] ``` +### Arguments + **input-file:** *A file to count lines in. If omitted, counts the lines of stdin.* +### Options + **--prefix=\:** *Only count lines with this prefix.* @@ -34,9 +38,8 @@ Show subcommand help information. count-lines help [...] ``` -**subcommands:** - - - +### Arguments +**subcommands:** +*The subcommand(s) you want help for.* diff --git a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testMathDoccReference().md b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testMathDoccReference().md index 79cb53e5..2633dda6 100644 --- a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testMathDoccReference().md +++ b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testMathDoccReference().md @@ -8,12 +8,14 @@ A utility for performing maths. math [--version] [--help] ``` -- term **--version**: +### Options + +- term **--version:** *Show the version.* -- term **--help**: +- term **--help:** *Show help information.* @@ -26,27 +28,28 @@ Print the sum of the values. math add [--hex-output] [...] [--version] [--help] ``` -- term **--hex-output**: - -*Use hexadecimal notation for the result.* - +### Arguments -- term **values**: +- term **values:** *A group of integers to operate on.* -- term **--version**: +### Options -*Show the version.* +- term **--hex-output:** + +*Use hexadecimal notation for the result.* -- term **--help**: +- term **--version:** -*Show help information.* +*Show the version.* +- term **--help:** +*Show help information.* ## math.multiply @@ -56,27 +59,28 @@ Print the product of the values. math multiply [--hex-output] [...] [--version] [--help] ``` -- term **--hex-output**: - -*Use hexadecimal notation for the result.* +### Arguments - -- term **values**: +- term **values:** *A group of integers to operate on.* -- term **--version**: +### Options -*Show the version.* +- term **--hex-output:** +*Use hexadecimal notation for the result.* -- term **--help**: -*Show help information.* +- term **--version:** +*Show the version.* +- term **--help:** + +*Show help information.* ## math.stats @@ -86,12 +90,14 @@ Calculate descriptive statistics. math stats [--version] [--help] ``` -- term **--version**: +### Options + +- term **--version:** *Show the version.* -- term **--help**: +- term **--help:** *Show help information.* @@ -104,27 +110,28 @@ Print the average of the values. math stats average [--kind=] [...] [--version] [--help] ``` -- term **--kind=\**: - -*The kind of average to provide.* - +### Arguments -- term **values**: +- term **values:** *A group of floating-point values to operate on.* -- term **--version**: +### Options -*Show the version.* +- term **--kind=\:** +*The kind of average to provide.* -- term **--help**: -*Show help information.* +- term **--version:** + +*Show the version.* +- term **--help:** +*Show help information.* ### math.stats.stdev @@ -134,23 +141,24 @@ Print the standard deviation of the values. math stats stdev [...] [--version] [--help] ``` -- term **values**: +### Arguments + +- term **values:** *A group of floating-point values to operate on.* -- term **--version**: +### Options + +- term **--version:** *Show the version.* -- term **--help**: +- term **--help:** *Show help information.* - - - ### math.stats.quantiles Print the quantiles of the values (TBD). @@ -159,49 +167,48 @@ Print the quantiles of the values (TBD). math stats quantiles [] [] [] [...] [--file=] [--directory=] [--shell=] [--custom=] [--custom-deprecated=] [--version] [--help] ``` -- term **one-of-four**: +### Arguments +- term **one-of-four:** -- term **custom-arg**: +- term **custom-arg:** -- term **custom-deprecated-arg**: +- term **custom-deprecated-arg:** -- term **values**: + +- term **values:** *A group of floating-point values to operate on.* -- term **--file=\**: +### Options + +- term **--file=\:** -- term **--directory=\**: +- term **--directory=\:** -- term **--shell=\**: +- term **--shell=\:** -- term **--custom=\**: +- term **--custom=\:** -- term **--custom-deprecated=\**: +- term **--custom-deprecated=\:** -- term **--version**: +- term **--version:** *Show the version.* -- term **--help**: +- term **--help:** *Show help information.* - - - - - ## math.help Show subcommand help information. @@ -210,14 +217,15 @@ Show subcommand help information. math help [...] [--version] ``` -- term **subcommands**: - +### Arguments -- term **--version**: - -*Show the version.* +- term **subcommands:** +*The subcommand(s) you want help for.* +### Options +- term **--version:** +*Show the version.* diff --git a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testMathMarkdownReference().md b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testMathMarkdownReference().md index 78419e67..5552294f 100644 --- a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testMathMarkdownReference().md +++ b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testMathMarkdownReference().md @@ -8,6 +8,8 @@ A utility for performing maths. math [--version] [--help] ``` +### Options + **--version:** *Show the version.* @@ -26,16 +28,20 @@ Print the sum of the values. math add [--hex-output] [...] [--version] [--help] ``` -**--hex-output:** - -*Use hexadecimal notation for the result.* - +### Arguments **values:** *A group of integers to operate on.* +### Options + +**--hex-output:** + +*Use hexadecimal notation for the result.* + + **--version:** *Show the version.* @@ -45,9 +51,6 @@ math add [--hex-output] [...] [--version] [--help] *Show help information.* - - - ## math.multiply Print the product of the values. @@ -56,16 +59,20 @@ Print the product of the values. math multiply [--hex-output] [...] [--version] [--help] ``` -**--hex-output:** - -*Use hexadecimal notation for the result.* - +### Arguments **values:** *A group of integers to operate on.* +### Options + +**--hex-output:** + +*Use hexadecimal notation for the result.* + + **--version:** *Show the version.* @@ -75,9 +82,6 @@ math multiply [--hex-output] [...] [--version] [--help] *Show help information.* - - - ## math.stats Calculate descriptive statistics. @@ -86,6 +90,8 @@ Calculate descriptive statistics. math stats [--version] [--help] ``` +### Options + **--version:** *Show the version.* @@ -104,16 +110,20 @@ Print the average of the values. math stats average [--kind=] [...] [--version] [--help] ``` -**--kind=\:** - -*The kind of average to provide.* - +### Arguments **values:** *A group of floating-point values to operate on.* +### Options + +**--kind=\:** + +*The kind of average to provide.* + + **--version:** *Show the version.* @@ -123,9 +133,6 @@ math stats average [--kind=] [...] [--version] [--help] *Show help information.* - - - ### math.stats.stdev Print the standard deviation of the values. @@ -134,11 +141,15 @@ Print the standard deviation of the values. math stats stdev [...] [--version] [--help] ``` +### Arguments + **values:** *A group of floating-point values to operate on.* +### Options + **--version:** *Show the version.* @@ -148,9 +159,6 @@ math stats stdev [...] [--version] [--help] *Show help information.* - - - ### math.stats.quantiles Print the quantiles of the values (TBD). @@ -159,6 +167,8 @@ Print the quantiles of the values (TBD). math stats quantiles [] [] [] [...] [--file=] [--directory=] [--shell=] [--custom=] [--custom-deprecated=] [--version] [--help] ``` +### Arguments + **one-of-four:** @@ -173,6 +183,8 @@ math stats quantiles [] [] [] [< *A group of floating-point values to operate on.* +### Options + **--file=\:** @@ -197,11 +209,6 @@ math stats quantiles [] [] [] [< *Show help information.* - - - - - ## math.help Show subcommand help information. @@ -210,14 +217,15 @@ Show subcommand help information. math help [...] [--version] ``` -**subcommands:** +### Arguments +**subcommands:** -**--version:** - -*Show the version.* - +*The subcommand(s) you want help for.* +### Options +**--version:** +*Show the version.* diff --git a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRepeatDoccReference().md b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRepeatDoccReference().md index 9e6e982d..10a3c8e4 100644 --- a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRepeatDoccReference().md +++ b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRepeatDoccReference().md @@ -6,22 +6,26 @@ repeat [--count=] [--include-counter] [--help] ``` -- term **--count=\**: +### Arguments -*The number of times to repeat 'phrase'.* +- term **phrase:** +*The phrase to repeat.* -- term **--include-counter**: -*Include a counter with each repetition.* +### Options +- term **--count=\:** -- term **phrase**: +*The number of times to repeat 'phrase'.* -*The phrase to repeat.* +- term **--include-counter:** -- term **--help**: +*Include a counter with each repetition.* + + +- term **--help:** *Show help information.* @@ -34,9 +38,8 @@ Show subcommand help information. repeat help [...] ``` -- term **subcommands**: - - - +### Arguments +- term **subcommands:** +*The subcommand(s) you want help for.* diff --git a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRepeatMarkdownReference().md b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRepeatMarkdownReference().md index 8d0714b4..2af077c4 100644 --- a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRepeatMarkdownReference().md +++ b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRepeatMarkdownReference().md @@ -6,6 +6,15 @@ repeat [--count=] [--include-counter] [--help] ``` +### Arguments + +**phrase:** + +*The phrase to repeat.* + + +### Options + **--count=\:** *The number of times to repeat 'phrase'.* @@ -16,11 +25,6 @@ repeat [--count=] [--include-counter] [--help] *Include a counter with each repetition.* -**phrase:** - -*The phrase to repeat.* - - **--help:** *Show help information.* @@ -34,9 +38,8 @@ Show subcommand help information. repeat help [...] ``` -**subcommands:** - - - +### Arguments +**subcommands:** +*The subcommand(s) you want help for.* diff --git a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRollDoccReference().md b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRollDoccReference().md index 5db09afb..e0b2bba7 100644 --- a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRollDoccReference().md +++ b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRollDoccReference().md @@ -6,29 +6,31 @@ roll [--times=] [--sides=] [--seed=] [--verbose] [--help] ``` -- term **--times=\**: +### Options + +- term **--times=\:** *Rolls the dice times.* -- term **--sides=\**: +- term **--sides=\:** *Rolls an -sided dice.* Use this option to override the default value of a six-sided die. -- term **--seed=\**: +- term **--seed=\:** *A seed to use for repeatable random generation.* -- term **--verbose**: +- term **--verbose:** *Show all roll results.* -- term **--help**: +- term **--help:** *Show help information.* @@ -41,9 +43,8 @@ Show subcommand help information. roll help [...] ``` -- term **subcommands**: - - - +### Arguments +- term **subcommands:** +*The subcommand(s) you want help for.* diff --git a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRollMarkdownReference().md b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRollMarkdownReference().md index d84e3e2b..990c5282 100644 --- a/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRollMarkdownReference().md +++ b/Tests/ArgumentParserGenerateDoccReferenceTests/Snapshots/testRollMarkdownReference().md @@ -6,6 +6,8 @@ roll [--times=] [--sides=] [--seed=] [--verbose] [--help] ``` +### Options + **--times=\:** *Rolls the dice times.* @@ -41,9 +43,8 @@ Show subcommand help information. roll help [...] ``` -**subcommands:** - - - +### Arguments +**subcommands:** +*The subcommand(s) you want help for.* diff --git a/Tools/generate-docc-reference/Extensions/ArgumentParser+Markdown.swift b/Tools/generate-docc-reference/Extensions/ArgumentParser+Markdown.swift index 5e8f5787..7df9be9b 100644 --- a/Tools/generate-docc-reference/Extensions/ArgumentParser+Markdown.swift +++ b/Tools/generate-docc-reference/Extensions/ArgumentParser+Markdown.swift @@ -67,25 +67,64 @@ extension CommandInfoV0 { } if let args = self.arguments { - for arg in args { - guard arg.shouldDisplay else { - continue + // Group arguments by sectionTitle + // This is done to organize the arguments into categories (e.g., options, flags) + let groupedArgs = Dictionary( + grouping: args.filter { + $0.shouldDisplay } - - switch markdownStyle { - case .docc: - result += "- term **\(arg.identity())**:\n\n" - case .github: - result += "**\(arg.identity()):**\n\n" - } - - if let abstract = arg.abstract { - result += "*\(abstract)*\n\n" + ) { self.assignSectionTitle(to: $0) } + + // Iterate through the grouped arguments, sorted by section title + // Sorting ensures that the sections appear in a clear, predictable order in the final documentation. + // The sections are listed alphabetically based on their title, enhancing readability. + for (section, arguments) in groupedArgs.sorted(by: { $0.key < $1.key }) { + // Add section title as a Markdown header to the result + // Adding section titles as Markdown headers helps separate sections in the documentation, + // making it easier for users to navigate and understand the structure of the arguments. + result += "### \(section)\n\n" + + // Iterate through each argument in the section + // Iterating through each argument allows us to add details for each argument under its respective section. + for arg in arguments { + // Add the argument identity in bold Markdown format + // The argument identity is emphasized in bold to make it stand out in the documentation. + + + // If the argument has an abstract, add it in italic Markdown format + // Including the abstract provides a brief description of the argument's purpose. + // The italic formatting helps to distinguish the abstract from other parts of the documentation. + switch markdownStyle { + case .docc: + result += "- term **\(arg.identity()):**\n\n" + case .github: + result += "**\(arg.identity()):**\n\n" + } + + if let abstract = arg.abstract { + result += "*\(abstract)*\n\n" + } + + // Inject a default help description for the the `help` command positional argument 'subcommands'. + // The 'subcommands' argument is missing an abstract in ArgumentParser. + // This results in incomplete help documentation, which may confuse users. + // Since it's a positional argument named 'subcommands', it can be easily confused with actual subcommands. + if arg.identity() == "subcommands" && arg.abstract == nil { + result += "*The subcommand(s) you want help for.*\n\n" + } + + // If the argument has a discussion, add it directly + // If a discussion is available, it is added to provide further explanation on how the argument works. + // This additional context is helpful for users to understand the full usage of the argument. + if let discussion = arg.discussion { + result += discussion + "\n\n" + } + + // Add an empty line for separation between arguments + // The empty line improves the visual structure of the documentation, + // making it easier to read and separating each argument for clarity. + result += "\n" } - if let discussion = arg.discussion { - result += discussion + "\n\n" - } - result += "\n" } } @@ -95,6 +134,11 @@ extension CommandInfoV0 { path + [self.commandName], markdownStyle: markdownStyle) + "\n\n" } + // Trim any unnecessary trailing newline that could have been added inadvertently + // By trimming, we prevent extra lines at the end of the generated document + // which is important for snapshot comparison. + result = result.trimmingCharacters(in: .newlines) + return result } @@ -105,8 +149,23 @@ extension CommandInfoV0 { return args.map { $0.usage() }.joined(separator: " ") } + + // Assign a default section title based on the arguments types + func assignSectionTitle(to argument: ArgumentInfoV0) -> String { + if let sectionTitle = argument.sectionTitle { + return sectionTitle + } else { + switch argument.kind { + case .positional: + return "Arguments" + case .option, .flag: + return "Options" + } + } + } } + extension ArgumentInfoV0 { /// Returns a string that describes the use of the argument. /// diff --git a/Tools/generate-docc-reference/GenerateDoccReference.swift b/Tools/generate-docc-reference/GenerateDoccReference.swift index 922ded49..7bb056df 100644 --- a/Tools/generate-docc-reference/GenerateDoccReference.swift +++ b/Tools/generate-docc-reference/GenerateDoccReference.swift @@ -28,8 +28,7 @@ extension GenerateDoccReferenceError: CustomStringConvertible { case .unableToParseToolOutput(let error): return "Failed to parse tool output: \(error)" case .unsupportedDumpHelpVersion(let expected, let found): - return - "Unsupported dump help version, expected '\(expected)' but found: '\(found)'" + return "Unsupported dump help version, expected '\(expected)' but found: '\(found)'" case .failedToGenerateDoccReference(let error): return "Failed to generated docc reference: \(error)" } @@ -110,13 +109,14 @@ struct GenerateDoccReference: ParsableCommand { throw GenerateDoccReferenceError.unableToParseToolOutput(error: error) } - let toolInfo: ToolInfoV0 + var toolInfo: ToolInfoV0 + do { toolInfo = try JSONDecoder().decode(ToolInfoV0.self, from: data) } catch { throw GenerateDoccReferenceError.unableToParseToolOutput(error: error) } - + do { if self.outputDirectory == "-" { try self.generatePages(