PHPackages                             sugarcraft/sugar-readline - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. sugarcraft/sugar-readline

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

sugarcraft/sugar-readline
=========================

PHP port of erikgeiser/promptkit — interactive line-editing prompt library. Supports text input with validation/completion/hidden-password mode, selection prompts with filtering/pagination/cursor navigation, confirmation prompts, and textarea multi-line input.

00PHP

Since Jul 1Pushed 1mo agoCompare

[ Source](https://github.com/sugarcraft/sugar-readline)[ Packagist](https://packagist.org/packages/sugarcraft/sugar-readline)[ RSS](/packages/sugarcraft-sugar-readline/feed)WikiDiscussions master Synced 3w ago

READMEChangelogDependenciesVersions (1)Used By (0)

[![sugar-readline](.assets/icon.png)](.assets/icon.png)

[![CI](https://github.com/detain/sugarcraft/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/detain/sugarcraft/actions/workflows/ci.yml)[![codecov](https://camo.githubusercontent.com/d35f56725e701406e581d845c9ed185ca0d261dcc4493adbc65ff2c81d662b1e/68747470733a2f2f636f6465636f762e696f2f67682f64657461696e2f737567617263726166742f6272616e63682f6d61737465722f67726170682f62616467652e7376673f666c61673d73756761722d726561646c696e65)](https://app.codecov.io/gh/detain/sugarcraft?flags%5B0%5D=sugar-readline)[![Packagist Version](https://camo.githubusercontent.com/e65ebecfcaea10ffc5bfaf577b392d8be6ac74394778a94003dde613dbc9ea95/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7375676172636f72652f73756761722d726561646c696e653f6c6162656c3d7061636b6167697374)](https://packagist.org/packages/sugarcore/sugar-readline)[![License](https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667)](LICENSE)[![PHP](https://camo.githubusercontent.com/e78ffc83837c0d12647811a7fd1910c3cbeae04988de94bb4fd5b67e0874696a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d254532253839254135382e312d3838393262662e737667)](https://www.php.net/)

SugarReadline
=============

[](#sugarreadline)

PHP port of [erikgeiser/promptkit](https://github.com/erikgeiser/promptkit) — interactive line-editing prompt library for terminal UIs.

Features
--------

[](#features)

- **TextPrompt** — single-line input with validation, auto-completion, hidden/password mode, char limit, default value
- **SelectionPrompt** — filtered list with cursor navigation and pagination
- **MultiSelectPrompt** — filtered multi-choice with min/max enforcement and FIFO rollover at the cap
- **ConfirmationPrompt** — yes/no with customizable labels, decoupled select-vs-submit
- **TextareaPrompt** — multi-line text input with line/column cursor and optional max-line cap
- **Pure renderer** — every method returns a new immutable instance; `view()` returns ANSI strings, `value()` returns the data
- **Vim keybindings** — vi-mode (Insert/Normal/Visual/VisualLine) handled by the shared `candy-forms` `VimKeyHandler` — the same handler backing `sugar-prompt` and `sugar-bits`; new bindings in `VimAction` enum benefit all three libs

Install
-------

[](#install)

```
composer require sugarcraft/sugar-readline
```

Quick Start
-----------

[](#quick-start)

`Readline` reads real TTY keypresses via `candy-input`'s `InputDriver`. In production, `StreamInputDriver::fromStdin()` is the default — no configuration needed. For testing, inject a driver over a fixture stream.

### Text Prompt

[](#text-prompt)

```
use SugarCraft\Readline\Readline;
use SugarCraft\Readline\TextPrompt;

$readline = Readline::fromStdin();

$prompt = TextPrompt::new('Enter your name: ')
    ->withDefault('Anonymous')
    ->withCompletions(['Alice', 'Bob', 'Carol']);

$result = $readline->run($prompt);
echo $result->value();  // 'Alice' (after typing + Tab + Enter)
```

### Selection Prompt

[](#selection-prompt)

```
use SugarCraft\Readline\Readline;
use SugarCraft\Readline\SelectionPrompt;

$result = Readline::fromStdin()->run(
    SelectionPrompt::new('Choose a fruit:', ['Apple', 'Banana', 'Cherry', 'Date'])
        ->withFilter('an')   // Banana matches
);
echo $result->selectedValue();  // 'Banana'
```

### Multi-Select Prompt

[](#multi-select-prompt)

```
use SugarCraft\Readline\Readline;
use SugarCraft\Readline\MultiSelectPrompt;

$result = Readline::fromStdin()->run(
    MultiSelectPrompt::new('Pick:', ['A', 'B', 'C'])
        ->withMinSelections(1)
);
print_r($result->selectedValues());  // ['A', 'B'] after navigation + Enter
```

### Confirmation Prompt

[](#confirmation-prompt)

```
use SugarCraft\Readline\Readline;
use SugarCraft\Readline\ConfirmationPrompt;

$result = Readline::fromStdin()->run(
    ConfirmationPrompt::new('Delete file?')
);
echo $result->result() ? 'yes' : 'no';  // 'yes' or 'no'
```

### Custom Key Handlers

[](#custom-key-handlers)

```
use SugarCraft\Readline\Readline;
use SugarCraft\Readline\TextPrompt;

$result = Readline::fromStdin()
    ->onKey('ctrl_c', fn($event) => print("aborted\n"))
    ->onKey('ctrl_u', fn($event) => print("cleared\n"))
    ->run(TextPrompt::new('> '));

echo $result->value();
```

Input Driver
------------

[](#input-driver)

`Readline` accepts an optional `SugarCraft\Input\InputDriver` to control where input comes from. Production code uses the default `StreamInputDriver::fromStdin()` which needs no configuration. Tests inject a driver over a fixture stream for deterministic byte-fed test cases.

```
// Production: reads real TTY keypresses (default)
$readline = new Readline();                        // uses StreamInputDriver::fromStdin()
$readline = Readline::fromStdin();                  // equivalent

// Testing: inject a fake stream
$fake = fopen('php://memory', 'r+');
fwrite($fake, "hello\x0d");                          // \x0d = Enter
rewind($fake);
$driver = new StreamInputDriver($fake);
$readline = new Readline($driver);
$result = $readline->run(TextPrompt::new('> '));
// $result->value() === 'hello'
```

Key Bindings
------------

[](#key-bindings)

The `SugarCraft\Readline\Key` class exposes symbolic constants for every supported key.

- `Key::Left` / `Key::Right` — move cursor (text input)
- `Key::Up` / `Key::Down` — navigate selection list / change line in textarea
- `Key::PageUp` / `Key::PageDown` — page through long lists
- `Key::Home` / `Key::End` — jump within the current line / list
- `Key::Enter` — submit text or select current choice
- `Key::Space` — toggle mark in multi-select
- `Key::Tab` — auto-complete or toggle confirmation value
- `Key::Backspace` / `Key::Delete` — delete characters
- `Key::CtrlU` / `Key::CtrlK` — delete to start / end of line
- `Key::Escape` / `Key::CtrlC` — abort

Submit / Abort Semantics
------------------------

[](#submit--abort-semantics)

Each prompt is a state machine with three states: pending, submitted, aborted.

- `submit()` finalises the prompt; for `MultiSelectPrompt` it only succeeds when `canSubmit()` is true.
- `abort()` (or feeding `Key::Escape` / `Key::CtrlC`) discards the prompt; `value()` / `selectedValues()` then return empty.
- `isSubmitted()` / `isAborted()` report status; `currentValue()` (Confirmation) and `selectedValue()` (Selection) reflect the current cursor regardless of submission state.

License
-------

[](#license)

[MIT](LICENSE)

###  Health Score

19

—

LowBetter than 9% of packages

Maintenance59

Moderate activity, may be stable

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/b1036e0717211b8030b83cbe729e8ba6ba442fdbd5285fb97a39d7dcfe339342?d=identicon)[detain](/maintainers/detain)

---

Top Contributors

[![detain](https://avatars.githubusercontent.com/u/1364504?v=4)](https://github.com/detain "detain (51 commits)")

### Embed Badge

![Health badge](/badges/sugarcraft-sugar-readline/health.svg)

```
[![Health](https://phpackages.com/badges/sugarcraft-sugar-readline/health.svg)](https://phpackages.com/packages/sugarcraft-sugar-readline)
```

###  Alternatives

[symfony/rocket-chat-notifier

Symfony RocketChat Notifier Bridge

13127.2k](/packages/symfony-rocket-chat-notifier)[pdir/social-feed-bundle

Social feed extension for Contao CMS

1615.7k](/packages/pdir-social-feed-bundle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
