Re: [RFC] Io\Terminal

From: Date: Tue, 06 Oct 2026 08:27:15 +0000
Subject: Re: [RFC] Io\Terminal
References: 1 2 3 4 5 6 7 8 9 10 11 12  Groups: php.internals 
Request: Send a blank email to internals+get-132804@lists.php.net to get a copy of this message
Hi all, Sorry for the delay. I took some time to think through the testing and ownership points and verify the changes on both platforms. I have updated the RFC and implementation to v0.4: https://wiki.php.net/rfc/io_terminal https://github.com/php/php-src/pull/23941 Ilia wrote: I agree with Tim and Bob: drop both interfaces and rename SystemTerminal to Terminal. This is now implemented. Terminal and ModeToken are final native classes, with one Terminal implementation and the existing fromStdio() and fromStreams() factories. Larry, the scripted-stream approach now works for key and secret reads as well as line reads. readKey() decodes ordinary byte streams on both platforms, readSecret() accepts scripted input, and enableRawMode() returns a no-op lease for non-terminal streams. This gives application input tests a straightforward PHP-stream approach without adding interfaces to core. Native dimensions, resize events and mode failures still need terminal integration tests. Tim, your point about keeping Windows test infrastructure separate from the long-term API design helped clarify this. I also investigated create_new_console on Windows 11 ARM64. With standard input redirected to a pipe, the child still reads that pipe; creating a console does not make those bytes native console key events. Opening CONIN$/CONOUT$ gives access to console handles, but writing bytes with fwrite() does not inject input records. The native console checks therefore used WriteConsoleInputW() through a test harness. That distinction no longer dictates the public API: ordinary streams support application input tests on Windows too. Ilia's other points are addressed: - Raw-mode acquisition preserves POSIX output settings, including OPOST. The RFC now specifies the observable input behavior. - Leases record the acquiring process. A forked child's cleanup does not restore the parent's terminal mode; explicit restoration of an inherited parent token is rejected. - Terminal no longer retains the latest token. restoreMode() requires a token and returns void. Normal completion means the lease was released; failures throw. An explicit final restoration failure leaves the token active for a retry. - Key::Insert and Key::ShiftTab are included. Nicolas's shared logical-terminal lease model is retained: the first acquisition saves the mode, overlapping leases can be released in any order, and the final release restores the saved state. Cross-wrapper restoration for the same terminal also remains supported. readLine() keeps its limited scope, without a portable editor or timeout parameter. It does not override an outstanding native raw-mode lease. The output stream remains useful for geometry and resize detection; application output continues through normal stream APIs. Local testing covered macOS and Windows 11 ARM64, including native Windows console input, Unicode and mode restoration. The PR also includes regressions for input transitions, split CRLF handling and timeout behavior. Thanks to everyone for working through this. I would like to move this revision toward voting after allowing time to review these changes. Please flag any remaining concerns with the public contract or implementation. Best regards, Pratik

« previous php.internals (#132804) next »