Comment-based help examples now support optional titles - #27387
Marius Storhaug (MariusStorhaug) wants to merge 41 commits into
Conversation
…into feature/example-titles-in-comment-help
… tests - Revert CommentHelpInfo.Examples to ReadOnlyCollection<string>; add parallel ExampleTitles property per issue spec (non-breaking) - Update HelpCommentsParser to maintain parallel _exampleTitles list - Make ProxyCommand.ExtractExampleTitle culture-agnostic (anchor on dashes/colon, not the literal English word EXAMPLE) - Fix \n vs backtick-n in ProxyCommand round-trip tests - Add tests: line-comment titled examples, ExampleTitles count parity, title ending with dash, untitled-output regression
…is not blocked by an unrelated pre-existing failure in ScriptHelp.Tests.ps1
…fix and function-scope isolation
|
If this is interesting, ill continue with the other repos to align those with the added feature. |
There was a problem hiding this comment.
Pull request overview
Adds support for optional titles on comment-based help examples using the .EXAMPLE <Title> syntax, and preserves those titles through XML generation and proxy help comment round-tripping.
Changes:
- Extend comment-based help parsing and XML generation to capture/render optional
.EXAMPLEtitles. - Add a new
CommentHelpInfo.ExampleTitlesparallel collection and updateGetCommentBlock()to round-trip titled examples. - Update
ProxyCommand.GetHelpComments()to emit.EXAMPLE <title>when a user title can be recovered, and add Pester coverage for the new behavior.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/System.Management.Automation/help/HelpCommentsParser.cs |
Captures .EXAMPLE <title> in the parser and appends titles to the generated example heading. |
src/System.Management.Automation/engine/parser/ast.cs |
Adds CommentHelpInfo.ExampleTitles and updates GetCommentBlock() to emit .EXAMPLE <title> when present. |
src/System.Management.Automation/engine/ProxyCommand.cs |
Extracts user titles from decorated MAML headings and emits .EXAMPLE <title> during proxy help comment generation. |
test/powershell/Language/Scripting/ScriptHelp.ExampleTitles.Tests.ps1 |
New Pester coverage for titled .EXAMPLE parsing, round-trip via GetCommentBlock(), and backward compatibility. |
test/powershell/engine/Api/ProxyCommand.Tests.ps1 |
Adds tests asserting ProxyCommand.GetHelpComments() preserves/emits titled examples and handles edge cases. |
…ng comment in ExtractExampleTitle
…hen ProxyCommand title round-trip tests
- Updated the XML doc on ExtractExampleTitle to say ':' (matching the
IndexOf(':') implementation) instead of the misleading ': '.
- Changed the existing round-trip assertion from Should -Not -BeNullOrEmpty
(trivially true for all examples) to exact title equality comparison.
- Added a dedicated test 'ProxyCommand.GetHelpComments preserves custom
example titles' that defines a function with titled and untitled examples,
round-trips through GetHelpComments, and asserts the custom title text
survives.
Use the fixed generated heading border and first colon-space delimiter without culture or example-number matching. Preserve unframed titles and add cross-culture and title-boundary regression coverage.
|
Tested commit This exposed two existing title-preservation bugs in platyPS, addressed in PowerShell/platyPS#864. With that fix, all 10 sample example headings survive export unchanged. The platyPS fix follows the same localization-independent principle: remove decorative borders without interpreting the example label. Unlike proxy comment generation, platyPS retains the complete numbered heading, so it does not split at |
|
The companion documentation PR is ready for review: MicrosoftDocs/PowerShell-Docs#13272 It documents optional |
Remove anchored dash-and-space borders without depending on a fixed width. Preserve hyphens in custom titles and leave malformed borders unchanged. Add regression coverage for border widths, required separator spaces, and title punctuation. Co-authored-by: Copilot App <[email protected]>
Capture the custom title and outer borders in one non-backtracking regex. Preserve existing untitled, localized, malformed-heading, and punctuation behavior. Add exact round-trip coverage for authored dash borders and internal hyphens, including line-comment help. Co-authored-by: Copilot App <[email protected]>
…les-in-comment-help
|
Simplified the title extraction as suggested, in 24fef03.
Match titleMatch = Regex.Match(title, @"\A-+ .*?(?:: (?<title>.*?))? -+\z", RegexOptions.NonBacktracking);The outer dash runs and the first Only the generated decoration is removed, so authored punctuation survives intact:
Added round-trip coverage for internal hyphens and authored dash borders through both Both focused files pass locally via Also merged current The |
Assert title and body alignment for titled-first, untitled-first, and three-example interleavings through both GetCommentBlock and proxy comment generation. Exercise titles containing hyphens and dash borders next to untitled examples, where a misaligned index would otherwise go unnoticed. Co-authored-by: Copilot App <[email protected]>
Add fully titled and fully untitled three-example cases so the layout permutations span both uniform ends alongside the interleaved ones. Co-authored-by: Copilot App <[email protected]>
Trim the dash border before the first space and after the last space using index scans over spans, then split at the first ": " delimiter. Behavior is unchanged, so authored hyphens and dash borders are still preserved. Removes the regular expression and its NonBacktracking dependency, which was only needed to bound backtracking on malformed headings. Co-authored-by: Copilot App <[email protected]>
Use Trim('-', ' ') to remove the generated dash border, then split at the
first ": " delimiter. A proxy-generated title therefore cannot begin or end
with a dash, and a heading without the delimiter carries no title.
The comment parser is unchanged, so authored titles still round-trip verbatim
through CommentHelpInfo.GetCommentBlock.
Co-authored-by: Copilot App <[email protected]>
|
This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days. |
Comment-based help examples now support optional titles using
.EXAMPLE <Title>syntax, matching the inline pattern already used by.PARAMETER <Name>. Titles appear inGet-Helpoutput, round-trip through serialization, and are exposed through a new public API so external tools like PlatyPS can consume them. Examples without titles continue to work exactly as before.New: Titled examples in comment-based help
Authors can now place a title on the same line as
.EXAMPLE:Get-Help Get-Report -Examplesrenders the title alongside the auto-generated number:Line-comment syntax (
# .EXAMPLE Title) is also supported.New:
CommentHelpInfo.ExampleTitlespublic propertyExternal tools (PlatyPS, doc generators, formatters) can now read titles via a new property on
CommentHelpInfo:ExampleTitlesruns in parallel with the existingExamplescollection — same length, same index mapping. An empty string at an index means that example has no title. The existingExamplesproperty type is unchanged, so the public API remains binary- and source-compatible.Backward compatibility
This change is fully backward compatible for functions and modules that run on the version that includes this fix:
.EXAMPLEwith no trailing text continues to behave exactly as before.Get-Helpoutput is identical — the only observable difference is that.EXAMPLE <Title>now works instead of breaking.CommentHelpInfo.ExampleTitlesis purely additive;Examplesis unchanged.Behavior on older PowerShell versions: Functions that use
.EXAMPLE <Title>continue to load and run normally on older PowerShell.Get-Helpon older versions silently discards the entire help block when it encounters.EXAMPLE <Title>— no error is thrown, but no authored help content is shown. Authors who adopt the new syntax should document that their help requires the version that includes this fix.Implementation plan progress — from #23966:
ExampleTitlesparallel collection — non-breaking)GetCommentBlock+ProxyCommand.GetHelpComments+ExtractExampleTitle)Technical Details
Semver classification: Minor. The
ExampleTitlespublic API addition and the new observableGet-Helpbehavior both require a minor version bump. Thedefault: return falseparser fix is patch-eligible on its own, but the additive API determines the classification.Files changed:
src/System.Management.Automation/help/HelpCommentsParser.cs— Addedcase "EXAMPLE"to theGroups[3].Success == trueswitch branch inAnalyzeCommentBlock. Capturesmatch.Groups[3].Value.Trim()as the title, then callsGetSection()for the body. The existing untitled branch appendsstring.Emptyto_exampleTitlesto keep indices aligned. XML generation conditionally appends: <title>to the heading string when the title is non-empty.src/System.Management.Automation/engine/parser/ast.cs— AddedReadOnlyCollection<string> ExampleTitles { get; internal set; }onCommentHelpInfo. UpdatedGetCommentBlock()to emit.EXAMPLE <title>when the title is non-empty and.EXAMPLEon its own line otherwise.src/System.Management.Automation/engine/ProxyCommand.cs— UpdatedGetHelpCommentsto emit.EXAMPLE <title>when the MAML title contains a user-supplied portion. AddedExtractExampleTitle— a culture-agnostic helper that recovers the user title by anchoring on surrounding dashes and the:separator rather than the literal wordEXAMPLE, so it works under any UI culture and handles both comment-based decorated headings and compiled-cmdlet MAML titles (which use"Example N: Title"without surrounding dashes). Also fixed a pre-existing bug where functions with exactly one example had their example silently dropped becauseGet-Helpreturns a single example as a barePSObjectrather thanPSObject[]— the fix normalizes both cases before the loop.test/powershell/Language/Scripting/ScriptHelp.ExampleTitles.Tests.ps1— New Pester file (28 tests) covering: titled examples, mixed titled/untitled,GetCommentBlock()round-trip, line-comment syntax, edge-case titles (with colons, dashes, titles ending in a dash),ExampleTitles.Count == Examples.Countparity, and backward-compat regression guard.test/powershell/engine/Api/ProxyCommand.Tests.ps1— Extended with 5 new tests: round-trip fidelity for titled examples, single-example functions (regression for thePSObjectvsPSObject[]fix), colon-in-title, dash-in-title, and titled/untitled mixed.Rendering path: All
Get-Helpoutput modes (-Examples,-Detailed,-Full) render titles through the sameMamlExampleControl→.AddPropertyExpressionBinding("Title")path, which reads themaml:titleXML node verbatim. The WPF help window (HelpParagraphBuilder.AddExamples) also reads the title node directly — no changes were needed in either renderer.Related issues