Supporting Titles in Comment-Based Help Examples for script-based functions
PowerShell's comment-based help system for script-based functions supports the .EXAMPLE directive to document usage examples. When Get-Help -Examples is invoked, each example is displayed with an auto-generated heading like EXAMPLE 1, EXAMPLE 2, etc.
Compiled cmdlets that use MAML-based help already support custom titles on examples (e.g., EXAMPLE 1: Retrieving an item). However, comment-based help — the primary documentation method for script-based functions and modules — has no equivalent mechanism.
This gap also affects documentation tooling. PlatyPS cannot generate titled examples from comment-based help because the parser does not expose title data. This was reported as PlatyPS issue #627, but the root cause is in PowerShell's parser itself.
Related: #23814 — Get-Help shows incorrect spacing and unwanted prefixes for first line of .EXAMPLE text.
Request
Support an optional title on the .EXAMPLE directive in comment-based help, following the same inline pattern used by .PARAMETER <name>:
.EXAMPLE <Title>Current behavior
Placing text on the same line as .EXAMPLE causes the parser to fall through to an unhandled default: case in the directive switch, which returns false and breaks help parsing entirely. The example — and potentially the entire help block — is silently discarded.
function Show-Example {
<#
.EXAMPLE Retrieving an item from a directory
Get-Item -Path C:\Temp
Retrieves the item at C:\Temp
#>
param()
}Get-Help Show-Example -Examples produces no output because the parser rejects the help block.
Expected behavior
The parser should extract the title and display it alongside the auto-generated number:
-------------------------- EXAMPLE 1: Retrieving an item from a directory --------------------------
Get-Item -Path C:\Temp
Retrieves the item at C:\TempExamples without titles should continue to display exactly as they do today — no behavioral change for existing help content.
Acceptance criteria
.EXAMPLE <Title>syntax is supported, with the title extracted and stored separately from the example bodyGet-Help -Examplesdisplays titles asEXAMPLE N: <Title>when a title is present- Examples without titles display identically to current behavior (
EXAMPLE Nwith no colon or trailing text) - Existing help content is not affected — full backward compatibility (no breaking API changes)
- The
CommentHelpInfopublic API exposes example titles so external tools (e.g., PlatyPS) can consume them - Round-tripping via
GetCommentBlock()preserves titles - Round-tripping via
ProxyCommand.GetHelpComments()preserves titles
Technical decisions
Parser handling — dual switch blocks. The HelpCommentsParser.AnalyzeCommentBlock method uses a directive regex ^\s*\.(\w+)(\s+(\S.*))?\s*$ that routes to two separate switch blocks: one when Groups[3].Success is true (text follows the keyword), and one when it is false. Currently EXAMPLE is only handled in the second block. To support .EXAMPLE <Title>, add a case "EXAMPLE" to the first block that captures match.Groups[3].Value.Trim() as the title, then falls through to collecting the body via GetSection(). A new List<string> _exampleTitles field stores titles in order, with an empty string inserted when no title is provided.
New public property on CommentHelpInfo (non-breaking). Add ReadOnlyCollection<string> ExampleTitles { get; internal set; } to the CommentHelpInfo class as a parallel collection alongside the existing Examples property. Each index in ExampleTitles corresponds to the same index in Examples. An empty string entry means no title for that example. The existing Examples property type (ReadOnlyCollection<string>) is preserved unchanged so the public API remains binary- and source-compatible.
Title format in XML generation. In the XML-building section of HelpCommentsParser (around line 363), when a title is present the example heading is built as EXAMPLE N: <Title>; when no title is present, the existing EXAMPLE N format is emitted unchanged. This matches the format used by MAML-based help for compiled cmdlets.
GetCommentBlock() round-tripping. Update the GetCommentBlock() method in CommentHelpInfo to emit .EXAMPLE <title> when ExampleTitles[index] is non-empty, and .EXAMPLE on its own line when the title is empty — preserving round-trip fidelity in both directions.
ProxyCommand.GetHelpComments round-tripping. Update ProxyCommand.GetHelpComments to emit .EXAMPLE <title> when the underlying MAML title contains a user-provided portion. A new private helper ExtractExampleTitle recovers the original user title from the decorated MAML title string. The extraction is culture-agnostic — it anchors on the dash-padding and the : separator rather than the literal English word EXAMPLE, so it works correctly under any UI culture.
GetExampleSections — no change needed. The static method that splits example content into prompt, code, and remarks operates on the body text, which is captured separately from the title. No modification required.
HelpParagraphBuilder — no change needed. The WPF help window already reads the title property from the XML example node. Since the title will be embedded in the XML by the parser, the UI will display it automatically.
Backward compatibility. No breaking changes. The syntax .EXAMPLE without trailing text continues to work identically. Only the new .EXAMPLE <Title> form adds behavior. The ExampleTitles property is purely additive to the public API; the existing Examples property type is unchanged.
Test strategy. Extend existing tests in ScriptHelp.Tests.ps1 and add coverage for ProxyCommand round-tripping in ProxyCommand.Tests.ps1. Cover: titled examples, untitled examples, mixed titled/untitled, line-comment syntax, parity between Examples and ExampleTitles, edge-case titles (containing colons, dashes, ending with a dash), and round-tripping via both GetCommentBlock() and ProxyCommand.GetHelpComments().
Implementation plan
Parser changes
- Add
case "EXAMPLE"to the firstswitchblock inAnalyzeCommentBlock(theGroups[3].Successbranch) — extract title frommatch.Groups[3].Value.Trim(), append it to_exampleTitles, and callGetSection()to store the body in_examples - In the second
switchblock (the no-arguments branch), append an empty string to_exampleTitlesfor the existingcase "EXAMPLE"to keep title indices aligned with body indices - Add a
List<string> _exampleTitlesfield toHelpCommentsParserthat runs in parallel with_examples - Assign
_sections.ExampleTitlesasReadOnlyCollection<string>after parsing completes
Data model changes
- Add a new
ReadOnlyCollection<string> ExampleTitles { get; internal set; }property toCommentHelpInfo(parallel collection — non-breaking;Examplesproperty type is unchanged)
XML generation changes
- Update the title format string in the XML-building section of
HelpCommentsParserto conditionally append: <title>when the example title is non-empty
Round-trip serialization
- Update
GetCommentBlock()inCommentHelpInfoto emit.EXAMPLE <title>when the title is non-empty, and.EXAMPLEon its own line when untitled - Update
ProxyCommand.GetHelpCommentsto emit.EXAMPLE <title>when the MAML title contains a user-provided title - Add culture-agnostic
ExtractExampleTitlehelper toProxyCommandthat recovers the user title from the decorated MAML title string (anchored on dashes/:separator, not the literal wordEXAMPLE)
Tests
- Add test for function with titled examples — verify
$help.examples.example.titlecontains the custom title - Add test for function with multiple examples, some titled and some untitled — verify titles appear only where specified
- Add test confirming untitled examples produce identical output to current behavior (regression guard)
- Add test for
GetCommentBlock()round-tripping — verify titles survive serialization and deserialization - Add regression test verifying
.EXAMPLE <Title>no longer breaks help parsing (the previousdefault: return falsebug) - Add test for
ProxyCommand.GetHelpCommentsround-tripping titled examples - Add edge case tests for titles containing colons and dashes (including titles ending with a dash)
- Add test for line-comment syntax (
# .EXAMPLE Title) titled examples - Add test asserting
Examples.CountandExampleTitles.Countare always equal
Documentation (MicrosoftDocs/PowerShell-Docs)
- Update the
.EXAMPLEkeyword section inabout_Comment_Based_Helpto document.EXAMPLE <Title>syntax — mirror how.PARAMETER <Name>is already described on the same page- File:
reference/7.x/Microsoft.PowerShell.Core/About/about_Comment_Based_Help.md
- File:
- Update Writing Comment-Based Help Topics developer/SDK authoring guide to cover
.EXAMPLE <Title>- File:
reference/docs-conceptual/developer/help/writing-comment-based-help-topics.md
- File:
- Add feature entry to What's New in PowerShell 7.x release notes for the shipping version
- File:
reference/docs-conceptual/whats-new/What-s-New-in-PowerShell-7x.md
- File:
Note: Only the
reference/7.xfolder matching the shipping PowerShell version needs updating. Older version folders (5.1, 7.2, 7.4, 7.5) should not be changed.
PlatyPS compatibility
- Update PlatyPS to consume titled examples from the new
CommentHelpInfo.ExampleTitlesproperty (PlatyPS issue #627)
VSCode PowerShell extension
- Update the vscode-powershell extension's TextMate grammar so that
.EXAMPLE <Title>is recognized as a directive keyword, not body text — the.EXAMPLEkeyword should retain its styling regardless of trailing title text on the same line
Markdown / syntax highlighting grammars
- Update the shared TextMate grammar (used by both VSCode and GitHub Flavored Markdown) so that
.EXAMPLE <Title>is treated the same way.PARAMETER <Name>is — the directive keyword should be recognized regardless of trailing text on the same line
Source: PowerShell/PowerShell