1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
require "curses"
module Blade::Runner
extend self
include Blade::Component
autoload :Tab, "blade/interface/runner/tab"
COLOR_NAMES = %w( white yellow green red )
PADDING = 1
def colors
@colors ||= OpenStruct.new.tap do |colors|
COLOR_NAMES.each do |name|
const = Curses.const_get("COLOR_#{name.upcase}")
Curses.init_pair(const, const, Curses::COLOR_BLACK)
colors[name] = Curses.color_pair(const)
end
end
end
def create_window(options = {})
height = options[:height] || 0
width = options[:width] || 0
top = options[:top] || 0
left = options[:left] || PADDING
parent = options[:parent] || Curses.stdscr
parent.subwin(height, width, top, left)
end
def start
run
Blade::Assets.watch_logical_paths
end
def stop
Curses.close_screen
end
def run
start_screen
init_windows
handle_keys
handle_stale_tabs
Blade.subscribe("/results") do |details|
session = Blade::Session.find(details[:session_id])
unless tab = Tab.find(session.id)
tab = Tab.create(id: session.id)
tab.activate if Tab.size == 1
end
tab.draw
Curses.doupdate
end
end
private
def start_screen
Curses.init_screen
Curses.start_color
Curses.noecho
Curses.curs_set(0)
Curses.stdscr.keypad(true)
end
def init_windows
header_window = create_window(height: 3)
header_window.attron(Curses::A_BOLD)
header_window.addstr "BLADE RUNNER [press 'q' to quit]\n"
header_window.attroff(Curses::A_BOLD)
header_window.addstr "Open #{Blade.url} to start"
header_window.noutrefresh
Tab.install(top: header_window.maxy)
Curses.doupdate
end
def handle_keys
EM.defer do
while ch = Curses.getch
case ch
when Curses::KEY_LEFT
Tab.active.try(:activate_previous)
Curses.doupdate
when Curses::KEY_RIGHT
Tab.active.try(:activate_next)
Curses.doupdate
when "q"
Blade.stop
end
end
end
end
def handle_stale_tabs
Blade.subscribe("/browsers") do |details|
if details["message"] = "ping"
if tab = Tab.find(details["session_id"])
tab.last_ping_at = Time.now
end
end
end
EM.add_periodic_timer(1) do
Tab.stale.each { |t| remove_tab(t) }
end
end
def remove_tab(tab)
Tab.remove(tab.id)
Curses.doupdate
end
end
|