Class: Tuile::Color

Inherits:
Object
  • Object
show all
Defined in:
lib/tuile/color.rb

Overview

An immutable terminal color. Accepts the three forms ANSI/SGR understands:

  • a Symbol from COLOR_SYMBOLS — 8 standard + 8 bright named colors (SGR 30..37 / 90..97 for fg, 40..47 / 100..107 for bg)

  • an Integer 0..255 — the 256-color palette (SGR 38;5;N / 48;5;N)

  • an Array of three Integers 0..255 — 24-bit RGB (SGR 38;2;R;G;B / 48;2;R;G;B)

A constant per named color is pre-defined (‘Color::RED`, `Color::BRIGHT_BLUE`, …) so callers can reach for `Color::RED` instead of building one each time. Color.coerce accepts anything new accepts plus `nil` (terminal default) and an existing Color (returned as-is), so APIs that accept colors typically take `[Color, nil]` and pass through Color.coerce.

“‘ruby Color.new(:red) # named Color.new(42) # 256-color palette Color.new([255, 100, 0]) # RGB Color::RED # constant Color.coerce(:red) # accepts raw forms, returns Color Color.coerce(nil) # nil → nil “`

#to_ansi renders a full SGR escape (‘“e[31m”`); #sgr_codes returns the raw numeric codes so callers (notably StyledString) can combine them with other SGR attributes in a single sequence.

Constant Summary collapse

COLOR_SYMBOLS =

Symbolic color names. Order is significant: indices 0..7 map to the standard ANSI colors (SGR 30..37 fg / 40..47 bg); indices 8..15 map to bright variants (SGR 90..97 / 100..107).

Returns:

  • (Array<Symbol>)
%i[
  black red green yellow blue magenta cyan white
  bright_black bright_red bright_green bright_yellow
  bright_blue bright_magenta bright_cyan bright_white
].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value) ⇒ Color

Returns a new instance of Color.

Parameters:

  • value (Symbol, Integer, Array<Integer>)

    see class-level docs for the three accepted forms.

Raises:

  • (ArgumentError)

    when ‘value` is not one of the accepted forms.



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/tuile/color.rb', line 57

def initialize(value)
  unless COLOR_SYMBOLS.include?(value) ||
         (value.is_a?(Integer) && value.between?(0, 255)) ||
         (value.is_a?(Array) && value.length == 3 &&
          value.all? { |v| v.is_a?(Integer) && v.between?(0, 255) })
    raise ArgumentError, "invalid color: #{value.inspect}"
  end

  @value = value.is_a?(Array) ? value.dup.freeze : value
  freeze
end

Instance Attribute Details

#valueSymbol, ... (readonly)

The underlying raw representation — a Symbol, Integer, or frozen Array<Integer>.

Returns:

  • (Symbol, Integer, Array<Integer>)


72
73
74
# File 'lib/tuile/color.rb', line 72

def value
  @value
end

Class Method Details

.coerce(value) ⇒ Color?

Coerces the input to a Tuile::Color. ‘nil` passes through unchanged (callers use `nil` for the terminal default); an existing Tuile::Color is returned as-is; otherwise the value is fed to new.

Parameters:

  • value (Color, Symbol, Integer, Array<Integer>, nil)

Returns:

Raises:

  • (ArgumentError)

    when ‘value` is not one of the accepted forms.



47
48
49
50
51
52
# File 'lib/tuile/color.rb', line 47

def self.coerce(value)
  case value
  when nil, Color then value
  else new(value)
  end
end

Instance Method Details

#==(other) ⇒ Boolean Also known as: eql?

Parameters:

  • other (Object)

Returns:

  • (Boolean)


108
109
110
# File 'lib/tuile/color.rb', line 108

def ==(other)
  other.is_a?(Color) && @value == other.value
end

#hashInteger

Returns:

  • (Integer)


114
115
116
# File 'lib/tuile/color.rb', line 114

def hash
  [self.class, @value].hash
end

#inspectString

Returns:

  • (String)


119
120
121
# File 'lib/tuile/color.rb', line 119

def inspect
  "#<#{self.class.name} #{@value.inspect}>"
end

#sgr_codes(target = :fg) ⇒ Array<Integer>

SGR parameter codes for emitting this color as either a foreground (‘target: :fg`) or background (`target: :bg`). Returned as an array so callers can splice them into a multi-attribute SGR (e.g. bold + color).

Parameters:

  • target (Symbol) (defaults to: :fg)

    ‘:fg` or `:bg`.

Returns:

  • (Array<Integer>)

Raises:

  • (ArgumentError)

    when ‘target` is neither `:fg` nor `:bg`.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/tuile/color.rb', line 81

def sgr_codes(target = :fg)
  base, ext = case target
              when :fg then [30, 38]
              when :bg then [40, 48]
              else raise ArgumentError, "target must be :fg or :bg, got #{target.inspect}"
              end
  case @value
  when Symbol
    idx = COLOR_SYMBOLS.index(@value)
    idx < 8 ? [base + idx] : [base + 60 + (idx - 8)]
  when Integer then [ext, 5, @value]
  when Array then [ext, 2, *@value]
  end
end

#to_ansi(target = :fg) ⇒ String

Full SGR escape sequence for this color (e.g. ‘“e[31m”`). Useful for `print`-style direct emission; for composing with other attributes use #sgr_codes instead.

Parameters:

  • target (Symbol) (defaults to: :fg)

    ‘:fg` or `:bg`.

Returns:

  • (String)


102
103
104
# File 'lib/tuile/color.rb', line 102

def to_ansi(target = :fg)
  "\e[#{sgr_codes(target).join(";")}m"
end