Class: Rich::Color

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

Overview

Represents a terminal color. Supports default colors, standard ANSI colors (0-15), 8-bit colors (0-255), and true color (24-bit RGB).

Constant Summary collapse

COLOR_REGEX =

Regex for parsing color definitions

/\A
  (?:\#(?<hex>[0-9a-fA-F]{6}))|
  (?:color\((?<color8>\d{1,3})\))|
  (?:rgb\((?<rgb>[\d\s,]+)\))
\z/x

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, type:, number: nil, triplet: nil) ⇒ Color

Create a new color

Parameters:

  • name (String)

    Color name or definition

  • type (Symbol)

    Color type (see ColorType)

  • number (Integer, nil) (defaults to: nil)

    Color number

  • triplet (ColorTriplet, nil) (defaults to: nil)

    RGB triplet



320
321
322
323
324
325
326
# File 'lib/rich/color.rb', line 320

def initialize(name, type:, number: nil, triplet: nil)
  @name = name.freeze
  @type = type
  @number = number
  @triplet = triplet
  freeze
end

Instance Attribute Details

#nameString (readonly)

Returns Original color name or definition.

Returns:

  • (String)

    Original color name or definition



296
297
298
# File 'lib/rich/color.rb', line 296

def name
  @name
end

#numberInteger? (readonly)

Returns Color number for standard/8-bit colors.

Returns:

  • (Integer, nil)

    Color number for standard/8-bit colors



302
303
304
# File 'lib/rich/color.rb', line 302

def number
  @number
end

#tripletColorTriplet? (readonly)

Returns RGB triplet for truecolor.

Returns:



305
306
307
# File 'lib/rich/color.rb', line 305

def triplet
  @triplet
end

#typeSymbol (readonly)

Returns Color type (see ColorType).

Returns:

  • (Symbol)

    Color type (see ColorType)



299
300
301
# File 'lib/rich/color.rb', line 299

def type
  @type
end

Class Method Details

.defaultColor

Create a default color

Returns:



474
475
476
# File 'lib/rich/color.rb', line 474

def default
  @default ||= new("default", type: ColorType::DEFAULT)
end

.from_ansi(number) ⇒ Color

Create a color from ANSI number

Parameters:

  • number (Integer)

    Color number (0-255)

Returns:



481
482
483
484
485
486
# File 'lib/rich/color.rb', line 481

def from_ansi(number)
  number = number.clamp(0, 255)
  type = number < 16 ? ColorType::STANDARD : ColorType::EIGHT_BIT
  name = COLOR_NUMBER_TO_NAME[number] || "color(#{number})"
  new(name, type: type, number: number)
end

.from_rgb(red, green, blue) ⇒ Color

Create a color from RGB values

Parameters:

  • red (Integer)

    Red (0-255)

  • green (Integer)

    Green (0-255)

  • blue (Integer)

    Blue (0-255)

Returns:



500
501
502
# File 'lib/rich/color.rb', line 500

def from_rgb(red, green, blue)
  from_triplet(ColorTriplet.new(red, green, blue))
end

.from_triplet(triplet) ⇒ Color

Create a color from RGB triplet

Parameters:

Returns:



491
492
493
# File 'lib/rich/color.rb', line 491

def from_triplet(triplet)
  new(triplet.hex, type: ColorType::TRUECOLOR, triplet: triplet)
end

.parse(color) ⇒ Color

Parse a color definition string

Parameters:

  • color (String)

    Color definition

Returns:

  • (Color)

    Parsed color

Raises:



456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
# File 'lib/rich/color.rb', line 456

def parse(color)
  return color if color.is_a?(Color)

  @parse_cache_mutex.synchronize do
    return @parse_cache[color] if @parse_cache.key?(color)
  end

  result = parse_uncached(color)

  @parse_cache_mutex.synchronize do
    @parse_cache[color] = result
  end

  result
end

Instance Method Details

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

Check equality with another color



424
425
426
427
428
# File 'lib/rich/color.rb', line 424

def ==(other)
  return false unless other.is_a?(Color)

  @type == other.type && @number == other.number && @triplet == other.triplet
end

#ansi_codes(foreground: true) ⇒ Array<String>

Get ANSI escape codes for this color

Parameters:

  • foreground (Boolean) (defaults to: true)

    True for foreground, false for background

Returns:

  • (Array<String>)

    ANSI code components



384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/rich/color.rb', line 384

