-
Notifications
You must be signed in to change notification settings - Fork 347
[GenerateDocCReference] Improve filtering and categorization of arguments in documentation with sectionTitle #753
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
base: main
Are you sure you want to change the base?
Conversation
…ents in documentation with sectionTitle
…enerate-docc command instead of in toolinfo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this, @Chamepp! I think it would be great to focus this PR on just categorizing the arguments/options/flags, rather than also changing the subcommand display.
|
||
// 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this alphabetical sorting the same as used when printing help for the command-line tool?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way the documentation generation sorts this is: Arguments, Flags, Options.
If documentation generation sorts this without alphabetical sorting the placement of default section titles will not be consistent. We will get section titles sorted randomly every time.
When we are printing help for the repeat command, which includes all three types of values(arguments, flags and options), the output is sorted in this way: Arguments, Options. Then Options section include options listed first and then flags next.
I think with the addition of custom sectionTitles this is going to be a good implementation since it makes the documentation easier to work with. But as you mentioned I think it's important that we match the help output, and in some way we do.
I will wait for your feedback on this. If you think this is a good choice I will commit my changes. If not I will find another solution to make sure we list Arguments, Options and Flags in a consistent way that follows the help output pattern. Also I can implement alphabetical sorting for custom section titles.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume you might be busy so I went ahead and committed my changes and will request for review. Let me know if you think we should change the sorting logic.
Another problem that arises if we don’t maintain a consistent section creation via sorting is that the snapshot and the generated document will always differ since the document generation produces random results. This will cause the tests to fail every time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this alphabetical sorting the same as used when printing help for the command-line tool?
It is not. the help for the command-line tool prints the groups in the order that they are defined. IMO that's what the help text should do as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Chamepp why did you resolve this conversation? The code below still sorts the groups by name which I said in my comment above that I don't think we should do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@d-ronnqvist You’re right thanks for pointing it out. It wasn’t intentional, I mistakenly resolved this conversation alongside the outdated topics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't look like any of our Docc/Markdown generation tests include titled option groups, which means we aren't seeing the difference in section ordering. Could you add a test that includes a couple titled option groups, so that we can verify the results of this change?
Tools/generate-docc-reference/Extensions/ArgumentParser+Markdown.swift
Outdated
Show resolved
Hide resolved
Tools/generate-docc-reference/Extensions/ArgumentParser+Markdown.swift
Outdated
Show resolved
Hide resolved
Tools/generate-docc-reference/Extensions/ArgumentParser+Markdown.swift
Outdated
Show resolved
Hide resolved
Tools/generate-docc-reference/Extensions/ArgumentParser+Markdown.swift
Outdated
Show resolved
Hide resolved
@rauhul I’ve updated the PR and resolved the merge conflicts with the latest main. |
@Chamepp It looks like the merge lost some of the output, at least according to the test fixtures – can you take a look? |
@natecook1000 Sure. Solved merge conflicts again and force pushed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Chamepp, apologies for the delayed response! I think if we step back, this change would make the most sense if it aligned the structure of the generated DocC and man pages with what you see in the help screen for a command. Specifically:
- "Arguments" is the right category to come first
- "Options" should be the next category, including both
@Flag
and@Option
properties – that distinction is internal to the library, it's not an external one - Arguments/options/flags that are in a titled option group should be pulled out into a separate section with that title – see this test file for examples (AFAICT it doesn't look like this feature is covered in the tests for DocC or man page generation) https://github.com/apple/swift-argument-parser/blob/main/Tests/ArgumentParserUnitTests/HelpGenerationTests%2BGroupName.swift
- We should have some kind of default help text for the
command help <subcommand>
pseudo-argument, since there's no place to customize that.
Thanks again for your contribution here!
@natecook1000 Yes, I believe it's a great idea to keep things consistent in design. Keeping the categorization structure unified across DocC, the man page, and the help screen will provide clarity for the user through that consistency. I think it's definitely more user friendly. I'll revise the PR with the changes you suggested and get back to you. |
…ndard help output
Dear @natecook1000, I’ve updated my solutions according to the requested modifications and added a default help message for the subcommands argument. Personally, I see the @Argument(help: "The subcommand(s) you want help for.")
var subcommands: [String] = [] Since this PR mainly focuses on documentation generation, I’m happy to make that change in a separate PR. However, if you think it’s fine to include it here, I can go ahead and make the adjustments. Please let me know what you prefer and what you think of this solution. |
I also noticed that dear @heckj is working on an improvement that might cause a conflict with this PR. I’ll wait for their PR to be merged first, and then I’ll resolve any conflicts and revisit this. In the meantime I’ll think of some scenarios where adding the default help message during documentation generation could cause issues. It’s also possible I’m missing something. Perhaps there are challenges with adding the help message directly to the subcommands argument which I don't see yet. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My main question is how these changes makes the rendered documentation look. If you could include a few screenshots that show the rendered documentation with these changes, then that would make it easier to review.
// The italic formatting helps to distinguish the abstract from other parts of the documentation. | ||
switch markdownStyle { | ||
case .docc: | ||
result += "- term **\(arg.identity()):**\n\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally am not convinced that bold/strong text is the preferred style to represent a command line flag in a term-definition list. In my DocC proof of concept (here) I used "code voice" / monospaced text for the flags/options/arguments and I think that looks better on the rendered page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI: these trailing new lines aren't necessarily and can make it harder to associate the argument with its description. For example, consider this argument from one of the tests
- term **--seed=\<seed\>**:
*A seed to use for repeatable random generation.*
That could also have been written as either;
- term **--seed=\<seed\>**:
*A seed to use for repeatable random generation.*
or even
- term **--seed=\<seed\>**: *A seed to use for repeatable random generation.*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: is there an example from the tests where there's a flag/option has more then one name (for example -h
and --help
)? How does this code format such a flag/option?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally am not convinced that bold/strong text is the preferred style to represent a command line flag in a term-definition list. In my DocC proof of concept (here) I used "code voice" / monospaced text for the flags/options/arguments and I think that looks better on the rendered page.
Since our goal is to align with DocC’s style for documentation generation, I agree that using the “code voice” / monospaced style you suggested is a better way to represent arguments, options, and flags in the generated documentation. I’ll add this as a task with the associated requirements, and once the tasks and requirements are compiled, I’ll share the list with you for approval before making the modifications.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI: these trailing new lines aren't necessarily and can make it harder to associate the argument with its description. For example, consider this argument from one of the tests
- term **--seed=\<seed\>**: *A seed to use for repeatable random generation.*
That could also have been written as either;
- term **--seed=\<seed\>**: *A seed to use for repeatable random generation.*
or even
- term **--seed=\<seed\>**: *A seed to use for repeatable random generation.*
That’s a great point. Since we are aligning with the DocC generation style, I agree that this is a better implementation.
- term **--seed=\<seed\>**: *A seed to use for repeatable random generation.*
I think following this style is the better choice. I’ll also add it to my task list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: is there an example from the tests where there's a flag/option has more then one name (for example
-h
and--help
)? How does this code format such a flag/option?
The --hex-output
option for the math add
subcommand is a good example of the issue you mentioned, which I’ve highlighted in the screenshot earlier. For now, we are only displaying the long name in the terms list. My goal was to focus on the categorization and filtering of arguments for now and then plan to address the finer details in subsequent PR's to avoid complication and confusion.
In order to solve this we have to focus on this area and support short names for the arguments in the terms list alongside the long name setting. Then we could follow the DocC style you mentioned earlier in the PR you shared, to present them in a way that matches the expected output.
The area for the development:
// TODO: default values, short, etc.
var inner: String
switch self.kind {
case .positional:
inner = "<\(names.joined(separator: "|"))>"
case .option:
inner = "--\(names.joined(separator: "|"))=<\(self.valueName ?? "")>"
case .flag:
inner = "--\(names.joined(separator: "|"))"
}
Final output:
- term `-x`, `--hex-output`:
*A seed to use for repeatable random generation.*
If you think this can be handled in this PR, I can add it to my task list. If not, we can address it in the next PR. I’ll wait for your approval before adding it as a task for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can also go into more detail on how the solution would be implemented to give you a clearer picture, if you think that would be helpful. That way, we can better decide whether it makes sense to include it here or handle it in a separate PR.
} | ||
|
||
if let abstract = arg.abstract { | ||
result += "*\(abstract)*\n\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have two comments about this:
- With the blank line from above, can you verify that this text does in fact associate with the term-definition element correctly? I would think that the blank line and the lack of leading indentation would cause this to parse as a separate paragraph.
- If basically all the text in the documentation is emphasized, that emphasis looses its importance and only result in a page where all the text is slanted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I checked this and you’re right. After doing some research I realized that the extra newline isn’t necessary. Markdown treats a blank line as a paragraph break, so the abstract may be interpreted as a separate paragraph rather than part of the term definition list. In other words, DocC could render it disconnected from the term instead of as its definition. I’ll add this to my tasks and refine the solution. That was a great point, thank you for the feedback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I agree with you on this. The use of italics was already there when I started working on the solution, and I didn’t really question or change it. Overusing emphasis definitely makes it less effective, so I’ll add this to my tasks too and adjust this in my refinements.
// 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" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: where is this text displayed? IIRC the command line help text for the --help
flag is "Show help information."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you know, every command and subcommand has a default subcommand called help. This help command takes an argument called subcommands, which can cause confusion during development because it might be mistaken for the actual subcommands section.
The subcommands argument always appears at the end of each generated documentation under the help section.
We should have some kind of default help text for the help pseudo-argument, since there’s no place to customize that.
Previously, there was no default help text for this argument, so we added it manually. However, from your feedback I realized that the abstraction I introduced differs from the math add --help
→ help subcommands
argument. I’ll add this to my tasks and refine the solution accordingly.

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you know, every command and subcommand has a default subcommand called help.
If this is the same content for every command, is there much value in repeating a (more or less) identical automatic page for every CLI?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I never thought about it that way, that’s a smart approach. When it comes to decision making for design, I personally focus on essentialism too. If it’s not a 100 percent yes, then it’s a no, in order to increase focus and avoid clutter and noise. Doing this keeps the design simple. I also agree that in terms of software maintenance, avoiding duplication can be helpful. But since users already expect the --help
flag and help subcommand to be present for every command, and because we want the command help output to be consistent, I believe the user’s cognitive load is lower by avoiding surprises. In this case, consistency outweighs the small cost of duplication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe keeping help in the same place consistently reduces mental effort. Even if the text or page is repetitive, it makes the documentation easier to navigate. Users don’t have to guess where help is documented, it’s always there, in the same way. When I think about the end result, skipping or centralizing it could lead to an uneven experience, where some commands have help documented and others don’t.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A counterargument would be that the more unimportant pages the documentation contains, the harder it is for readers to find the pages that are important.
|
||
|
||
- term **--verbose**: | ||
- term **--verbose:** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: does this render as expected? I know that term-definition lists split on the colon but I don't know of the top of my head what happens if the colon is inside a formatted element.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked into this and from my research it seems important that the colon remain outside of the formatting. I believe the colon acts as a syntactic separator. It signals a term definition pair for the DocC parser. If it’s wrapped inside, the parser may no longer recognize it as a separator. I’ll add this to my tasks as well.
|
||
### Arguments | ||
|
||
**phrase:** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: should this argument also be listed as a term-definition element?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well since its a positional argument and we should match the help output structure for filtering and categorization, yes it should be listed as a term definition under the Arguments
section.
} | ||
|
||
let toolInfo: ToolInfoV0 | ||
var toolInfo: ToolInfoV0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious: what's the reason for making this property mutable? At a glance I couldn't see any mutations in the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You’re right. I don’t actually mutate toolInfo, so it makes sense to make it a let. I’ll add it to my tasks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the compiler would have warned about this. Are there any other warnings that are introduced by the changes in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I double checked this. I ran a clean build with:
swift package clean
swift build -Xswiftc -warnings-as-errors
so any warnings introduced by my changes would fail the build.

