class Chromate::Color

The `Color` class is used to represent a terminal color in the range 0..255. Colors are powerful tools, and have a multitude of convenience methods to make working with them easier.

Color Models

All colors have a so-called 'color model' (accessible via the `color_model` attribute). The color model of a color determines how it will be escaped. The following color models are possible:

- Colors in the range 0..7 have a color model of 8. These colors are
  always escaped as single-integer values in the ranges 30..37 and
  40..47 for foregrounds and backgrounds, respectively.
- Colors in the range 8..15 have a color model of 16. These colors
  can be escaped in two ways, with single-integer values in the 
  ranges 90..97 and 100..107, for foreground and background,
  respectively, or with additional bold sequences. Which route is
  taken depends on the compliancy setting; single-integer values are
  non-compliant, while bold sequences are. The compliancy setting
  may be specified in three ways, each overriding the last: via the
  class attribute on `Color`, via the instance attribute by the same
  name, and in the method call as a second (optional parameter).
  The default at all levels is non-compliancy.
- Colors in the range 16..255 have a color model of 256. These
  colors are always escaped as xterm-256 escape sequences of the
  form 38;5;x for foreground and 48;5;x for background, where x is
  the actual color value.

Converting from Other Formats

The `Color` class features a powerful approximation mechanism, allowing the creation of colors from arbitrary RGB values, which may be specified either in RGB using {::from_rgb} or in hex using {::from_hex}. When either of these methods are used, the closest matching terminal color code will be found automatically, using the CIE 1976 delta-E algorithm. This operation is quite a bit slower compared to using exact color values, but it must be done only once, as all values are cached after first use and kept until the end of program execution.

Making New Colors

If you __really__ want to make a new color, you may do so by calling the provided constructor. However, this is wasteful – there is, after all, a finite set of possible colors. Moreover, all of these colors already exist as members of the `COLORS` constant. That's all well and good if you have the raw color code, which can be used as an index for the `COLORS` array, but what if you don't? Well, then {::[]} is your new best friend! This method accepts the full range of color representations, including raw color codes, names, hex strings, and RGB values. The following example showcases all of the various types that {::[]} accepts:

“`ruby # The following all return the 'black' color Color Color Color Color Color[[0, 0, 0]] Color[0, 0, 0]

# Malformed inputs Color # => ArgumentError: bad color code: -1 Color # => ArgumentError: bad color code: 256 Color # => nil Color # => ArgumentError: invalid hex string: # Color # => nil “`

Note that when getting a color from a name, `nil` will be returned if no color with that name exists, rather than throwing an error.

Attributes

compliant[RW]

@return [Boolean] the global default compliancy setting

color_model[R]

@return [Integer] the color model of the color (either 8, 16, or 256)

compliant[RW]

