Skip to main content
The Terminal module provides comprehensive control over terminal behavior, including cursor movement, screen manipulation, input handling, and capability detection.

Capability detection

Functions for detecting terminal capabilities and properties.

terminal::is_tty()

Check if stdout is a terminal.
if terminal::is_tty; then
    echo "Running in a terminal"
fi
Returns: Exit code 0 if stdout is a TTY, 1 otherwise.

terminal::is_tty::stdin()

Check if stdin is a terminal.
if terminal::is_tty::stdin; then
    echo "Reading from terminal"
fi
Returns: Exit code 0 if stdin is a TTY, 1 otherwise.

terminal::is_tty::stderr()

Check if stderr is a terminal.
if terminal::is_tty::stderr; then
    echo "Errors go to terminal"
fi
Returns: Exit code 0 if stderr is a TTY, 1 otherwise.

terminal::width()

Get terminal width in columns.
width=$(terminal::width)
echo "Terminal is $width columns wide"
Returns: Number of columns (defaults to 80 if unable to detect).

terminal::height()

Get terminal height in rows.
height=$(terminal::height)
echo "Terminal is $height rows tall"
Returns: Number of rows (defaults to 24 if unable to detect).

terminal::size()

Get both width and height as space-separated values.
read cols rows <<< "$(terminal::size)"
echo "Size: ${cols}x${rows}"
Returns: String in format “cols rows”.

terminal::has_colour()

Check if terminal supports colours (at least 8 colours).
if terminal::has_colour; then
    echo "Colours supported"
fi
Returns: Exit code 0 if colour is supported, 1 otherwise.

terminal::has_256colour()

Check if terminal supports 256 colours.
if terminal::has_256colour; then
    echo "256 colours available"
fi
Returns: Exit code 0 if 256-colour is supported, 1 otherwise.

terminal::has_truecolour()

Check if terminal supports true colour (24-bit RGB).
if terminal::has_truecolour; then
    echo "True colour supported"
fi
Returns: Exit code 0 if true colour is supported, 1 otherwise.

terminal::name()

Return the terminal emulator name if detectable.
echo "Running in: $(terminal::name)"
Returns: Terminal name from $TERM_PROGRAM, $TERMINAL, or $TERM (defaults to “unknown”).

Cursor control

Functions for controlling cursor visibility and position.

terminal::cursor::show()