The build did fail, but it was due to an existing deprecation warning, customDeprecated
in DumpHelpGenerator.swift
, not something introduced in this PR.
To confirm, I ran:
git blame Sources/ArgumentParser/Usage/DumpHelpGenerator.swift -L 213,217
and saw that this code was added in commit 42585ad (2025-05-07) by Ross Goldberg, so it predates my changes.
So to clarify, my PR doesn’t introduce new warnings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. I thought the compiler would notice that this is never modified but maybe it doesn't because it's assigned on a later line.
Tools/generate-docc-reference/Extensions/ArgumentParser+Markdown.swift
Outdated
Show resolved
Hide resolved
roll [--times=<n>] [--sides=<m>] [--seed=<seed>] [--verbose] [--help] | ||
``` | ||
|
||
### Options |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: how are arguments, flags, and options organized in the command-line help text? Are they organized into categories there as well? I feel that the documentation's organization should follow the command-line help text's organization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I actually covered this earlier with the screenshot and explanation. The organization in the documentation directly follows the command line help text’s organization, so they stay consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where can I find that screenshot? I don't see any in the PR description.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@d-ronnqvist I have already included screenshots of both the generated documentation output and the CLI help output for the math add
subcommand here. For better understanding and in order to make the comparison clearer, I’ll also share an example of the roll command you mentioned below.
Our solution currently follows and matches the command help output structure and categorization. In the help output, the organization is consistent. Positional arguments appear first under the Arguments
section, followed by the Options
section, where optional arguments are listed first and flags are listed afterward.
Since the roll command doesn’t have any positional arguments, there is no Arguments
category for it in the generated help text. The math add
help output is a better reference because it includes both positional arguments and options, and shows how they are listed in the help output.


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding this screenshot.
Even though this (below) wasn't what my question was about, I can spot a few different issues by comparing the command line output with that web page:
- The two dashes that prefix each long flag name is joined together into an "en"-dash instead of displaying as two separate
-
characters. This impacts the reader in two ways;- they can't copy the flag name from the documentation and paste it on the command line
- it looks like one dash when reading the documentation, so they might manually write it on the command line with one dash instead of two.
- Both, the
<n>
inRolls the dice <n>-times
and the<m>
inRoll an <m>-sided dice.
aren't rendering on the page because they're parsed as unrecognized html tags. Because<value>
is how the help text displays the argument's value, it's not entirely unlikely that developers would refer to the value in the documentation as<value>
. It might be worth doing something about this, even if it's just opening a new issue to track this so that it doesn't get lost. - The default values aren't displayed anywhere.
- The short flag names aren't displayed anywhere.
- The command is referred to as an "Article". This could be solved with a custom
@TitleHeading
directive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICT all of those issues are existing ones for the DocC reference output, not new ones that result from @Chamepp's changes. We should track these separately.
@d-ronnqvist Here are screenshots demonstrating how the generated document categorizes the math add subcommand, matching its help output: ![]() ![]() |
@d-ronnqvist Here’s the task list I put together based on your earlier suggestions. Thank you again for your feedback, it really helped shape a much more mature solution.
The only task I’m waiting on is supporting short names alongside long names in the documentation generation, which I mentioned earlier. I’ll wait for your approval before working on it to see if you consider it appropriate for this PR. Otherwise, I can handle it in a subsequent PR. In the meantime, I’m continuing work on the tasks above.
|
@d-ronnqvist One thing I’ve realized is that I don’t yet have a deep understanding of the DocC documentation generation process or how the parser works at its core. Since you’ve spent a lot of time building it, you clearly have a more mature perspective and expertise than I do. You’re spotting connections and areas for improvement that I’ve been missing. Because of that, I thought it might be great if you could highlight some issues or areas in DocC that I could contribute to. By working on those, I’d be able to build enough knowledge to design more mature solutions in the future. So far, my approach has been to build on Swift Argument Parser and check for DocC compatibility along the way. But I believe first developing a stronger understanding of DocC would make the process much faster and lead to better solutions. If you consider this a good approach, I’d love the chance to contribute to DocC as well and keep learning through that. |
…arity Co-authored-by: David Rönnqvist <ronnqvist@apple.com>
…ArgumentInfoV0 extension
roll [--times=<n>] [--sides=<m>] [--seed=<seed>] [--verbose] [--help] | ||
``` | ||
|
||
### Options |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICT all of those issues are existing ones for the DocC reference output, not new ones that result from @Chamepp's changes. We should track these separately.
|
||
// 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't look like any of our Docc/Markdown generation tests include titled option groups, which means we aren't seeing the difference in section ordering. Could you add a test that includes a couple titled option groups, so that we can verify the results of this change?
Summary
The recent modifications improve the readability and structure of documents generated using the GenerateDocC plugin. This update addresses #722 by enhancing how arguments are categorized within sections using the sectionTitle property.
Now, arguments—including required arguments, optionals, and flags—are grouped under their respective sectionTitles based on their type. Since sectionTitle is an optional value, some arguments may not have one explicitly provided. To handle this, we introduced logic that assigns a default section when no custom sectionTitle is specified. These default sections are:
Each argument is placed under its corresponding section based on its type. This ensures a well-structured and organized documentation format while allowing users to define their own custom sectionTitles when needed.
Changes
Listing arguments under custom sectionTitles
Default section titles for missing values
Better argument categorization and organization
Fixed missing dash in argument output
Updated unit tests and snapshot recordings
Re-ran and updated snapshot tests for:
Since section titles now have default values, output consistency has been verified.
Subcommands now have their own category
(Closes #722)"
Checklist