#23966·PowerShell

Supporting Titles in Comment-Based Help Examples for script-based functions

Author: MariusStorhaugCreated Jun 19, 2024Updated Sep 16, 2026
LabelsIssue-EnhancementWG-Interactive-HelpSystemWG-Reviewed

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: #23814Get-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.

powershell
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:\Temp

Examples 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 body
  • Get-Help -Examples displays titles as EXAMPLE N: <Title> when a title is present
  • Examples without titles display identically to current behavior (EXAMPLE N with no colon or trailing text)
  • Existing help content is not affected — full backward compatibility (no breaking API changes)
  • The CommentHelpInfo public 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 first switch block in AnalyzeCommentBlock (the Groups[3].Success branch) — extract title from match.Groups[3].Value.Trim(), append it to _exampleTitles, and call GetSection() to store the body in _examples
  • In the second switch block (the no-arguments branch), append an empty string to _exampleTitles for the existing case "EXAMPLE" to keep title indices aligned with body indices
  • Add a List<string> _exampleTitles field to HelpCommentsParser that runs in parallel with _examples
  • Assign _sections.ExampleTitles as ReadOnlyCollection<string> after parsing completes

Data model changes

  • Add a new ReadOnlyCollection<string> ExampleTitles { get; internal set; } property to CommentHelpInfo (parallel collection — non-breaking; Examples property type is unchanged)

XML generation changes

  • Update the title format string in the XML-building section of HelpCommentsParser to conditionally append : <title> when the example title is non-empty

Round-trip serialization

  • Update GetCommentBlock() in CommentHelpInfo to emit .EXAMPLE <title> when the title is non-empty, and .EXAMPLE on its own line when untitled
  • Update ProxyCommand.GetHelpComments to emit .EXAMPLE <title> when the MAML title contains a user-provided title
  • Add culture-agnostic ExtractExampleTitle helper to ProxyCommand that recovers the user title from the decorated MAML title string (anchored on dashes/: separator, not the literal word EXAMPLE)

Tests

  • Add test for function with titled examples — verify $help.examples.example.title contains 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 previous default: return false bug)
  • Add test for ProxyCommand.GetHelpComments round-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.Count and ExampleTitles.Count are always equal

Documentation (MicrosoftDocs/PowerShell-Docs)

  • Update the .EXAMPLE keyword section in about_Comment_Based_Help to 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
  • 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
  • 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

Note: Only the reference/7.x folder matching the shipping PowerShell version needs updating. Older version folders (5.1, 7.2, 7.4, 7.5) should not be changed.

PlatyPS compatibility

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 .EXAMPLE keyword 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