class Rouge::Formatters::Terminal256::EscapeSequence

Constants

MAX_DISTANCE

max distance between two colors, #000000 to ffffff

Attributes

style[R]

Public Class Methods

new(style) click to toggle source
# File lib/rouge/formatters/terminal256.rb, line 32
def initialize(style)
  @style = style
end
xterm_colors() click to toggle source
# File lib/rouge/formatters/terminal256.rb, line 36
def self.xterm_colors
  @xterm_colors ||= [].tap do |out|
    # colors 0..15: 16 basic colors
    out << [0x00, 0x00, 0x00] # 0
    out << [0xcd, 0x00, 0x00] # 1
    out << [0x00, 0xcd, 0x00] # 2
    out << [0xcd, 0xcd, 0x00] # 3
    out << [0x00, 0x00, 0xee] # 4
    out << [0xcd, 0x00, 0xcd] # 5
    out << [0x00, 0xcd, 0xcd] # 6
    out << [0xe5, 0xe5, 0xe5] # 7
    out << [0x7f, 0x7f, 0x7f] # 8
    out << [0xff, 0x00, 0x00] # 9
    out << [0x00, 0xff, 0x00] # 10
    out << [0xff, 0xff, 0x00] # 11
    out << [0x5c, 0x5c, 0xff] # 12
    out << [0xff, 0x00, 0xff] # 13
    out << [0x00, 0xff, 0xff] # 14
    out << [0xff, 0xff, 0xff] # 15

    # colors 16..232: the 6x6x6 color cube
    valuerange = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]

    217.times do |i|
      r = valuerange[(i / 36) % 6]
      g = valuerange[(i / 6) % 6]
      b = valuerange[i % 6]
      out << [r, g, b]
    end

    # colors 233..253: grayscale
    1.upto 22 do |i|
      v = 8 + i * 10
      out << [v, v, v]
    end
  end
end

Private Class Methods

closest_color(r, g, b) click to toggle source
# File lib/rouge/formatters/terminal256.rb, line 143
def self.closest_color(r, g, b)
  @@colors_cache ||= {}
  key = (r << 16) + (g << 8) + b
  @@colors_cache.fetch(key) do
    distance = MAX_DISTANCE

    match = 0

    xterm_colors.each_with_index do |(cr, cg, cb), i|
      d = (r - cr)**2 + (g - cg)**2 + (b - cb)**2
      next if d >= distance

      match = i
      distance = d
    end

    match
  end
end
color_index(color) click to toggle source
# File lib/rouge/formatters/terminal256.rb, line 121
def self.color_index(color)
  @color_index_cache ||= {}
  @color_index_cache[color] ||= closest_color(*get_rgb(color))
end
get_rgb(color) click to toggle source
# File lib/rouge/formatters/terminal256.rb, line 126
def self.get_rgb(color)
  color = $1 if color =~ /#([0-9a-f]+)/i
  hexes = case color.size
  when 3
    color.chars.map { |c| "#{c}#{c}" }
  when 6
    color.scan(/../)
  else
    raise "invalid color: #{color}"
  end

  hexes.map { |h| h.to_i(16) }
end

Public Instance Methods

bg() click to toggle source
# File lib/rouge/formatters/terminal256.rb, line 79
def bg
  return @bg if instance_variable_defined? :@bg
  @bg = style.bg && self.class.color_index(style.bg)
end
fg() click to toggle source
# File lib/rouge/formatters/terminal256.rb, line 74
def fg
  return @fg if instance_variable_defined? :@fg
  @fg = style.fg && self.class.color_index(style.fg)
end
reset_string() click to toggle source
# File lib/rouge/formatters/terminal256.rb, line 104
def reset_string
  @reset_string ||= begin
    attrs = []
    attrs << '39' if fg # fg reset
    attrs << '49' if bg # bg reset
    attrs << '00' if style[:bold] || style[:italic]

    escape(attrs)
  end
end
stream_value(val) { |style_string| ... } click to toggle source
# File lib/rouge/formatters/terminal256.rb, line 85
def stream_value(val, &b)
  yield style_string
  yield val.gsub("\e", "\\e")
           .gsub("\n", "#{reset_string}\n#{style_string}")
  yield reset_string
end
style_string() click to toggle source
# File lib/rouge/formatters/terminal256.rb, line 92
def style_string
  @style_string ||= begin
    attrs = []

    attrs << ['38', '5', fg.to_s] if fg
    attrs << ['48', '5', bg.to_s] if bg
    attrs << '01' if style[:bold]
    attrs << '04' if style[:italic] # underline, but hey, whatevs
    escape(attrs)
  end
end

Private Instance Methods

escape(attrs) click to toggle source
# File lib/rouge/formatters/terminal256.rb, line 116
def escape(attrs)
  return '' if attrs.empty?
  "\e[#{attrs.join(';')}m"
end