Hi Tim, hi internals, Following up on this thread now that the API work we discussed here has actually settled.
I made the changes from your review in 0.9.0: a unified Terminal session, create/from constructors, an OO-only API, and TerminalSize instead of separate width/height helpers. 1.0.0 then froze that session API as the stable 1.x contract. 1.1.0 added readEvent after working through what Symfony TUI actually needs; readKey is useful for normalized keys, but TUI also needs raw POSIX chunks and native Windows event details. Symfony Console/TUI PR #66173 is now using ext-terminal optionally for terminal size, hidden input and raw mode: https://github.com/symfony/symfony/pull/66173 Nicolas Grekas has approved it, and GromNaN also approved it after testing and benchmarking the native size path on macOS. That integration work has been useful because it exposed real compatibility and behavior questions rather than only API design in isolation. Yesterday I also did a fresh audit on real Windows, Linux and macOS runners. It found five edge cases around stale mode tokens, overlapping raw-mode ownership, POSIX SIGWINCH coordination, split Windows surrogate input and split POSIX UTF-8 input. Those fixes are all merged on main now and the final CI is green. I have not released those fixes yet; the latest public release is still 1.1.0. At this point I do not think the RFC should simply move the extension into core unchanged. My current thought is a smaller Io\Terminal surface for PHP 8.7, with the extension remaining useful as the reference implementation and backport, and compatibility-only pieces left out of the core proposal. Before I write the formal RFC, I would like to sanity-check that direction here. Would you prefer the initial RFC to stay with the higher-level primitives such as session creation, TTY/size, raw mode, hidden input and readKey, or does including the lower-level readEvent primitive also make sense given the Symfony TUI use case? Thanks, Pratik On Fri, 18 Sep 2026 09:46:05 +0200, "Tim Düsterhus" <[email protected]> wrote: > 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
