Skip to content

Add --man man page generator from a shared usage model#400

Open
gmipf wants to merge 1 commit into
superg:mainfrom
gmipf:man-page-generator
Open

Add --man man page generator from a shared usage model#400
gmipf wants to merge 1 commit into
superg:mainfrom
gmipf:man-page-generator

Conversation

@gmipf

@gmipf gmipf commented Jun 25, 2026

Copy link
Copy Markdown

This adds a --man option that emits a roff man page, generated from the
same in-code usage definition that --help already prints. The goal is to give
packagers a man page that never drifts from the actual command/option set,
without maintaining a separate hand-written .1 downstream.

Today printUsage() hard-codes each command and option as a LOG(...) line,
and any man page a distribution ships has to be hand-maintained in parallel, so
it drifts whenever an option changes. This refactors the usage text into a small
data model and feeds both outputs from it.

What it does:

  • Adds UsageOption / UsageGroup / UsageCommand plus usageCommands() and
    usageGroups(), holding the commands, option groups and descriptions. Numeric
    option defaults are interpolated with std::format from compile-time constants
    (a small set of *_default values shared with the constructor), so the printed
    default always reflects the built-in value.

  • Rewrites printUsage() to iterate that model. The --help output is
    unchanged except for the corrections noted below (column widths are computed
    from the longest entry).

  • Adds printUsageMan(), which iterates the same model and writes a man page,
    reachable through a new hidden --man flag. Packagers can then generate
    the page at build time:

    redumper --man > redumper.1
    

While here, this corrects two pre-existing issues, both of which the old
hard-coded printUsage() already had:

  • --mediatek-leadout-retries binds to an integer argument in the parser, but
    its usage text omitted the =VALUE marker. The output now includes it. This
    is the only change to plain redumper --help.
  • The usage text formatted its "default" values from the mutable parsed members,
    so an override combined with help — e.g. redumper --retries=9 --help
    printed 9 as the "default" instead of 0. Sourcing the defaults from
    compile-time constants fixes this for both --help and --man.

So plain redumper --help stays byte-for-byte identical apart from the one
=VALUE line; the only other behavioral change is that an override no longer
leaks into the displayed default.

The output uses only the standard man(7) macros (.TH/.SH/.SS/.TP/.B) and
escapes roff metacharacters, so it renders identically under groff (Linux) and
mandoc (macOS and the BSDs). As redumper also ships a CLI on macOS, the same
generated page is reusable there (e.g. for a Homebrew formula) and on the BSDs,
not just on Linux distributions. The .TH date is intentionally left blank for
the packager to stamp at build time (e.g. from SOURCE_DATE_EPOCH), keeping the
generator output reproducible.

Verification (ubuntu-24.04, clang-18 + libc++-18, matching the Linux CI):

  • cmake --build + ctest: all 358 tests pass.
  • clang-format-18 --dry-run -Werror: clean.
  • diff of plain --help before and after: only the one corrected
    --mediatek-leadout-retries line differs.
  • redumper --retries=9 --help now prints (default: 0) instead of
    (default: 9).
  • groff -mandoc -ww: no warnings.
  • mandoc -T lint (the parser used on macOS and the BSDs): no errors; the only
    note is the intentionally blank .TH date.

The change is standard C++20 with no platform-specific code, so the Windows and
macOS build jobs should be unaffected, but I've only been able to run the Linux
toolchain locally.

A couple of things I'm happy to adjust in review:

  • Whether you'd want a CMake/CPack install target for the generated page, or
    prefer to leave generation to downstream packagers.
  • The NAME line wording (currently taken from the README:
    "low-level byte-perfect CD/DVD/HD-DVD/Blu-ray disc dumper").

Prepared with AI assistance (Claude Opus 4.8) and reviewed before submission.

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Structured usage data now drives console help and man-page output. Options gains man from --man, printUsage() becomes data-driven, and main() routes the new flag to the man-page printer.

Changes

Usage help and man-page output

Layer / File(s) Summary
Usage model and flag parsing
options.ixx
The usage structs are added, man is added to Options, and --man parsing plus default initialization are wired in.
Console usage formatting
options.ixx
printUsage() now renders command and option sections from shared usage data with computed widths.
Man-page output path
main.cc, options.ixx
main() routes options.man to printUsageMan(), which emits roff sections using the shared usage model and escaping helpers.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

A rabbit hopped with paper bright,
And roffed the help page just right.
--man now sings in tidy rows,
With wrapped-up text and grouped-up shows,
A moonlit usage feast tonight 🐰

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding a --man man page generator based on shared usage data.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
options.ixx (1)