Show the cursor.
terminal::cursor::show
Escape sequence: \033[?25h

terminal::cursor::hide()

Hide the cursor.
terminal::cursor::hide
# Do work without cursor visible
terminal::cursor::show
Escape sequence: \033[?25l

terminal::cursor::toggle()

Toggle cursor visibility. Tracks state via internal flag _TERMINAL_CURSOR_HIDDEN.
terminal::cursor::toggle  # Hides if shown
terminal::cursor::toggle  # Shows if hidden

terminal::cursor::save()

Save current cursor position.
terminal::cursor::save
# Move cursor around
terminal::cursor::restore  # Return to saved position
Escape sequence: \033[s

terminal::cursor::restore()

Restore cursor to saved position.Escape sequence: \033[u

terminal::cursor::move()

Move cursor to specific row and column (1-indexed).
terminal::cursor::move 10 20  # Row 10, column 20
Parameters:
  • $1 - Row number (1-indexed)
  • $2 - Column number (1-indexed)
Escape sequence: \033[row;colH

terminal::cursor::home()

Move cursor to top-left corner (1,1).
terminal::cursor::home
Escape sequence: \033[H

terminal::cursor::up()

Move cursor up by n rows (default 1).
terminal::cursor::up     # Up 1 row
terminal::cursor::up 5   # Up 5 rows
Parameters:
  • $1 - Number of rows (default: 1)
Escape sequence: \033[nA

terminal::cursor::down()

Move cursor down by n rows (default 1).
terminal::cursor::down     # Down 1 row
terminal::cursor::down 3   # Down 3 rows
Parameters:
  • $1 - Number of rows (default: 1)
Escape sequence: \033[nB

terminal::cursor::right()

Move cursor right by n columns (default 1).
terminal::cursor::right     # Right 1 column
terminal::cursor::right 10  # Right 10 columns
Parameters:
  • $1 - Number of columns (default: 1)
Escape sequence: \033[nC

terminal::cursor::left()

Move cursor left by n columns (default 1).
terminal::cursor::left     # Left 1 column
terminal::cursor::left 5   # Left 5 columns
Parameters:
  • $1 - Number of columns (default: 1)
Escape sequence: \033[nD

terminal::cursor::next_line()

Move cursor to start of line n lines down (default 1).
terminal::cursor::next_line    # Next line, column 1
terminal::cursor::next_line 3  # 3 lines down, column 1
Parameters:
  • $1 - Number of lines (default: 1)
Escape sequence: \033[nE

terminal::cursor::prev_line()

Move cursor to start of line n lines up (default 1).
terminal::cursor::prev_line    # Previous line, column 1
terminal::cursor::prev_line 2  # 2 lines up, column 1
Parameters:
  • $1 - Number of lines (default: 1)
Escape sequence: \033[nF

terminal::cursor::col()

Move cursor to specific column on current line (1-indexed).
terminal::cursor::col 40  # Move to column 40
Parameters:
  • $1 - Column number (default: 1)
Escape sequence: \033[nG

Screen manipulation

Functions for clearing, scrolling, and managing screen buffers.

terminal::clear()

Clear entire screen and move cursor to home position.
terminal::clear
Escape sequence: \033[2J followed by \033[H

terminal::clear::to_end()

Clear from cursor to end of screen.
terminal::clear::to_end
Escape sequence: \033[0J

terminal::clear::to_start()

Clear from cursor to beginning of screen.
terminal::clear::to_start
Escape sequence: \033[1J

terminal::clear::line()

Clear current line.
terminal::clear::line
Escape sequence: \033[2K

terminal::clear::line_end()

Clear from cursor to end of line.
terminal::clear::line_end
Escape sequence: \033[0K

terminal::clear::line_start()

Clear from cursor to start of line.
terminal::clear::line_start
Escape sequence: \033[1K

terminal::screen::alternate()

Enter alternate screen buffer (like vim/less).
terminal::screen::alternate
# Your fullscreen app here
terminal::screen::normal
Escape sequence: \033[?1049h

terminal::screen::normal()

Return to normal screen buffer.Escape sequence: \033[?1049l

terminal::screen::wrap()

Run a command in alternate screen buffer, then return to normal.
terminal::screen::wrap my_fullscreen_app arg1 arg2
Parameters:
  • $@ - Command and arguments to execute
Returns: Exit code of the wrapped command.

terminal::screen::alternate_enter()

Enter alternate screen with cleanup trap. Automatically sets up trap to return to normal screen on EXIT/INT/TERM.
terminal::screen::alternate_enter
# Your app code
terminal::screen::alternate_exit

terminal::screen::alternate_exit()

Exit alternate screen and remove traps.

terminal::scroll::up()

Scroll screen up by n lines (default 1).
terminal::scroll::up 3  # Scroll up 3 lines
Parameters:
  • $1 - Number of lines (default: 1)
Escape sequence: \033[nS

terminal::scroll::down()

Scroll screen down by n lines (default 1).
terminal::scroll::down 2  # Scroll down 2 lines
Parameters:
  • $1 - Number of lines (default: 1)
Escape sequence: \033[nT

terminal::title()

Set terminal window title (works in most modern terminal emulators).
terminal::title "My Build Script"
Parameters:
  • $1 - Title text
Escape sequence: \033]0;title\007

terminal::bell()

Ring the terminal bell.
terminal::bell  # Alert user
Escape sequence: \007

Input handling

Functions for reading keyboard input and managing terminal echo.

terminal::read_key()

Read a single keypress without requiring Enter.
terminal::read_key key
echo "You pressed: $key"
Parameters:
  • $1 - Variable name to store key (default: _TERMINAL_KEY)

terminal::read_key::timeout()

Read a single keypress with timeout.
if terminal::read_key::timeout key 5; then
    echo "You pressed: $key"
else
    echo "Timed out after 5 seconds"
fi
Parameters:
  • $1 - Variable name to store key (default: _TERMINAL_KEY)
  • $2 - Timeout in seconds (default: 5)
Returns: Exit code 0 if key pressed, non-zero on timeout.

terminal::confirm()

Prompt user for yes/no confirmation. Returns 0 for yes, 1 for no.
if terminal::confirm "Delete all files?"; then
    echo "Deleting..."
else
    echo "Cancelled"
fi
Parameters:
  • $1 - Prompt text (default: “Are you sure?”)
Returns: Exit code 0 for ‘y’, 1 for any other key.
This function defaults to NO - any key except ‘y’ will return 1.

terminal::confirm::default()

Prompt with a default choice shown. Empty input uses the default.
# Default to yes
if terminal::confirm::default yes "Continue?"; then
    echo "Continuing..."
fi

# Default to no
if terminal::confirm::default no "Risky operation?"; then
    echo "Proceeding with risk..."
fi
Parameters:
  • $1 - Default choice: “yes” or “no”
  • $2 - Prompt text (default: “Are you sure?”)
Returns: Exit code 0 for yes, 1 for no.

terminal::echo::off()

Disable terminal echo (characters won’t appear on screen).
terminal::echo::off
read -r secret
terminal::echo::on

terminal::echo::on()

Re-enable terminal echo.

terminal::read_password()

Read a password (no echo, with prompt).
terminal::read_password pass "Enter password: "
echo "Password length: ${#pass}"
Parameters:
  • $1 - Variable name to store password
  • $2 - Prompt text (default: “Password: ”)
This function automatically handles echo disable/enable and adds a newline after input.

Shell options (shopt)

Functions for managing bash shell options.

terminal::shopt::enable()

Enable a shopt option.
terminal::shopt::enable globstar
Parameters:
  • $1 - Option name
Returns: Exit code 1 if option is unsupported.

terminal::shopt::disable()

Disable a shopt option.
terminal::shopt::disable nullglob
Parameters:
  • $1 - Option name

terminal::shopt::is_enabled()

Check if a shopt option is enabled.
if terminal::shopt::is_enabled globstar; then
    echo "Globstar is enabled"
fi
Parameters:
  • $1 - Option name
Returns: Exit code 0 if enabled, 1 if disabled.

terminal::shopt::get()

Get current value of a shopt option (“on” or “off”).
value=$(terminal::shopt::get nullglob)
echo "nullglob is $value"
Parameters:
  • $1 - Option name
Returns: String “on” or “off”.

terminal::shopt::list::enabled()

List all enabled shopt options.
for opt in $(terminal::shopt::list::enabled); do
    echo "Enabled: $opt"
done
Returns: List of enabled option names, one per line.

terminal::shopt::list::disabled()

List all disabled shopt options.
for opt in $(terminal::shopt::list::disabled); do
    echo "Disabled: $opt"
done
Returns: List of disabled option names, one per line.

terminal::shopt::save()

Save current shopt state as restore commands.
state=$(terminal::shopt::save)
# Change options
eval "$state"  # Restore
Returns: Shell commands to restore current state.

terminal::shopt::load()

Restore shopt state from a variable.
state=$(terminal::shopt::save)
# Change options
terminal::shopt::load state  # Restore from variable
Parameters:
  • $1 - Variable name containing saved state (default: _SHOPT_STATE)
These functions provide quick enable/disable for commonly used shell options.

Globstar (** recursive glob)

terminal::shopt::globstar::enable   # Enable ** for recursive globs
terminal::shopt::globstar::disable  # Disable **

Nullglob (failed globs → empty)

terminal::shopt::nullglob::enable   # Empty string if glob fails
terminal::shopt::nullglob::disable  # Literal string if glob fails

Dotglob (globs match dotfiles)

terminal::shopt::dotglob::enable    # * matches .hidden
terminal::shopt::dotglob::disable   # * skips .hidden

Extglob (extended patterns)

terminal::shopt::extglob::enable    # !(foo), +(bar), etc.
terminal::shopt::extglob::disable

Nocaseglob (case-insensitive glob)

terminal::shopt::nocaseglob::enable   # *.TXT matches test.txt
terminal::shopt::nocaseglob::disable

Autocd (cd by typing directory name)

terminal::shopt::autocd::enable    # "mydir" → cd mydir
terminal::shopt::autocd::disable

Checkwinsize (update LINES/COLUMNS)

terminal::shopt::checkwinsize::enable   # Auto-update after commands
terminal::shopt::checkwinsize::disable

Histappend (append to history)

terminal::shopt::histappend::enable   # Append, don't overwrite
terminal::shopt::histappend::disable

Cdspell (autocorrect cd typos)

terminal::shopt::cdspell::enable    # cd /usr/lcoal → /usr/local
terminal::shopt::cdspell::disable

Nocasematch (case-insensitive [[ =~)

terminal::shopt::nocasematch::enable   # Case-insensitive regex
terminal::shopt::nocasematch::disable

Build docs developers (and LLMs) love