Skip to content

feat: console prompts wrappers - #26

Merged
loadinglucian merged 3 commits into
mainfrom
feat/console-prompts-wrappers
Oct 4, 2025
Merged

feat: console prompts wrappers#26
loadinglucian merged 3 commits into
mainfrom
feat/console-prompts-wrappers

Conversation

@loadinglucian

@loadinglucian loadinglucian commented Oct 4, 2025

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features
    • Expanded interactive CLI prompts: text, password, confirm, select, multiselect, suggest, search, pause, and spinner.
    • Closure-based prompting when options aren’t provided for flexible non-interactive/interactive flows.
  • Refactor
    • Streamlined output helpers and updated formatting for info, success, warning, error, headings, and command hints.
    • Removed the plain single-line text helper.
  • Documentation
    • Updated command usage examples and non-interactive guidance; removed an outdated section header guidance.
  • Tests
    • Added and updated tests to cover new prompt wrappers, closure flows, and revised output formatting.

@coderabbitai

coderabbitai Bot commented Oct 4, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

This PR refactors console I/O: removes legacy text()/note() helpers, changes several output method signatures/formatting, adds closure-driven getOptionOrPrompt and numerous prompt wrapper methods, updates docs, and adapts tests to use a mock command factory and expanded prompt/output coverage.

Changes

