Skip to content

[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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

Chamepp
Copy link
Contributor

@Chamepp Chamepp commented Apr 3, 2025

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:

  • Arguments – for required arguments
  • Options – for optional values
  • Flags – for boolean flags

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

    • If a custom sectionTitle is provided, arguments are correctly grouped under it.
  • Default section titles for missing values

    • When no custom sectionTitle is given, arguments are automatically grouped based on their type:
      • Positional arguments → "Arguments"
      • Options → "Options"
      • Flags → "Flags"
  • Better argument categorization and organization

    • Arguments are now properly grouped and listed under designated sections.
    • Ensures all arguments appear under an appropriate category, whether a custom or default sectionTitle is provided.
  • Fixed missing dash in argument output

    • The previous method incorrectly displayed arguments like -option instead of --option.
    • Now, options are displayed correctly with a double dash (--option) by wrapping the argument in (‘’)
  • Updated unit tests and snapshot recordings

    • Re-ran and updated snapshot tests for:

      • Documentation snapshots
      • Dump help snapshots
    • Since section titles now have default values, output consistency has been verified.

  • Subcommands now have their own category

    • Ensured subcommands are listed under a dedicated section to maintain consistency across all argument categories.

(Closes #722)"

Checklist

  • I've added at least one test that validates that my change is working, if appropriate
  • I've followed the code style of the rest of the project
  • I've read the Contribution Guidelines
  • I've updated the documentation if necessary

@@ -218,7 +218,23 @@ public struct ArgumentInfoV0: Codable, Hashable {
self.kind = kind

self.shouldDisplay = shouldDisplay
self.sectionTitle = sectionTitle

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be part of ToolInfo. Instead the consumer of tool info can choose how to interpret the missing title. (the consumers of toolinfo are/will be: generate–docc-reference, generate-manual, generate-shell-completion, help-generation, usage-generation)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your feedback dear Rauhul. I handled the logic in the generate-docc command.

@Chamepp Chamepp requested a review from rauhul April 3, 2025 23:21
Copy link
Member

@natecook1000 natecook1000 left a 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.

@@ -126,4 +153,19 @@ struct GenerateDoccReference: ParsableCommand {
print(page)
}
}

func assignSectionTitle(to argument: ArgumentInfoV0) throws -> String {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any errors that this function is throwing, which would eliminate the need for the new argumentAssignmentFailed error above.


// 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.
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Comment on lines 108 to 119
if let subcommands = self.subcommands, !subcommands.isEmpty {
// Add a separate section for subcommands.
// Subcommands are treated differently from regular arguments, so they deserve their own section in the documentation.
// This helps to visually distinguish subcommands from regular arguments, enhancing readability.
result += "## Subcommands\n\n"

// Iterate through each subcommand and convert it to Markdown format
// Each subcommand is processed and added to the documentation under the "Subcommands" section.
// This ensures that users can easily identify and understand the subcommands available for the command.
for subcommand in subcommands {
result += subcommand.toMarkdown(path + [self.commandName])
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this change to how subcommands are listed is an improvement, since it ends up hard to see the hierarchy between commands (see the math docs). Could you keep this PR focused on grouping the args/options/flags by section?

Copy link
Contributor Author

@Chamepp Chamepp Apr 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. The reason I changed this alongside the argument grouping was because after grouping the arguments, the subcommands started to feel a bit confusing. Since I was already organizing arguments into sections, I thought it might make sense to give subcommands their own section as well. And since both changes were aligned with the same purpose which is grouping by section, I thought it would be reasonable to include this small change in the same PR. I’ve now reverted the changes related to subcommands.

}
if let discussion = arg.discussion {
result += discussion + "\n\n"
) { $0.sectionTitle ?? "General" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the "General" fallback needed here? It looks like the section titles might only be added for the root-level command (see the subcommands in the math docs for example).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason behind this fallback was that in case the property doesn’t have a custom sectionTitle and doesn’t fall into arguments default categories, it will be placed under the General category. I thought this will be great to handle this edge case and we can spot problems when the General section appears alongside throwing an error. I think I have developed a bad habit of over engineering. From now on I will focus on what's necessary and essential.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I checked the Math documentation output. This wasn’t an issue when I was assigning the default value in the ToolInfo. Since subcommands also uses the toMarkDown() function from the GenerateDocC extension, we should handle the default value of the section in the CommandInfoV0 extension. By doing this, every single command that uses the toMarkdown() can benefit from this feature. I have implemented this and will commit my new changes soon.

@Chamepp Chamepp requested a review from natecook1000 April 12, 2025 14:10
// 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"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is targeting markdown for use in DocC in particular, I'd recommend using ### for section headers. DocC tends to preserve the 2nd level headers for a couple specific uses, and it doesn't always reflect arbitrary headers at the second level in the way you might expect. (the two common ones are ## Overview and ## Topics)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a great point, thank you. I will adjust it shortly.

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.
result += "**`\(arg.identity())`**\n\n"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is for DocC consumption in particular, this pattern could benefit from using term lists. In DocC markdown, that looks something like:

- term `--hosting-base-path <hosting-base-path>`:
  The base path where your will host your documentation.

^ the above example is a bit more focused on using it for flags, but figured I'd toss it out there.

Note that regular (GitHub-flavored) markdown doesn't respect this term markup - so if you want to use this in both GH and DocC, this likely isn't a winner suggestion.

Copy link
Contributor Author

@Chamepp Chamepp Apr 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for taking the time to review this. I agree that using term lists is beneficial. I had actually noticed a separate issue related to this #721 and was planning to open a new pull request for it since the contribution guidelines emphasize the importance of making small focused changes that address a single goal. The same with the snapshot record issue. I saw that you already addressed it, appreciate that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

generate-docc-reference: group argument my section title
4 participants