Documentation
¶
Overview ¶
Package termio provides interruptible I/O primitives and terminal handling.
It solves common issues with blocking I/O in Go CLI tools, particularly on Windows, where a blocked read from stdin can prevent signal delivery or cause hangs.
Key features:
- InterruptibleReader: A reader that respects context cancellation.
- Open: Platform-safe terminal opening (uses CONIN$ on Windows).
- Upgrade: Automatic detection and upgrade of readers to terminal-aware handles.
Safety ¶
The InterruptibleReader uses a "Shielded Return" strategy. If data arrives exactly as the context is cancelled, the reader prioritizes returning the data (Data First, Error Second). The *next* read will then check for cancellation. This ensures no data loss occurs when reading from pipes or streams.
For interactive prompts (e.g., "Confirm Delete y/N"), use InterruptibleReader.ReadInteractive. This method enforces "Error First" logic, discarding potential race-condition input to prioritize safety.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrInterrupted = errors.New("interrupted")
Functions ¶
func IsInterrupted ¶
IsInterrupted checks if the error is related to an interruption (Context Canceled, ErrInterrupted, or EOF).
func IsTerminal ¶
IsTerminal checks if the given file is a terminal. For now, we rely on basic checks or x/term if needed, but for simple cases we just assume it's okay. We might add x/term dependency later if we need IsTerminal check.
func Open ¶
func Open() (io.ReadCloser, error)
Open returns the standard input reader. On POSIX, it simply returns os.Stdin.
Types ¶
type InterruptibleReader ¶
type InterruptibleReader struct {
// contains filtered or unexported fields
}
InterruptibleReader wraps an io.Reader and checks for cancellation before and after reads. Note: The underlying Read() call may still block! This wrapper primarily ensures that if the context is cancelled *before* we read, we return immediately, and if cancelled *during* the read (and the read returns), we prioritize the cancellation error.
func NewInterruptibleReader ¶
func NewInterruptibleReader(base io.Reader, cancel <-chan struct{}) *InterruptibleReader
NewInterruptibleReader returns a reader that checks the cancel channel.
func (*InterruptibleReader) ReadInteractive ¶ added in v1.4.0
func (r *InterruptibleReader) ReadInteractive(p []byte) (n int, err error)
ReadInteractive reads from the underlying source but enforces a "Strict Cancel" policy. Unlike Read() (which prioritizes Data over Error to prevent data loss), ReadInteractive prioritizes the Cancellation Error over Data.
If the context is cancelled while reading (or immediately after), any data read from the OS buffer is DISCARDED, and ErrInterrupted is returned.
Use this for interactive prompts (e.g. "Do you want to continue? y/N") where a User Interrupt (Ctrl+C) should always take precedence over the input "y", preventing accidental execution of dangerous actions.