lib/ruco/screen.rb in ruco-0.1.14 vs lib/ruco/screen.rb in ruco-0.2.0.beta

- old
+ new

@@ -1,23 +1,29 @@ module Ruco class Screen + @@styles = {} + def initialize(options) @options = options @cache = [] end def self.open(options, &block) new(options).open(&block) end def open(&block) + if $ruco_colors and ENV['TERM'] == 'xterm' + ENV['TERM'] += '-256color' # activate 256 colors + end Curses.noecho # do not show typed chars Curses.nonl # turn off newline translation Curses.stdscr.keypad(true) # enable arrow keys Curses.raw # give us all other keys Curses.stdscr.nodelay = 1 # do not block -> we can use timeouts Curses.init_screen + Curses.start_color if $ruco_colors and Curses.has_colors? yield self ensure Curses.clear # needed to clear the menu/status bar on windows Curses.close_screen end @@ -86,16 +92,64 @@ return if @cache[key] == args # would not change the line -> nothing to do @cache[key] = args # store current line yield # render the line end - STYLES = { - :normal => 0, - :reverse => Curses::A_REVERSE - } - def self.curses_style(style) - return 0 unless style - STYLES[style] or raise("Unknown style #{style.inspect}") + @@styles[style] ||= begin + if $ruco_colors + foreground = $ruco_foreground || '#ffffff' + background = $ruco_background || '#000000' + + foreground, background = if style == :normal + [foreground, background] + elsif style == :reverse + ['#000000', '#ffffff'] + else + # :red or [:red, :blue] + f,b = style + b ||= background + [f,b] + end + + foreground = html_to_terminal_color(foreground) + background = html_to_terminal_color(background) + color_id(foreground, background) + else # no colors + if style == :reverse + Curses::A_REVERSE + else + Curses::A_NORMAL + end + end + end + end + + # create a new color from foreground+background or reuse old + # and return color-id + def self.color_id(foreground, background) + @@color_ids ||= {} + @@color_ids[[foreground, background]] ||= begin + # make a new pair with a unique id + @@max_color_id ||= 0 + id = (@@max_color_id += 1) + unless defined? RSpec # stops normal text-output, do not use in tests + Curses::init_pair(id, foreground, background) + end + Curses.color_pair(id) + end + end + + COLOR_SOURCE_VALUES = 256 + COLOR_TARGET_VALUES = 5 + COLOR_DIVIDE = COLOR_SOURCE_VALUES / COLOR_TARGET_VALUES + TERM_COLOR_BASE = 16 + + def self.html_to_terminal_color(html_color) + return unless html_color + r = (html_color[1..2].to_i(16) / COLOR_DIVIDE) * 36 + g = (html_color[3..4].to_i(16) / COLOR_DIVIDE) * 6 + b = (html_color[5..6].to_i(16) / COLOR_DIVIDE) * 1 + TERM_COLOR_BASE + r + g + b end end end