Class: Hansi::ColorParser

Inherits:
Object
  • Object
show all
Defined in:
lib/hansi/color_parser.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeColorParser

Returns a new instance of ColorParser.


11
12
13
# File 'lib/hansi/color_parser.rb', line 11

def initialize
  @cache = {}
end

Class Method Details

.parse(*values) ⇒ Object


6
7
8
9
# File 'lib/hansi/color_parser.rb', line 6

def self.parse(*values)
  @parser ||= new
  @parser.parse(values)
end

Instance Method Details

#illegal(value) ⇒ Object

Raises:

  • (IllegalValue)

89
90
91
# File 'lib/hansi/color_parser.rb', line 89

def illegal(value)
  raise IllegalValue, 'illegal color value %p' % value
end

#parse(values, potentially_illegal: nil) ⇒ Object


15
16
17
# File 'lib/hansi/color_parser.rb', line 15

def parse(values, potentially_illegal: nil)
  @cache[values] ||= parse_values(values, potentially_illegal)
end

#parse_ansi(string, potentially_illegal) ⇒ Object


75
76
77
78
79
80
81
# File 'lib/hansi/color_parser.rb', line 75

def parse_ansi(string, potentially_illegal)
  case string
  when /\e\[(?:\d;)?38;2;(\d{1,3});(\d{1,3});(\d{1,3})(?:;\d)?m/ then parse_hash(potentially_illegal, red: $1.to_i, green: $2.to_i, blue: $3.to_i)
  when /\e\[(?:\d;)?38;5;(\d{1,3})(?:;\d)?m/                     then parse_color(PALETTES[ 'xterm-256color' ].fetch("\e[38;5;#{$1.to_i}m") { illegal(potentially_illegal) }, potentially_illegal)
  when /\e\[(?:\d;)?([39]\d)(?:;\d)?m/                           then parse_color(PALETTES[ 'xterm'          ].fetch("\e[#{$1}m")           { illegal(potentially_illegal) }, potentially_illegal)
  end
end

#parse_color(color, potentially_illegal) ⇒ Object


47
48
49
# File 'lib/hansi/color_parser.rb', line 47

def parse_color(color, potentially_illegal)
  [color.red, color.green, color.blue]
end

#parse_float(value, potentially_illegal) ⇒ Object


51
52
53
54
# File 'lib/hansi/color_parser.rb', line 51

def parse_float(value, potentially_illegal)
  value *= 255 if value.between? 0, 1
  parse_integer(value.to_i, potentially_illegal || value)
end

#parse_hash(potentially_illegal, red: 0, green: 0, blue: 0) ⇒ Object


43
44
45
# File 'lib/hansi/color_parser.rb', line 43

def parse_hash(potentially_illegal, red: 0, green: 0, blue: 0)
  [red, green, blue].map { |v| parse_value(v, potentially_illegal) }
end

#parse_integer(value, potentially_illegal) ⇒ Object


56
57
58
59
# File 'lib/hansi/color_parser.rb', line 56

def parse_integer(value, potentially_illegal)
  return value if value.between? 0, 255
  value > 255 ? 255 : 0
end

#parse_string(string, potentially_illegal) ⇒ Object


61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/hansi/color_parser.rb', line 61

def parse_string(string, potentially_illegal)
  return parse_ansi(string, potentially_illegal || string) if string.start_with? ?\e
  return parse_hash(potentially_illegal || string, red: $1.to_i, green: $2.to_i, blue: $3.to_i) if string =~ /^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)$/m
  return parse_symbol(string, potentially_illegal || string) if string !~ /^#?[0-9a-f]+$/
  string = string[1..-1] if string.start_with?(?#)
  case string.size
  when 1 then (string*2).to_i(16)
  when 2 then string.to_i(16)
  when 3 then string.each_char.map { |c| (c*2).to_i(16) }
  when 6 then [string[0,2].to_i(16), string[2,2].to_i(16), string[4,2].to_i(16)]
  else illegal(potentially_illegal || string)
  end
end

#parse_symbol(symbol, potentially_illegal) ⇒ Object


83
84
85
86
87
# File 'lib/hansi/color_parser.rb', line 83

def parse_symbol(symbol, potentially_illegal)
  value = symbol.to_s.downcase.gsub(/[^a-z]/, '').to_sym
  value = PALETTES['special'][value] || PALETTES['web'][value]
  parse_value(value, potentially_illegal || symbol)
end

#parse_value(value, potentially_illegal) ⇒ Object


31
32
33
34
35
36
37
38
39
40
41
# File 'lib/hansi/color_parser.rb', line 31

def parse_value(value, potentially_illegal)
  case value
  when Float    then parse_float(value,   potentially_illegal)
  when Integer  then parse_integer(value, potentially_illegal)
  when String   then parse_string(value,  potentially_illegal)
  when Hash     then parse_hash(potentially_illegal,  **value)
  when Symbol   then parse_symbol(value,  potentially_illegal)
  when AnsiCode then value
  else illegal(potentially_illegal || value)
  end
end

#parse_values(values, potentially_illegal) ⇒ Object


19
20
21
22
23
24
25
26
27
28
29
# File 'lib/hansi/color_parser.rb', line 19

def parse_values(values, potentially_illegal)
  values = values.first while values.size == 1 and values.first.is_a? Array
  values = values.flat_map { |value| parse_value(value, potentially_illegal) }

  if values.size == 1 and values.first.is_a? AnsiCode
    values.first
  else
    values *= 3 if values.size == 1
    Color.new(*values)
  end
end