Skip to content

feat(Modern): add help formatting system (Week 5)#7

Open
ralflang wants to merge 1 commit intofeat/modern-api-implementationfrom
feat/modern-api-week5
Open

feat(Modern): add help formatting system (Week 5)#7
ralflang wants to merge 1 commit intofeat/modern-api-implementationfrom
feat/modern-api-week5

Conversation

@ralflang
Copy link
Member

@ralflang ralflang commented Mar 4, 2026

Summary

Add professional help formatting system to Modern API. This completes the Modern API implementation with full help text generation capabilities.

Changes

HelpFormatter Implementation

  • Immutable help formatter with builder pattern
  • Terminal-width-aware text wrapping
  • Auto-detection of terminal width (fallback to 80)
  • Configurable indentation and alignment
  • Support for usage, description, epilog, options, and groups

Parser Integration

  • formatHelp() method on ImmutableParser
  • Optional custom formatter support
  • Uses builder-provided formatter if available
  • Falls back to default formatter

Features

Formatting Capabilities:

  • Usage line with %prog substitution
  • Description and epilog text wrapping
  • Option alignment with configurable column position
  • Automatic default value display
  • Automatic choices display
  • Metavar support for argument placeholders
  • Option groups with headers and descriptions

Customization:

  • withWidth(int): Set terminal width
  • withIndent(int): Set indentation increment
  • withMaxHelpPosition(int): Set help column position
  • withShortFirst(bool): Control option ordering

Example Output:

Usage: converter [options] <input> <output>

Convert files between formats

Options:
  -v, --verbose         Increase verbosity
  -p, --port=PORT       Server port (default: 8080)
  -f, --format=FORMAT   Output format (choices: 'json', 'xml', 'csv')
                        (default: json)

Debugging:
  -d, --debug           Enable debug mode
  -t, --trace           Enable trace output

For more information, visit https://example.com

Test Coverage

✓ 28 new tests (234 total Modern API tests)
✓ 73 new assertions (403 total assertions)
✓ 100% passing

Test Coverage Includes:

  • Formatter creation and immutability
  • All formatting scenarios (usage, description, epilog, options, groups)
  • Default value and choice display
  • Custom width and indentation
  • Short/long option ordering
  • Parser integration
  • Complete help generation

Design

Immutable Throughout:

  • Readonly HelpFormatter class
  • Builder pattern for configuration
  • No side effects during formatting
  • Thread-safe and cacheable

Clean Separation:

  • Formatter is independent of parser
  • Parser delegates to formatter
  • Can swap formatters without changing parser

Performance:

  • Fast formatting (no reflection)
  • Efficient text wrapping algorithm
  • Minimal memory allocations

Example Usage

use Horde\Argv\Modern\Builder\{ParserBuilder, OptionBuilder};
use Horde\Argv\Modern\Help\HelpFormatter;
use Horde\Argv\Modern\Enum\OptionType;

$verbose = OptionBuilder::create()
    ->short('-v')->long('--verbose')
    ->counter()->help('Increase verbosity')
    ->build();

$port = OptionBuilder::create()
    ->short('-p')->long('--port')
    ->type(OptionType::Int)->default(8080)
    ->help('Server port')
    ->build();

$parser = ParserBuilder::create()
    ->withUsage('%prog [options] <file>')
    ->withDescription('Process files')
    ->addOption($verbose)
    ->addOption($port)
    ->build();

// Default formatter
echo $parser->formatHelp();

// Custom formatter
$formatter = HelpFormatter::create()->withWidth(100);
echo $parser->formatHelp($formatter);

Status

Modern API is now feature-complete:

  • ✅ Enums (Week 1)
  • ✅ Config objects (Week 1)
  • ✅ Result objects (Week 2)
  • ✅ Exceptions (Week 2)
  • ✅ Validators (Week 2)
  • ✅ Builders (Week 3)
  • ✅ Parser (Week 4)
  • ✅ Help formatting (Week 5)

The Modern API is production-ready with full parsing, validation, and help generation!

Checklist

  • All tests passing (234/234)
  • PHPDoc complete
  • Type declarations on all methods
  • Conventional commit message
  • No breaking changes
  • Immutability verified
  • Integration tested

Implement immutable help formatter for Modern API following Principle #5 and #7.
Provides professional, terminal-width-aware help text formatting with full
support for options, groups, and descriptions.

Core Components:
- HelpFormatter: Immutable help text generator
- Integration with ImmutableParser via formatHelp()
- Builder pattern for customization
- Terminal width auto-detection

Features:
- Usage line formatting with %prog substitution
- Description and epilog support
- Option formatting with alignment and wrapping
- Option groups with descriptions
- Default value display (e.g., "(default: 8080)")
- Choice list display (e.g., "(choices: 'json', 'xml', 'csv')")
- Metavar support for argument placeholders
- Short/long option ordering control
- Text wrapping for terminal width
- Configurable indentation

Formatter Configuration:
- width: Terminal width (0 = auto-detect, default: 80)
- indent: Indentation increment (default: 2)
- maxHelpPosition: Column before wrapping help text (default: 24)
- shortFirst: Show short option first in listings (default: true)

Formatting Rules:
- Options aligned at configurable column position
- Help text wraps to terminal width
- Default values and choices automatically appended
- Groups separated with headers
- Consistent spacing and indentation

Parser Integration:
- formatHelp(): Generate help text for parser
- Accepts optional custom formatter
- Uses builder-provided formatter if available
- Falls back to default formatter

Example Usage:
  $formatter = HelpFormatter::create()
      ->withWidth(100)
      ->withIndent(4)
      ->build();

  $parser = ParserBuilder::create()
      ->withUsage('%prog [options] <file>')
      ->withDescription('Process files')
      ->addOption($verboseOption)
      ->build();

  echo $parser->formatHelp($formatter);

Output Example:
  Usage: myapp [options] <file>

  Process files

  Options:
    -v, --verbose         Increase verbosity
    -p, --port=PORT       Server port (default: 8080)
    -f, --format=FORMAT   Output format (choices: 'json', 'xml', 'csv')
                          (default: json)

Test Coverage:
- 28 tests added (234 total Modern API tests)
- 73 assertions added (403 total assertions)
- All tests passing (100%)
- Tests cover all formatting scenarios
- Integration tests with ImmutableParser

Formatter Characteristics:
- Readonly class (Principle #7)
- Immutable builder pattern (Principle #5)
- No side effects, pure output generation
- Thread-safe and cacheable
- Fast formatting (no reflection)

Text Wrapping Algorithm:
- Word-based wrapping (no mid-word breaks)
- Respects indentation for wrapped lines
- Handles long option strings gracefully
- Falls back to next-line help for long options

Terminal Width Detection:
- Auto-detects via tput cols if available
- Falls back to 80 columns default
- Can be explicitly set via withWidth()
- Zero width disables wrapping

Principles Demonstrated:
- Principle #5: Modern API is Immutable - formatter fully immutable
- Principle #7: Immutable Throughout - readonly class, builder for config
- Principle #6: Explicit Access - clear method calls, no magic
- Clean separation between formatting logic and parser logic

Next Steps: Modern API is now feature-complete with parsing and help formatting
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.

1 participant