@return [Boolean] the default compliancy setting for {#to_fg} and {#to_bg}

Public Class Methods

[](value, g = nil, b = nil) click to toggle source

Get an existing Color object representing the specified color code, hex value, color name, or RGB array. @param value [String,Symbol,Array]

@return [Color]

# File lib/chromate/color.rb, line 125
def self.[](value, g = nil, b = nil)
  case value
  when Fixnum
    if value > 255 or value < 0
      raise ArgumentError, "bad color code: #{value}"
    else
      COLORS[value]
    end
  when String
    if value[0] == '#'
      Color.from_hex(value)
    elsif COLOR_NAMES.key?(value.intern)
      COLORS[COLOR_NAMES[value.intern]]
    else
      nil
    end
  when Symbol
    if COLOR_NAMES.key?(value)
      COLORS[COLOR_NAMES[value]]
    else
      nil
    end
  when Array
    Color.from_rgb(*value)
  else
    if g.nil? and b.nil?
      raise TypeError, "don't know what to do with a #{value.class}"
    else
      Color.from_rgb(value, g, b)
    end
  end
end
compliant=(what) click to toggle source
# File lib/chromate/color.rb, line 87
def compliant=(what)
  @compliant = what
  COLORS.each { |c| c.compliant = what }
end
from_hex(hex) click to toggle source

Get a Color object representing the specified hex string. @param hex [String] a string of the form #XXXXXX

@return [Color]

# File lib/chromate/color.rb, line 163
def self.from_hex(hex)
  if Hex::PATTERN =~ hex
    Color.from_rgb(*hex.scan(Hex::BYTE).map { |b| b.to_i(16) })
  else
    raise ArgumentError, "invalid hex string: #{hex}"
  end
end
from_rgb(r, g = r, b = r) click to toggle source

Get a Color object representing the specified color in RGB space. @note The `g` and `b` arguments default to the value passed in for `r`, so

that if you have a monochromatic color (e.g., r, g, and b are the same),
you may pass a single value.

@param r [Integer] the red component @param g [Integer] the green component @param b [Integer] the blue component

@example Getting a monochromatic color

Color.from_rgb(0) # <=> Color.from_rgb(0, 0, 0)

@return [Color]

# File lib/chromate/color.rb, line 184
def self.from_rgb(r, g = r, b = r)
  ary = [r, g, b]
  if RGB::COLORS.include?(ary)
    COLORS[RGB::COLORS.index(ary)]
  elsif CACHE.include?(ary)
    CACHE[ary]
  else
    lab = RGB.to_lab(ary)
    code = Lab::COLORS.index(Lab::COLORS.sort do |lab1, lab2|
      Lab.difference(lab, lab1) <=> Lab.difference(lab, lab2)
    end.first)
    CACHE[ary] = COLORS[code]
    COLORS[code]
  end
end
new(value, compliant = Color.compliant) click to toggle source

Create a new Color object representing the specified color code. The color model will be inferred automatically based on the range of `value` (8 if it's less than 8, 16 if it's less than 16, and 256 otherwise). @param value [Numeric] the xterm color code of the new color

@return [Color]

Calls superclass method
# File lib/chromate/color.rb, line 101
def initialize(value, compliant = Color.compliant)
  if COLOR_NAMES.key?(value)
    super(COLOR_NAMES[value])
  else
    super(value)
  end

  @compliant = compliant
  @escape = :fg
  @color_model = if @value < 8
    8
  elsif @value < 16
    16
  else
    256
  end
end

Public Instance Methods

as_bg() click to toggle source

Convert to a Color that escapes to a background by default.

@return [Color]

# File lib/chromate/color.rb, line 279
def as_bg
  @escape = :bg
  self
end
as_fg() click to toggle source

Convert to a Color that escapes to a foreground by default.

@return [Color]

# File lib/chromate/color.rb, line 241
def as_fg
  @escape = :fg
  self
end
b()
Alias for: blue
bg?() click to toggle source

Does this color represent a background?

@return [Boolean]

# File lib/chromate/color.rb, line 288
def bg?
  @escape == :bg
end
blue() click to toggle source

Get the blue component of the color.

@return [Integer]

# File lib/chromate/color.rb, line 361
def blue
  RGB::COLORS[@value][2]
end
Also aliased as: b
escape() click to toggle source

Escape as an SGR escape sequence.

@return [String] an escape sequence of the form “e[1;2;3;…m”

# File lib/chromate/color.rb, line 296
def escape
  case @escape
  when :fg
    to_fg
  when :bg
    to_bg
  end
end
fg?() click to toggle source

Does this color represent a foreground?

@return [Boolean]

# File lib/chromate/color.rb, line 250
def fg?
  @escape == :fg
end
g()
Alias for: green
green() click to toggle source

Get the green component of the color.

@return [Integer]

# File lib/chromate/color.rb, line 352
def green
  RGB::COLORS[@value][1]
end
Also aliased as: g
greyscale?() click to toggle source

Is this color greyscale?

@return [Boolean]

# File lib/chromate/color.rb, line 212
def greyscale?
  GREYSCALE_COLORS.include?(self)
end
inspect() click to toggle source
# File lib/chromate/color.rb, line 315
def inspect
  if name.nil?
    "#<Color: (#{to_rgb.join(',')})>"
  else
    "#<Color: #{name}>"
  end
end
name() click to toggle source

Get the name of the color, if it exists.

@return [Symbol]

# File lib/chromate/color.rb, line 309
def name
  if COLOR_NAMES.value?(@value)
    COLOR_NAMES.find { |k, v| v == @value }.first
  end
end
r()
Alias for: red
red() click to toggle source

Get the red component of the color.

@return [Integer]

# File lib/chromate/color.rb, line 343
def red
  RGB::COLORS[@value][0]
end
Also aliased as: r
supported?() click to toggle source

Is this color supported by the host environment?

@return [Boolean]

# File lib/chromate/color.rb, line 204
def supported?
  SUPPORTED_COLORS.include?(self)
end
to_bg(compliant = @compliant) click to toggle source

Escape as a background SGR escape sequence. @param compliant [Boolean] whether to use standards-compliant bold

sequences or the non-standard 100-107 range

@return [String] an escape sequence setting the foreground to the color

# File lib/chromate/color.rb, line 260
def to_bg(compliant = @compliant)
  case @color_model
  when 8
    "\e[#{40 + @value}m"
  when 16
    if compliant
      "\e[#{40 + @value - 8};1m"
    else
      "\e[#{100 + @value - 8}m"
    end
  when 256
    "\e[48;5;#{@value}m"
  end
end
to_fg(compliant = @compliant) click to toggle source

Escape as a foreground SGR escape sequence. @param compliant [Boolean] whether to use standards-compliant bold

sequences or the non-standard 90-97 range

@return [String] an escape sequence setting the foreground to the color

# File lib/chromate/color.rb, line 222
def to_fg(compliant = @compliant)
  case @color_model
  when 8
    "\e[#{30 + @value}m"
  when 16
    if compliant
      "\e[#{30 + @value - 8};1m"
    else
      "\e[#{90 + @value - 8}m"
    end
  when 256
    "\e[38;5;#{@value}m"
  end
end
to_hex() click to toggle source

Get the hex value represented by the color.

@return [String] a string of the form #XXXXXX

# File lib/chromate/color.rb, line 335
def to_hex
  '#' + Hex::COLORS[@value]
end
to_rgb() click to toggle source

Get the RGB value represented by the color.

@return [<Integer>] an array containing r, g, and b values, in that order

# File lib/chromate/color.rb, line 327
def to_rgb
  RGB::COLORS[@value]
end