def ansi_codes(foreground: true)
  case @type
  when ColorType::DEFAULT
    [foreground ? "39" : "49"]
  when ColorType::STANDARD
    base = foreground ? 30 : 40
    offset = @number < 8 ? @number : (@number - 8 + 60)
    [(base + (@number < 8 ? @number : @number - 8 + 60)).to_s]
  when ColorType::EIGHT_BIT
    [foreground ? "38" : "48", "5", @number.to_s]
  when ColorType::TRUECOLOR
    [foreground ? "38" : "48", "2", @triplet.red.to_s, @triplet.green.to_s, @triplet.blue.to_s]
  when ColorType::WINDOWS
    base = @number < 8 ? (foreground ? 30 : 40) : (foreground ? 90 : 100)
    [(base + @number % 8).to_s]
  else
    []
  end
end

#default?Boolean

Returns True if this is the default color.

Returns:

  • (Boolean)

    True if this is the default color



350
351
352
# File 'lib/rich/color.rb', line 350

def default?
  @type == ColorType::DEFAULT
end

#downgrade(target_system) ⇒ Color

Downgrade color to a simpler color system

Parameters:

  • target_system (Symbol)

    Target color system

Returns:

  • (Color)

    Downgraded color (may be self if no downgrade needed)



407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
# File 'lib/rich/color.rb', line 407

def downgrade(target_system)
  return self if @type == ColorType::DEFAULT
  return self if target_system == system

  cache_key = [@type, @number, @triplet&.to_a, target_system]

  self.class.instance_variable_get(:@downgrade_cache_mutex).synchronize do
    cache = self.class.instance_variable_get(:@downgrade_cache)
    return cache[cache_key] if cache.key?(cache_key)

    result = compute_downgrade(target_system)
    cache[cache_key] = result
    result
  end
end

#get_truecolor(theme: nil, foreground: true) ⇒ ColorTriplet

Get the RGB triplet for this color

Parameters:

  • theme (TerminalTheme, nil) (defaults to: nil)

    Terminal theme for system colors

  • foreground (Boolean) (defaults to: true)

    True for foreground, false for background

Returns:



358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
# File 'lib/rich/color.rb', line 358

def get_truecolor(theme: nil, foreground: true)
  case @type
  when ColorType::TRUECOLOR
    @triplet
  when ColorType::EIGHT_BIT
    Palettes.get_eight_bit(@number)
  when ColorType::STANDARD
    if theme
      theme.ansi_colors[@number]
    else
      Palettes.get_standard(@number)
    end
  when ColorType::WINDOWS
    Palettes.get_windows(@number)
  when ColorType::DEFAULT
    if theme
      foreground ? theme.foreground : theme.background
    else
      foreground ? ColorTriplet.new(255, 255, 255) : ColorTriplet.new(0, 0, 0)
    end
  end
end

#hashObject



432
433
434
# File 'lib/rich/color.rb', line 432

def hash
  [@type, @number, @triplet].hash
end

#inspectObject



440
441
442
443
444
445
446
447
448
449
# File 'lib/rich/color.rb', line 440

def inspect
  case @type
  when ColorType::DEFAULT
    "#<Rich::Color default>"
  when ColorType::TRUECOLOR
    "#<Rich::Color #{@name} (#{@triplet.hex})>"
  else
    "#<Rich::Color #{@name} (#{@type}:#{@number})>"
  end
end

#systemSymbol

Returns Native color system for this color.

Returns:

  • (Symbol)

    Native color system for this color



329
330
331
332
333
334
335
336
337
338
339
340
341
342
# File 'lib/rich/color.rb', line 329

def system
  case @type
  when ColorType::DEFAULT
    ColorSystem::STANDARD
  when ColorType::STANDARD
    ColorSystem::STANDARD
  when ColorType::EIGHT_BIT
    ColorSystem::EIGHT_BIT
  when ColorType::TRUECOLOR
    ColorSystem::TRUECOLOR
  when ColorType::WINDOWS
    ColorSystem::WINDOWS
  end
end

#system_defined?Boolean

Returns True if color is system-defined (may vary by terminal).

Returns:

  • (Boolean)

    True if color is system-defined (may vary by terminal)



345
346
347
# File 'lib/rich/color.rb', line 345

def system_defined?
  [ColorType::DEFAULT, ColorType::STANDARD].include?(@type)
end

#to_sObject



436
437
438
# File 'lib/rich/color.rb', line 436

def to_s
  @name
end