471-471: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Brace placement violates repository C++ style rule

return { should place { on the next line per project style.

As per coding guidelines: "Always add a new line before {".

Also applies to: 494-494

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@options.ixx` at line 471, The brace placement in the return statements
violates the repository C++ style rule, so update the affected `return`
expressions in `options.ixx` to put the opening `{` on its own next line instead
of on the same line as `return`. Apply the same formatting fix to both
occurrences mentioned in the diff, keeping the surrounding logic unchanged.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@options.ixx`:
- Line 530: The usage text for the option entry in options.ixx is missing the
value marker for a parameterized flag. Update the help string for the
--mediatek-leadout-retries entry so it includes =VALUE, matching the parser’s
expected integer argument and keeping --help and --help-man consistent with the
behavior of the option definition.

---

Nitpick comments:
In `@options.ixx`:
- Line 471: The brace placement in the return statements violates the repository
C++ style rule, so update the affected `return` expressions in `options.ixx` to
put the opening `{` on its own next line instead of on the same line as
`return`. Apply the same formatting fix to both occurrences mentioned in the
diff, keeping the surrounding logic unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a93e3343-a012-411f-999e-46907daec205

📥 Commits

Reviewing files that changed from the base of the PR and between cbf7c9b and 67b9903.

📒 Files selected for processing (2)
  • main.cc
  • options.ixx

Comment thread options.ixx Outdated
Comment thread options.ixx
private:
static std::vector<UsageCommand> usageCommands()
{
return {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Regarding the return { brace placement (also at line 494): clang-format-18 — the formatter the CI clang-format Check runs — produces and accepts this layout, and reformats the brace back onto this line if it is moved to its own line, so changing it would fail the format gate. The repository's "Always add a new line before {" rule and the .clang-format Allman wrapping apply to statement and declaration blocks, not to braced-init-list expressions like return {...}. I've left it as the formatter emits it to keep the check green, but I'm happy to adjust if you'd prefer a different layout.

Generated with Claude Opus 4.8.

@gmipf gmipf force-pushed the man-page-generator branch from f41d599 to 7cdff2d Compare June 26, 2026 09:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@options.ixx`:
- Around line 187-188: The option parser in the command-line handling logic
recognizes only the hidden flag currently checked in the key comparison, so the
intended man-page switch is not accepted. Update the parsing branch that sets
the man-page mode to accept the documented hidden flag name used by the PR
objective, and keep the existing unknown-option handling unchanged so the parser
routes the correct flag into the same man-page path.
- Around line 492-575: The help text in usageGroups() is formatting “default”
values from mutable parsed members such as retries, plextor_leadin_retries,
mediatek_leadout_retries, audio_silence_threshold, skip_fill,
cdr_error_threshold, and scsi_timeout, which lets argv overrides leak into
--help and --man output. Update usageGroups() to source these descriptions from
invariant built-in default constants or static constexpr defaults instead of
runtime state, so the rendered docs always reflect the true compile-time
defaults regardless of parsed options.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b3e15204-23ad-45c1-a810-1addabb7eb84

📥 Commits

Reviewing files that changed from the base of the PR and between f41d599 and 7cdff2d.

📒 Files selected for processing (2)
  • main.cc
  • options.ixx
🚧 Files skipped from review as they are similar to previous changes (1)
  • main.cc

Comment thread options.ixx
Comment thread options.ixx
@gmipf gmipf changed the title Add --help-man man page generator from a shared usage model Add --man man page generator from a shared usage model Jun 26, 2026
Refactor printUsage() to build its output from a small data model
(UsageCommand/UsageGroup/UsageOption) instead of hard-coded LOG lines.
Add printUsageMan(), reachable via a hidden --man flag, which renders
the same model as a roff man page (standard man(7) macros, renders
warning-free under groff and mandoc -T lint) so packagers can generate
redumper.1 without maintaining it separately.

The shared model sources value-option defaults from compile-time
constants, so --help and --man always print the built-in default. This
keeps plain --help byte-identical apart from correcting the
--mediatek-leadout-retries usage text to show =VALUE, and additionally
fixes a pre-existing case where an override such as --retries=9 --help
printed the override (9) as the "default" instead of 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gmipf gmipf force-pushed the man-page-generator branch from 7cdff2d to 32b656d Compare June 26, 2026 10:05

@superg superg left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I'm sorry I cannot accept this for the following reasons:

  • man page is different from the built-in help and it shouldn't be a part of program implementation, it's perfectly fine not to have a man page for a utility
  • it's slop and it changed a lot of things human would not change

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.

2 participants