require 'ncurses' module CLI @@mev = nil extend self def self.keytable(key) case key when 12 '' when ?\n '' when ?\b, Ncurses::KEY_BACKSPACE, 127 '' when Ncurses::KEY_RIGHT '' when Ncurses::KEY_LEFT '' when Ncurses::KEY_UP '' when Ncurses::KEY_DOWN '' when ?\e '' when Ncurses::KEY_BTAB '' when 9 '' when 1..26 # CTRL + ... "" when 32..127 key.chr when Ncurses::KEY_MOUSE fetch_mouse_data '' else '' end end def fetch_mouse_data @@mev = MouseEvent.new Ncurses::getmouse(@@mev) end def mouse @@mev end def self.included(this) @@window = Ncurses.initscr starti end # (Re)Start the Interface def starti @@running = true @@screen = Ncurses.stdscr @@screen.keypad(true) Ncurses.start_color Ncurses.use_default_colors Ncurses.noecho Ncurses.curs_set 0 Ncurses.halfdelay(200) @@colortable = [] end MOUSE_MASK_ON = Ncurses::ALL_MOUSE_EVENTS | Ncurses::REPORT_MOUSE_POSITION MOUSE_MASK_OFF = 0 def init_mouse Ncurses.mouseinterval( 0 ) Ncurses.mousemask( MOUSE_MASK_ON, [] ) end def stop_mouse Ncurses.mousemask( MOUSE_MASK_OFF, [] ) end def self.refresh Ncurses.refresh end # Close the Interface def closei @@running = false Ncurses.echo Ncurses.nocbreak Ncurses.curs_set 1 Ncurses.endwin end def running?() @@running end def cleari Ncurses.mvaddstr(0, 0, ' ' * (lines * cols)) end def geti CLI.keytable(Ncurses.getch) end def set_title(x) print "\e]2;#{x}\007" end def lines Ncurses.LINES end def cols Ncurses.COLS end def movi(y=0, x=0) y < 0 and y += lines Ncurses.move(y, x) end def puti *args case args.size when 1 Ncurses.addstr(args[0].to_s) when 2 if (y = args[0]) < 0 then y += Ncurses.LINES end Ncurses.mvaddstr(y, 0, args[1].to_s) when 3 if (y = args[0]) < 0 then y += Ncurses.LINES end Ncurses.mvaddstr(y, args[1], args[2].to_s) end end def attr_set(fg=-1, bg=-1, attr = nil) fg, bg, attr = fg if fg.is_a? Array if attr Ncurses.attrset(attr | Ncurses.COLOR_PAIR(get_color(fg, bg))) else Ncurses.color_set(get_color(fg, bg), nil) end end def attr_at(y=0, x=0, len=-1, fg=-1, bg=-1, attr=0) fg, bg, attr = fg if fg.is_a? Array y += lines if y < 0 x += cols if x < 0 attr ||= 0 Ncurses.mvchgat(y, x, len, attr, get_color(fg, bg), nil) end def get_color(fg, bg) n = bg+2 + 9*(fg+2) color = @@colortable[n] unless color # create a new pair size = @@colortable.reject{|x| x.nil? }.size + 1 Ncurses::init_pair(size, fg, bg) color = @@colortable[n] = size end return color end class MouseEvent # {{{ attr_accessor :id, :x,:y,:z, :bstate def press1?() 0 != @bstate & Ncurses::BUTTON1_PRESSED end def press2?() 0 != @bstate & Ncurses::BUTTON2_PRESSED end def press3?() 0 != @bstate & Ncurses::BUTTON3_PRESSED end def press4?() 0 != @bstate & Ncurses::BUTTON4_PRESSED end ## this does not work. BUTTON5_* is not defined def press5?() 0 != @bstate & Ncurses::BUTTON5_PRESSED end ## this is an EVIL fix but I don't know better def press5?() 0 != ( @bstate & 128 ) + ( @bstate & 134217728 ) end def release1?() 0 != @bstate & Ncurses::BUTTON1_RELEASED end def release2?() 0 != @bstate & Ncurses::BUTTON2_RELEASED end def release3?() 0 != @bstate & Ncurses::BUTTON3_RELEASED end def release4?() 0 != @bstate & Ncurses::BUTTON4_RELEASED end # def release5?() 0 != @bstate & Ncurses::BUTTON5_RELEASED end def click1?() 0 != @bstate & Ncurses::BUTTON1_CLICKED end def click2?() 0 != @bstate & Ncurses::BUTTON2_CLICKED end def click3?() 0 != @bstate & Ncurses::BUTTON3_CLICKED end def click4?() 0 != @bstate & Ncurses::BUTTON4_CLICKED end # def click5?() 0 != @bstate & Ncurses::BUTTON5_CLICKED end def doubleclick1?() 0 != @bstate & Ncurses::BUTTON1_DOUBLE_CLICKED end def doubleclick2?() 0 != @bstate & Ncurses::BUTTON2_DOUBLE_CLICKED end def doubleclick3?() 0 != @bstate & Ncurses::BUTTON3_DOUBLE_CLICKED end def doubleclick4?() 0 != @bstate & Ncurses::BUTTON4_DOUBLE_CLICKED end # def doubleclick5?() 0 != @bstate & Ncurses::BUTTON5_DOUBLE_CLICKED end def tripleclick1?() 0 != @bstate & Ncurses::BUTTON1_TRIPLE_CLICKED end def tripleclick2?() 0 != @bstate & Ncurses::BUTTON2_TRIPLE_CLICKED end def tripleclick3?() 0 != @bstate & Ncurses::BUTTON3_TRIPLE_CLICKED end def tripleclick4?() 0 != @bstate & Ncurses::BUTTON4_TRIPLE_CLICKED end # def tripleclick5?() 0 != @bstate & Ncurses::BUTTON5_TRIPLE_CLICKED end def alt?() 0 != @bstate & Ncurses::BUTTON_ALT end def shift?() 0 != @bstate & Ncurses::BUTTON_SHIFT end def ctrl?() 0 != @bstate & Ncurses::BUTTON_CTRL end ## too many keys {{{ # def press6?() 0 != @bstate & Ncurses::BUTTON6_PRESSED end # def press7?() 0 != @bstate & Ncurses::BUTTON7_PRESSED end # def press8?() 0 != @bstate & Ncurses::BUTTON8_PRESSED end # def press9?() 0 != @bstate & Ncurses::BUTTON9_PRESSED end # def release6?() 0 != @bstate & Ncurses::BUTTON6_RELEASED end # def release7?() 0 != @bstate & Ncurses::BUTTON7_RELEASED end # def release8?() 0 != @bstate & Ncurses::BUTTON8_RELEASED end # def release9?() 0 != @bstate & Ncurses::BUTTON9_RELEASED end # def click6?() 0 != @bstate & Ncurses::BUTTON6_CLICKED end # def click7?() 0 != @bstate & Ncurses::BUTTON7_CLICKED end # def click8?() 0 != @bstate & Ncurses::BUTTON8_CLICKED end # def click9?() 0 != @bstate & Ncurses::BUTTON9_CLICKED end # def doubleclick6?() 0 != @bstate & Ncurses::BUTTON6_DOUBLE_CLICKED end # def doubleclick7?() 0 != @bstate & Ncurses::BUTTON7_DOUBLE_CLICKED end # def doubleclick8?() 0 != @bstate & Ncurses::BUTTON8_DOUBLE_CLICKED end # def doubleclick9?() 0 != @bstate & Ncurses::BUTTON9_DOUBLE_CLICKED end # def tripleclick6?() 0 != @bstate & Ncurses::BUTTON6_TRIPLE_CLICKED end # def tripleclick7?() 0 != @bstate & Ncurses::BUTTON7_TRIPLE_CLICKED end # def tripleclick8?() 0 != @bstate & Ncurses::BUTTON8_TRIPLE_CLICKED end # def tripleclick9?() 0 != @bstate & Ncurses::BUTTON9_TRIPLE_CLICKED end # }}} end # }}} end