Cohort / File(s) Summary
Rules docs
.cursor/rules/01-architecture.mdc, .cursor/rules/03-commands.mdc
Removes a header-format guidance block; updates commands doc to drop text() examples, add closure-based getOptionOrPrompt, introduce prompt wrapper APIs and update example wording.
Console input trait
app/Traits/ConsoleInputTrait.php
Adds getOptionOrPrompt(string, Closure), a spacing-suppression helper, and prompt wrappers: promptText, promptPassword, promptConfirm, promptPause, promptSelect, promptMultiselect, promptSuggest, promptSearch, promptSpin; adds related imports and docblocks.
Console output trait
app/Traits/ConsoleOutputTrait.php
Removes text() and note alias; updates info, success, warning, error formats (error signature now error(string)); h1() now emits a trailing blank line; showCommandHint() signature simplified and rendering changed to multi-line.
Test fixture and helpers
tests/Fixtures/TestConsoleCommand.php, tests/TestHelpers.php
Adds `-y
Unit tests — BaseCommand and helpers
tests/Unit/Contracts/BaseCommandTest.php, tests/Unit/TestHelpersTest.php
Replaces text(...) calls with writeln(...) in tests; adds test validating mockTestConsoleCommand() returns TestConsoleCommand.
Unit tests — traits
tests/Unit/Traits/ConsoleInputTraitTest.php, tests/Unit/Traits/ConsoleOutputTraitTest.php
Refactors to use mockTestConsoleCommand(); expands input tests for option/closure/boolean/types and multiple prompt wrappers (including spinner); updates output tests to match new symbols, formats, h1/hr and command hint rendering.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Cmd as BaseCommand<br/>(ConsoleInputTrait)
  participant Prompts as Laravel Prompts

  User->>Cmd: execute()
  Cmd->>Cmd: getOptionOrPrompt(name, promptCb)
  alt option provided
    Cmd-->>User: return option value
  else option missing
    Cmd->>Prompts: prompt* wrapper via promptCb()
    Prompts-->>Cmd: user input
    Cmd-->>User: return prompted value
  end
Loading
sequenceDiagram
  autonumber
  actor User
  participant Cmd as BaseCommand<br/>(ConsoleOutputTrait)

  User->>Cmd: execute()
  Note over Cmd: Updated output helpers and formats
  Cmd->>User: info() → "<fg=cyan>ℹ message</>"
  Cmd->>User: success() → "✓ message"
  Cmd->>User: warning() → "⚠ message"
  Cmd->>User: error() → "✗ message"
  Cmd->>User: h1(), hr(), writeln()
  Cmd->>User: showCommandHint(cmd, options) → multi-line hint
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • bigpixelrocket/deployer-php#23 — Modifies the same console I/O traits and getOptionOrPrompt; strong code-level overlap.
  • bigpixelrocket/deployer-php#26 — Adds prompt wrappers and removes text() in the same traits; directly related changes.
  • bigpixelrocket/deployer-php#20 — Adjusts console output/prompt usage and deprecates text(); closely connected to this refactor.

Poem

A rabbit taps the terminal keys,
Swaps old text for prompts with nimble ease.
Closures hop where options fail,
Spinners whirl their cotton tail.
Hints now line up, neat and clear—
Console burrows, crisp to hear.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly and succinctly describes the main feature introduced by the pull request, namely the addition of console prompt wrapper methods, and follows a standard “feat:” prefix to indicate a new feature. It is concise, focused on the primary change, and easily understood by team members scanning the PR history.
Docstring Coverage ✅ Passed Docstring coverage is 89.29% which is sufficient. The required threshold is 80.00%.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bdf9ef5 and 3390a3f.

📒 Files selected for processing (2)
  • tests/Fixtures/TestConsoleCommand.php (3 hunks)
  • tests/Unit/Traits/ConsoleInputTraitTest.php (2 hunks)

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

@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 (2)
tests/TestHelpers.php (1)

256-272: Complete the helper docblock.

The new helper needs the parameter and return annotations called out in our PHP guidelines. Please extend the docblock accordingly. As per coding guidelines

     /**
      * Create a TestConsoleCommand for testing with mocked dependencies.
+     *
+     * @param bool $envFileExists Whether the .env file should be treated as present.
+     * @param string $envContent Contents to expose through the mocked .env file.
+     * @param bool $inventoryFileExists Whether the inventory file should be treated as present.
+     * @param array|string $inventoryData Inventory structure or raw YAML to preload.
+     * @return TestConsoleCommand
      */
tests/Unit/Traits/ConsoleInputTraitTest.php (1)

120-139: Consider the trade-offs of regex-based verification.

This test verifies that each prompt wrapper calls suppressPromptSpacing() by reading and parsing the source file with regex. While this ensures the implementation detail is correct, it's potentially fragile if the method implementation is refactored (e.g., extracting helper methods, adding complexity).

However, given that this appears to be testing a critical requirement (consistent spacing suppression), the approach is acceptable for now.

Alternative approach to consider for the future: Mock the Laravel Prompts functions and verify that output has the expected ANSI escape sequences, which would test behavior rather than implementation.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed2ceed and bdf9ef5.

📒 Files selected for processing (10)
  • .cursor/rules/01-architecture.mdc (0 hunks)
  • .cursor/rules/03-commands.mdc (8 hunks)
  • app/Traits/ConsoleInputTrait.php (2 hunks)
  • app/Traits/ConsoleOutputTrait.php (4 hunks)
  • tests/Fixtures/TestConsoleCommand.php (3 hunks)
  • tests/TestHelpers.php (2 hunks)
  • tests/Unit/Contracts/BaseCommandTest.php (1 hunks)
  • tests/Unit/TestHelpersTest.php (1 hunks)
  • tests/Unit/Traits/ConsoleInputTraitTest.php (2 hunks)
  • tests/Unit/Traits/ConsoleOutputTraitTest.php (2 hunks)
💤 Files with no reviewable changes (1)
  • .cursor/rules/01-architecture.mdc
🧰 Additional context used
📓 Path-based instructions (5)
**/*.php

📄 CodeRabbit inference engine (.cursor/rules/01-architecture.mdc)

**/*.php: Follow PSR-12 coding standard in all PHP files
Declare strict types in all PHP files (declare(strict_types=1);)
Use PHP 8.x features where appropriate (unions, match, attributes, readonly)
Use import statements (use ...) instead of fully qualified class names in code
All methods must declare explicit return types with proper generics (e.g., Collection<int, User>)
Prefer Dependency Injection over manual class resolution/instantiation
Use Symfony component classes (e.g., Filesystem, Process) instead of native PHP functions for easier mocking
All object creation must use $container->build(ClassName::class) except for value objects, DTOs, and pure data structures
Access the container via constructor injection in production code; tests may instantiate Container directly
Services must receive dependencies via constructor injection
Use SymfonyStyle consistently for all user-facing console output
Add DocBlock comments with minimalist descriptions, parameters, and return types for classes and functions
Use comments to separate sections and explain complex logic; avoid obvious or stale comments
Use the exact section header comment format with a single newline between headers/subheaders/paragraphs

**/*.php: Eliminate single-use private methods by inlining them directly
Cache expensive computed values by initializing them in the constructor instead of recomputing
Prefer direct property access over method calls when appropriate to avoid call overhead
Organize code into comment-separated sections; prefer alphabetical ordering when it does not conflict with logical grouping

Files:

  • tests/Unit/Traits/ConsoleOutputTraitTest.php
  • tests/Unit/Traits/ConsoleInputTraitTest.php
  • tests/TestHelpers.php
  • tests/Unit/TestHelpersTest.php
  • app/Traits/ConsoleOutputTrait.php
  • tests/Fixtures/TestConsoleCommand.php
  • app/Traits/ConsoleInputTrait.php
  • tests/Unit/Contracts/BaseCommandTest.php
{tests/**,test/**,**/*@(Test|Spec).php}

📄 CodeRabbit inference engine (.cursor/rules/00-main.mdc)

Do not run or edit tests unless explicitly instructed

Files:

  • tests/Unit/Traits/ConsoleOutputTraitTest.php
  • tests/Unit/Traits/ConsoleInputTraitTest.php
  • tests/TestHelpers.php
  • tests/Unit/TestHelpersTest.php
  • tests/Fixtures/TestConsoleCommand.php
  • tests/Unit/Contracts/BaseCommandTest.php
tests/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/02-tests.mdc)

tests/**/*.php: Use Pest exclusively with it() syntax for tests
In unit tests, instantiate classes manually with explicit mocks; use the container only for integration tests
Keep individual test files under ~1.8x the size of the source they cover
Test core business logic; avoid testing the framework itself
Prefer dataset-driven testing with ->with([...]) for multiple scenarios
Eliminate overlapping tests; avoid two tests covering the same functionality
Consolidate assertions with expect(...)->and(...) when appropriate
Mock external dependencies only; do not mock internal behavior
Avoid performance tests unless performance is the primary concern
Do not sacrifice readability to hit size/ratio targets
Follow the AAA pattern (Arrange, Act, Assert) in tests; use ACT & ASSERT for exception tests when act triggers assertion
Organize tests with describe() blocks, beforeEach() setup, and extract helpers/traits for DRY
Forbid meaningless assertions (e.g., toBeTrue, not->toBeNull, type-only checks, sleep(...)); use time mocking instead of sleep
Prefer meaningful assertions on behavior and results, and proper mocks (e.g., expect domain outputs; mock->shouldReceive(...))
Unit tests: mock all external dependencies; test single units in isolation; execute in milliseconds
Integration tests: perform real file operations/external processes; cover CLI commands and full workflows
Ignore PHPStan issues in tests; avoid excessive PHPDoc added only to appease types

Files:

  • tests/Unit/Traits/ConsoleOutputTraitTest.php
  • tests/Unit/Traits/ConsoleInputTraitTest.php
  • tests/TestHelpers.php
  • tests/Unit/TestHelpersTest.php
  • tests/Fixtures/TestConsoleCommand.php
  • tests/Unit/Contracts/BaseCommandTest.php
app/Traits/ConsoleOutputTrait.php

📄 CodeRabbit inference engine (.cursor/rules/03-commands.mdc)

Add output/formatting methods in ConsoleOutputTrait that format and display text and operate via $this->io

Files:

  • app/Traits/ConsoleOutputTrait.php
app/Traits/ConsoleInputTrait.php

📄 CodeRabbit inference engine (.cursor/rules/03-commands.mdc)

Add input-gathering methods in ConsoleInputTrait that operate via $this->input (prompt helpers, validators, transformers)

Files:

  • app/Traits/ConsoleInputTrait.php
🧠 Learnings (10)
📚 Learning: 2025-10-02T22:05:48.355Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-02T22:05:48.355Z
Learning: Applies to app/Traits/ConsoleOutputTrait.php : Add output/formatting methods in ConsoleOutputTrait that format and display text and operate via `$this->io`

Applied to files:

  • tests/Unit/Traits/ConsoleOutputTraitTest.php
  • app/Traits/ConsoleOutputTrait.php
  • .cursor/rules/03-commands.mdc
📚 Learning: 2025-10-02T22:05:48.355Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-02T22:05:48.355Z
Learning: Applies to app/Traits/ConsoleInputTrait.php : Add input-gathering methods in ConsoleInputTrait that operate via `$this->input` (prompt helpers, validators, transformers)

Applied to files:

  • tests/Unit/Traits/ConsoleInputTraitTest.php
  • app/Traits/ConsoleInputTrait.php
📚 Learning: 2025-10-02T22:05:48.355Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-02T22:05:48.355Z
Learning: Applies to app/**/*Command.php : Use getOptionOrPrompt to detect provided options vs prompt interactively, leveraging Laravel Prompts parameters

Applied to files:

  • tests/Unit/Traits/ConsoleInputTraitTest.php
  • tests/Fixtures/TestConsoleCommand.php
  • app/Traits/ConsoleInputTrait.php
  • .cursor/rules/03-commands.mdc
📚 Learning: 2025-10-02T22:05:48.355Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-02T22:05:48.355Z
Learning: Applies to app/**/*Command.php : Support both interactive prompts and CLI options; use getOptionOrPrompt for each option and showCommandHint to display the full non-interactive command

Applied to files:

  • app/Traits/ConsoleOutputTrait.php
  • .cursor/rules/03-commands.mdc
📚 Learning: 2025-10-02T22:05:48.355Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-02T22:05:48.355Z
Learning: Applies to app/**/*Command.php : Use laravel/prompts for all user interactions (text, password, confirm, select, multiselect, suggest, search, spin) instead of Symfony IO

Applied to files:

  • app/Traits/ConsoleInputTrait.php
  • .cursor/rules/03-commands.mdc
📚 Learning: 2025-10-02T22:05:48.355Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-02T22:05:48.355Z
Learning: Applies to app/Contracts/BaseCommand.php : If missing output functionality, add a new, reusable, minimally-scoped, well-documented method to BaseCommand

Applied to files:

  • tests/Unit/Contracts/BaseCommandTest.php
  • .cursor/rules/03-commands.mdc
📚 Learning: 2025-10-02T22:05:48.355Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-02T22:05:48.355Z
Learning: Applies to app/**/*Command.php : Never use Symfony IO methods directly in commands; use BaseCommand custom methods (writeln, text, info, note, hr, h1, success, error, warning) exclusively

Applied to files:

  • .cursor/rules/03-commands.mdc
📚 Learning: 2025-10-02T22:05:48.355Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-02T22:05:48.355Z
Learning: Applies to app/**/*Command.php : Use status helpers (success, error with optional tip, warning) for all status messages to ensure consistent formatting

Applied to files:

  • .cursor/rules/03-commands.mdc
📚 Learning: 2025-10-02T22:05:48.355Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-02T22:05:48.355Z
Learning: Applies to app/Contracts/BaseCommand.php : Keep BaseCommand focused on shared initialization/configuration/orchestration; do not place individual I/O operations here

Applied to files:

  • .cursor/rules/03-commands.mdc
📚 Learning: 2025-10-01T13:56:16.653Z
Learnt from: CR
PR: bigpixelrocket/deployer-php#0
File: .cursor/rules/01-architecture.mdc:0-0
Timestamp: 2025-10-01T13:56:16.653Z
Learning: Commands are responsible for console styling, error formatting, and user prompts

Applied to files:

  • .cursor/rules/03-commands.mdc
🧬 Code graph analysis (6)
tests/Unit/Traits/ConsoleOutputTraitTest.php (3)
tests/TestHelpers.php (1)
  • mockTestConsoleCommand (260-272)
tests/Fixtures/TestConsoleCommand.php (2)
  • setTestMethod (40-44)
  • execute (55-77)
app/Contracts/BaseCommand.php (1)
  • execute (109-130)
tests/Unit/Traits/ConsoleInputTraitTest.php (2)
tests/TestHelpers.php (1)
  • mockTestConsoleCommand (260-272)
tests/Fixtures/TestConsoleCommand.php (2)
  • setTestMethod (40-44)
  • execute (55-77)
tests/TestHelpers.php (2)
app/Container.php (1)
  • Container (23-227)
tests/Fixtures/TestConsoleCommand.php (1)
  • TestConsoleCommand (22-157)
tests/Unit/TestHelpersTest.php (2)
tests/TestHelpers.php (1)
  • mockTestConsoleCommand (260-272)
tests/Fixtures/TestConsoleCommand.php (1)
  • TestConsoleCommand (22-157)
tests/Fixtures/TestConsoleCommand.php (1)
app/Traits/ConsoleInputTrait.php (3)
  • getOptionOrPrompt (58-76)
  • promptText (106-124)
  • promptSpin (345-353)
tests/Unit/Contracts/BaseCommandTest.php (1)
app/Traits/ConsoleOutputTrait.php (1)
  • writeln (23-29)
🔇 Additional comments (18)
tests/Unit/Traits/ConsoleInputTraitTest.php (5)

13-15: LGTM: Clean test setup with mock helper.

The refactored setup using mockTestConsoleCommand() provides consistent test isolation and reduces boilerplate.


24-60: LGTM: Comprehensive coverage of string option handling.

The tests thoroughly cover the three scenarios for string options:

  • Provided value: returns the value directly
  • Empty string: executes the closure
  • Missing option: executes the closure

This validates the core getOptionOrPrompt flow correctly.


65-87: LGTM: Boolean flag handling is well-tested.

Tests correctly verify that VALUE_NONE flags return true when provided and execute the closure (returning false in this case) when not provided.


92-114: LGTM: Excellent use of parameterized testing.

The dataset-driven approach efficiently covers multiple return types (string, boolean, integer, array) with appropriate assertions for each type.


141-151: LGTM: Clean test for promptSpin wrapper.

Correctly verifies that the callback executes and returns the result.

tests/Fixtures/TestConsoleCommand.php (4)

52-52: LGTM: Boolean flag option added for testing.

The 'yes' flag with VALUE_NONE type is properly configured for testing boolean flag handling in getOptionOrPrompt.


68-71: LGTM: Match cases updated for new test methods.

All new test method mappings are properly registered in the execute method.


84-143: LGTM: Comprehensive test helper methods.

The test methods effectively exercise different aspects of getOptionOrPrompt:

  • testGetOptionOrPrompt: Basic closure-based prompting with promptText
  • testGetOptionOrPromptEmpty: Tracks closure execution and handles empty/missing options
  • testGetOptionOrPromptBoolean: Validates boolean flag behavior
  • testGetOptionOrPromptTypes: Tests return type flexibility with proper type-based output formatting

Each method correctly outputs results in a format that tests can verify.


148-156: LGTM: Clean promptSpin wrapper test.

Properly exercises the spin functionality with a callback and message parameter.

tests/Unit/Traits/ConsoleOutputTraitTest.php (5)

13-15: LGTM: Consistent test setup.

Uses the same mockTestConsoleCommand() pattern as other trait tests for consistency.


21-44: LGTM: Clean writeln tests.

Tests correctly verify both single-line and multi-line output formatting.


50-100: LGTM: Comprehensive message helper verification.

Tests thoroughly validate that each message helper (info, success, warning, error) displays the correct symbol and message text with appropriate formatting.


106-130: LGTM: Heading and separator tests are clear.

Properly verifies the heading icon and separator box-drawing characters.


136-188: LGTM: Thorough command hint testing.

Tests cover:

  • Basic command hint generation with options
  • Option formatting with values
  • Filtering of null/empty values

This ensures the showCommandHint method behaves correctly for non-interactive execution guidance.

app/Traits/ConsoleInputTrait.php (4)

7-17: LGTM: Clean imports for Laravel Prompts integration.

All necessary Laravel Prompts functions are properly imported for the wrapper methods.

Based on learnings


58-76: LGTM: Well-designed option detection and prompting flow.

The getOptionOrPrompt method correctly handles three scenarios:

  1. Boolean flags (VALUE_NONE): Returns true when flag is provided
  2. Non-empty strings: Returns the provided option value
  3. Empty/null values: Falls back to the closure-based prompt

The closure-based approach provides excellent flexibility, allowing callers to use any prompt type (text, select, confirm, etc.) as needed.

Based on learnings


87-92: LGTM: Necessary workaround for Laravel Prompts spacing.

The ANSI escape sequence \033[1A\033[2K (move cursor up one line and clear it) compensates for unwanted newlines that Laravel Prompts adds before each prompt. This is a reasonable workaround for improving the user experience.

Note: This approach assumes terminal ANSI support, which is standard for modern terminals but may not work in all environments. The current implementation is acceptable given the target use case for CLI deployment tools.


106-353: LGTM: Comprehensive and well-documented prompt wrappers.

All prompt wrapper methods follow a consistent pattern:

  1. Call suppressPromptSpacing() for consistent spacing
  2. Delegate to the corresponding Laravel Prompts function with named parameters
  3. Maintain explicit type hints and return types
  4. Include comprehensive docblocks with parameter descriptions

The wrappers cover all Laravel Prompts functions:

  • Text input: promptText, promptPassword, promptSuggest
  • Selection: promptSelect, promptMultiselect, promptSearch
  • Confirmation: promptConfirm, promptPause
  • Loading: promptSpin

The use of generics in promptSpin (template T) correctly preserves the callback return type.

Based on learnings

Comment on lines +132 to +137
$this->writeln(" <fg=gray>vendor/bin/deployer {$commandName} \\ </>");

foreach ($parts as $index => $part) {
$last = $index === count($parts) - 1;
$this->writeln(" <fg=gray> {$part}</>".($last ? '' : '<fg=gray> \\ </>'));
}

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.

⚠️ Potential issue | 🟠 Major

Avoid dangling backslash when no options are rendered.

When $options normalise to an empty set (all values null/empty/false), the command hint still prints vendor/bin/deployer … \ on the headline. That backslash implies a continuation line that never appears, so the rendered command is invalid. Please gate the continuation marker on !empty($parts) before adding it.

-        $this->writeln("  <fg=gray>vendor/bin/deployer {$commandName} \\ </>");
-
-        foreach ($parts as $index => $part) {
-            $last = $index === count($parts) - 1;
+        $hasOptions = $parts !== [];
+        $this->writeln(
+            $hasOptions
+                ? "  <fg=gray>vendor/bin/deployer {$commandName} \\ </>"
+                : "  <fg=gray>vendor/bin/deployer {$commandName}</>"
+        );
+
+        $lastIndex = count($parts) - 1;
+        foreach ($parts as $index => $part) {
+            $last = $index === $lastIndex;
             $this->writeln("  <fg=gray>  {$part}</>".($last ? '' : '<fg=gray> \\ </>'));
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$this->writeln(" <fg=gray>vendor/bin/deployer {$commandName} \\ </>");
foreach ($parts as $index => $part) {
$last = $index === count($parts) - 1;
$this->writeln(" <fg=gray> {$part}</>".($last ? '' : '<fg=gray> \\ </>'));
}
$hasOptions = $parts !== [];
$this->writeln(
$hasOptions
? " <fg=gray>vendor/bin/deployer {$commandName} \\ </>"
: " <fg=gray>vendor/bin/deployer {$commandName}</>"
);
$lastIndex = count($parts) - 1;
foreach ($parts as $index => $part) {
$last = $index === $lastIndex;
$this->writeln(" <fg=gray> {$part}</>".($last ? '' : '<fg=gray> \\ </>'));
}
🤖 Prompt for AI Agents
In app/Traits/ConsoleOutputTrait.php around lines 132 to 137, the headline
always prints a trailing continuation backslash even when $parts is empty; guard
the headline's " \ " suffix with a check like if (!empty($parts)) so the
backslash is only added when there are continuation lines, and ensure the
per-part loop only emits the " \ " separator for non-final parts (current logic
ok) so no dangling backslash is rendered when $options normalise to an empty
set.

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