TermUI.Terminal.SizeDetector (TermUI v1.0.0)
View SourceTerminal size detection utilities.
This module provides centralized terminal size detection that can be used by both the Terminal module and backend implementations. It attempts multiple methods in order of reliability:
- Erlang
:iomodule (most reliable when available) - LINES/COLUMNS environment variables
stty sizecommand (last resort)
All methods validate dimensions against practical bounds to prevent resource exhaustion from malicious input.
Size Format
All functions return size as {rows, cols} (height, width) to match standard
terminal conventions where rows come first.
Example
iex> SizeDetector.detect()
{:ok, {24, 80}}
iex> SizeDetector.detect(size: {40, 120})
{:ok, {40, 120}}Bounds Checking
Detected sizes are validated against max_dimension/0 (9999) to prevent
integer overflow or resource exhaustion attacks through environment variables
or malicious terminal responses.
Summary
Functions
Auto-detects terminal size using all available methods.
Detects terminal size, optionally accepting an explicit size.
Detects terminal size from LINES and COLUMNS environment variables.
Detects terminal size from Erlang's :io module.
Detects terminal size from the stty size command.
Returns the maximum valid terminal dimension.
Validates that the given dimensions are within practical bounds.
Functions
@spec auto_detect() :: {:ok, {pos_integer(), pos_integer()}} | {:error, :size_detection_failed}
Auto-detects terminal size using all available methods.
Tries methods in order:
:io.rows/0and:io.columns/0- LINES and COLUMNS environment variables
stty sizecommand
Returns
{:ok, {rows, cols}}- Successfully detected size{:error, :size_detection_failed}- All methods failed
@spec detect(keyword()) :: {:ok, {pos_integer(), pos_integer()}} | {:error, term()}
Detects terminal size, optionally accepting an explicit size.
When an explicit size tuple is provided, it's validated and returned. Otherwise, auto-detection is attempted.
Options
:size- Explicit{rows, cols}tuple to use instead of detection
Returns
{:ok, {rows, cols}}- Successfully detected or validated size{:error, reason}- Failed to detect size
Examples
# Auto-detect
{:ok, {24, 80}} = SizeDetector.detect()
# Use explicit size
{:ok, {40, 120}} = SizeDetector.detect(size: {40, 120})
@spec detect_from_env() :: {:ok, {pos_integer(), pos_integer()}} | {:error, term()}
Detects terminal size from LINES and COLUMNS environment variables.
These are standard environment variables set by many shells and terminal emulators. Values are validated against practical bounds.
@spec detect_from_io() :: {:ok, {pos_integer(), pos_integer()}} | {:error, term()}
Detects terminal size from Erlang's :io module.
Uses :io.rows/0 and :io.columns/0 which query the terminal directly.
This is the most reliable method when running in a real terminal.
@spec detect_from_stty() :: {:ok, {pos_integer(), pos_integer()}} | {:error, term()}
Detects terminal size from the stty size command.
This is a fallback method that works on most Unix-like systems.
It spawns a subprocess to run stty size with safety protections.
@spec max_dimension() :: pos_integer()
Returns the maximum valid terminal dimension.
@spec validate_size(term(), term()) :: {:ok, {pos_integer(), pos_integer()}} | {:error, :invalid_size}
Validates that the given dimensions are within practical bounds.
Returns
{:ok, {rows, cols}}- Valid dimensions{:error, :invalid_size}- Invalid dimensions