Re: [PHP-DEV] Re: [PHP DEV] [Discussion] Native terminal helpers for PHP CLI

[email protected] (Tim Düsterhus)
Newsgroups php.internals
Message-ID <[email protected]>
Hi

it seems your replies don't contain proper `in-reply-to` or `references` 
headers, which breaks the threading. As an example in the archives at 
https://news-web.php.net/php.internals/132530 no other emails from the 
discussion are shown and https://news-web.php.net/php.internals/132528 
only shows your email and my reply. On externals.io new threads are 
created for every email. Can you check the configuration of your email 
client and make sure to always use real “Reply” instead of sending a 
fresh email?

On 2026-09-18 04:19, Pratik Bhujel wrote:
> To answer your question regarding the domain problem:
> 
> The primary issue is that PHP CLI currently lacks native primitives for
> non-canonical raw terminal mode and single keypress reading. Modern
> interactive CLI tools in userland (such as Laravel Prompts, Symfony
> Console, and interactive tools) want to deliver rich experiences like
> searchable selection menus, autocomplete, multi-choice checkboxes,
> spinners, and hidden password prompts.

Yes, I roughly understand the problem that is being solved. It's just 
something I never had to deal with, so I can't comment on whether the 
solution is complete and ergonomic.

> 2. Instance-based Terminal handle:
> Classes are no longer static wrappers. The Io\Terminal\Terminal class
> encapsulates a stream descriptor, created via named constructors 
> stdin(),
> stdout(), stderr(), or by wrapping custom stream resources.

For consistency with the recently introduced APIs, the named 
constructors should start with a prefix that clearly indicates that the 
method is a constructor. As of now we have the following:

- Dom\HTMLDocument::createEmpty(), ::createFromFile(), 
::createFromString()
- Time\Duration::fromSeconds(), ::fromMilliseconds(), …, 
::fromIso8601DurationString()
- Uri\Rfc3986\Uri::parse() (though this one also has a real 
constructor).

For the Terminal I wonder why we need to have stdin, stdout, and stderr 
separately. For me logically a “Terminal” is a combination of all three 
and I would expect them to be “synchronized” if that makes sense?

> 3. Automatic RAII cleanup:
> Both Terminal instances and ModeToken objects track active raw mode and
> automatically restore terminal state upon destruction. If an uncaught
> exception terminates script execution, the destructor restores 
> canonical
> mode so the developer shell is never left broken.

That makes sense to me.

> 5. Free-standing procedural functions:
> Io\Terminal provides procedural functions like is_tty(), read_key(), 
> and
> get_size() for functional script usage.

I've taken another look at these and have some point that stood out to 
me:

- Do we need all three of get_size(), get_width(), get_height()? The 
latter two seem redundant.
- Should related methods have a common prefix for discoverability? So 
mode_enable_raw() and mode_restore() instead of enable_raw_mode() and 
restore_mode()?
- Many (all?) of the functions also exists as methods on the Terminal 
class. This redundant procedural + object-oriented API design is 
something we no longer do. Decide on one of the two, depending on what 
is more useful. I expect the OO variant to be the right choice due to 
the RAII support.

Best regards
Tim Düsterhus
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.