Skip to content

Add experimental interactive readline#914

Merged
bobthecow merged 18 commits intomainfrom
feature/interactive-readline
Mar 5, 2026
Merged

Add experimental interactive readline#914
bobthecow merged 18 commits intomainfrom
feature/interactive-readline

Conversation

@bobthecow
Copy link
Owner

@bobthecow bobthecow commented Feb 25, 2026

Experimental interactive readline

PsySH has always been limited by what ext-readline and ext-libedit expose: flat completion lists, single-line input, no context awareness. This is a pure-PHP readline replacement that gives PsySH full control over the interactive experience.

This is opt-in and experimental. Default behavior is completely unchanged.

Completions that actually understand your code

The old tab completion system matches strings against lists of known symbol names. The new completion engine is fundamentally different; it's syntax-aware, type-aware, and runtime-value-aware:

  • Syntax-aware: Parses input with php-parser to understand context. It knows $foo-> needs instance methods, Foo:: needs static members, and a bare arra needs global functions or classes.
  • Type-aware: Resolves types through assignments, return types, and doc annotations so it can complete a chain like $repo->find(1)-> with the right type.
  • Runtime-value-aware: Inspects the actual live objects in scope. If $user is a User instance, $user-> completes with User's real methods and properties, not just every method name PHP knows about.

Completions show in a navigable multi-column menu (arrow keys to browse, type to filter). Fuzzy matching means asum finds array_sum and stl finds strtolower.

Multi-line editing that just works

Press Enter with unclosed brackets or an incomplete statement and the input continues on the next line, with proper indentation. Closing brackets auto-dedent. Shift+Enter always inserts a newline. No more fighting the shell to write a multi-line closure.

Feels like a real editor

  • Bracket and quote auto-pairing (( inserts () with cursor inside, typing ) skips over the existing one, backspace between () deletes both)
  • Reverse history search (Ctrl-R) with incremental matching
  • Bracketed paste; pastes multi-line code verbatim

How to try it

// In your PsySH config file
'useExperimentalReadline' => true,
# Or from the command line
psysh --experimental-readline

Requires a TTY (interactive terminal). Falls back to the standard readline stack in non-interactive contexts.

Architecture notes

  • Readline\Interactive\ Input engine: action-based key dispatch, text buffer, key bindings, terminal management, frame-based rendering
  • Completion\ New completion system: context analysis via php-parser, runtime type resolution, 14+ completion sources, fuzzy matching
  • Custom tab completion matchers are bridged in via MatcherAdapterSource

Related issues

This addresses a bunch of long-standing readline and tab completion issues:

… and lays the groundwork for even more:

What's NOT changing

  • Default behavior is unchanged; you have to opt in
  • Existing readline implementations (GnuReadline, Libedit, Userland) are untouched
  • Custom tab completion matchers still work

@codecov
Copy link

codecov bot commented Feb 25, 2026

Codecov Report

❌ Patch coverage is 77.64604% with 1037 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.42%. Comparing base (281ade2) to head (4c0d732).
⚠️ Report is 19 commits behind head on main.

Files with missing lines Patch % Lines
src/Readline/Interactive/Actions/TabAction.php 51.98% 121 Missing ⚠️
src/Util/TerminalColor.php 23.33% 92 Missing ⚠️
src/Readline/Interactive/Terminal.php 5.37% 88 Missing ⚠️
src/Completion/TypeResolver.php 80.11% 72 Missing ⚠️
src/Readline/Interactive/Readline.php 78.88% 57 Missing ⚠️
src/Readline/InteractiveReadline.php 63.44% 53 Missing ⚠️
src/Readline/Interactive/Helper/DebugLog.php 14.54% 47 Missing ⚠️
src/Shell.php 65.15% 46 Missing ⚠️
src/Readline/Interactive/Input/StdinReader.php 62.50% 45 Missing ⚠️
...ine/Interactive/Actions/HistoryExpansionAction.php 73.61% 38 Missing ⚠️
... and 65 more
Additional details and impacted files
@@             Coverage Diff              @@
##               main     #914      +/-   ##
============================================
+ Coverage     70.78%   73.42%   +2.63%     
- Complexity     3769     5609    +1840     
============================================
  Files           163      264     +101     
  Lines          8870    13479    +4609     
============================================
+ Hits           6279     9897    +3618     
- Misses         2591     3582     +991     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

bobthecow added 18 commits March 5, 2026 09:11
A pure-PHP readline replacement purpose-built for PsySH. Instead of
delegating to ext-readline or ext-libedit, this gives PsySH full control
over input, editing, completion, and rendering.

The completion system is syntax, type, and runtime-value aware; it
parses your input, resolves types from live objects in scope, and
completes based on what your code actually is, not just string matching
on symbol names.

Highlights:

 - Completions that understand your code: $user->getA resolves $user's
   type at runtime and completes with its actual methods and properties.
   Fuzzy matching and interactive selection menu.
 - Multi-line editing that just works: auto-continues on unclosed brackets
   or incomplete statements, with syntax-aware indent/dedent
 - Smart bracket and quote auto-pairing
 - Reverse history search (Ctrl-R)

Opt in via config or CLI flag:

    'useExperimentalReadline' => true

    psysh --experimental-readline
@bobthecow bobthecow force-pushed the feature/interactive-readline branch from 27c7619 to 4c0d732 Compare March 5, 2026 14:34
@bobthecow bobthecow merged commit 7d6ade6 into main Mar 5, 2026
68 checks passed
@bobthecow bobthecow deleted the feature/interactive-readline branch March 5, 2026 14:47
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