Module Spectrum_capabilities.Capabilities

Terminal color capability detection.

Detects terminal color support using environment variables and system information. Supports detection for various terminals, CI systems, and operating systems.

type color_level =
  1. | Unsupported
    (*

    No color support (or FORCE_COLOR=0). Colors quantized to Basic.

    *)
  2. | Basic
    (*

    16 colors via ANSI codes 30-37, 90-97 (or FORCE_COLOR=1).

    *)
  3. | Eight_bit
    (*

    256 colors from xterm palette (or FORCE_COLOR=2).

    *)
  4. | True_color
    (*

    24-bit RGB true color support (or FORCE_COLOR=3).

    *)

Color support level of a terminal.

val pp_color_level : Ppx_deriving_runtime.Format.formatter -> color_level -> Ppx_deriving_runtime.unit
val show_color_level : color_level -> Ppx_deriving_runtime.string
val equal_color_level : color_level -> color_level -> Ppx_deriving_runtime.bool
type color_level_info = {
  1. stdout : color_level;
    (*

    Color support level for stdout

    *)
  2. stderr : color_level;
    (*

    Color support level for stderr

    *)
}

Color level information for stdout and stderr streams.

val supported_color_level : bool -> color_level

Detect color support level for a file descriptor.

Checks environment variables (FORCE_COLOR, COLORTERM, TERM, CI variables) and system information to determine terminal capabilities. Uses heuristics adapted from the Chalk JavaScript library.

  (* Check if stdout supports colors *)
  let is_tty = Unix.isatty Unix.stdout in
  let level = Spectrum_capabilities.Capabilities.supported_color_level is_tty in
  match level with
  | True_color -> Printf.printf "24-bit RGB supported\n"
  | Eight_bit -> Printf.printf "256 colors supported\n"
  | Basic -> Printf.printf "16 colors supported\n"
  | Unsupported -> Printf.printf "No color support\n"
  (* Check a specific file descriptor *)
  let fd = Unix.openfile "/dev/tty" [Unix.O_RDWR] 0o666 in
  let is_tty = Unix.isatty fd in
  let level = Spectrum_capabilities.Capabilities.supported_color_level is_tty in
  Unix.close fd
  • parameter is_tty

    Whether the file descriptor is a TTY

  • returns

    Detected color support level

val supported_color_levels : unit -> color_level_info

Detect color support for stdout and stderr.

Convenience function that checks Unix.isatty for both stdout and stderr and returns their respective color support levels.

  let info = Spectrum_capabilities.Capabilities.supported_color_levels () in
  match info.stdout with
  | True_color -> print_endline "24-bit color supported"
  | Eight_bit -> print_endline "256 colors supported"
  | Basic -> print_endline "16 colors supported"
  | Unsupported -> print_endline "No color support"

Override detection using the FORCE_COLOR environment variable:

  • FORCE_COLOR=0 or FORCE_COLOR=false: Force Unsupported/Basic
  • FORCE_COLOR=1 or FORCE_COLOR=true: Force Basic (16 colors)
  • FORCE_COLOR=2: Force Eight_bit (256 colors)
  • FORCE_COLOR=3: Force True_color (24-bit RGB)
  • returns

    Color level info for stdout and stderr

Testing Utilities

The following types and functions are exposed for testing purposes. They allow mocking environment variables and OS information in tests.

module StrMap : Stdlib.Map.S with type key = string

String map type for building fake environments.

module type EnvProvider = sig ... end

Environment provider interface for dependency injection.

module type OsInfoProvider = sig ... end

OS information provider interface for dependency injection.

module type CapabilitiesProvider = sig ... end

Capability detection functor parameterized by environment and OS providers.

Create capabilities module with custom providers.

val env_provider_of_map : string StrMap.t -> (module EnvProvider)

Create an environment provider from a string map (for testing).

  let env_map = Spectrum_capabilities.Capabilities.StrMap.(
      empty
      |> add "FORCE_COLOR" "3"
      |> add "TERM" "xterm-256color"
    ) in
  let module Env = (val Spectrum_capabilities.Capabilities.env_provider_of_map env_map) in
  (* Use Env in tests *)
val os_info_provider : bool -> string option -> (module OsInfoProvider)

Create an OS info provider with fixed values (for testing).

  let module OsInfo = (val Spectrum_capabilities.Capabilities.os_info_provider false (Some "10.0.19041")) in
  (* Use OsInfo in tests *)