class Eclair::Grid
Attributes
mode[R]
Public Class Methods
new(keyword = "")
click to toggle source
# File lib/eclair/grid.rb, line 9 def initialize keyword = "" case config.provider when :ec2 require "eclair/providers/ec2" @provider = EC2Provider when :k8s require "eclair/providers/k8s" @provider = K8sProvider when :gce require "eclair/providers/gce" @provider = GCEProvider end @item_class = @provider.item_class @scroll = config.columns.times.map{0} @header_rows = 4 @cursor = [0,0] @cell_width = Curses.stdscr.maxx/config.columns @maxy = Curses.stdscr.maxy - @header_rows @mode = :assign @search_buffer = "" @provider.prepare keyword assign at(*@cursor).select(true) draw_all transit_mode(:nav) end
Public Instance Methods
action()
click to toggle source
# File lib/eclair/grid.rb, line 83 def action targets = @provider.items.select{|i| i.selected && i.connectable?} return if targets.empty? Curses.close_screen if targets.length == 1 cmd = targets.first.command else cmds = [] target_cmd = "" targets.each_with_index do |target, i| if i == 0 if ENV['TMUX'] # Eclair called inside of tmux # Create new session and save window id window_name = `tmux new-window -P -- '#{target.command}'`.strip target_cmd = "-t #{window_name}" else # Eclair called from outside of tmux # Create new session and save session session_name = "eclair#{Time.now.to_i}" target_cmd = "-t #{session_name}" `tmux new-session -d -s #{session_name} -- '#{target.command}'` end else # Split layout and cmds << "split-window #{target_cmd} -- '#{target.command}'" cmds << "select-layout #{target_cmd} tiled" end end cmds << "set-window-option #{target_cmd} synchronize-panes on" cmds << "attach #{target_cmd}" unless ENV['TMUX'] cmd = "tmux #{cmds.join(" \\; ")}" end system(cmd) exit() resize end
append_search(key)
click to toggle source
# File lib/eclair/grid.rb, line 172 def append_search key return unless key if @search_buffer.length > 0 && (key == 127 || key == Curses::KEY_BACKSPACE || key == 8) #backspace @search_buffer = @search_buffer.chop elsif key.to_s.length == 1 begin @search_buffer = @search_buffer + key.to_s rescue return end else return end update_search end
clear_search()
click to toggle source
# File lib/eclair/grid.rb, line 167 def clear_search @search_buffer = "" update_search end
end_search()
click to toggle source
# File lib/eclair/grid.rb, line 159 def end_search if @provider.items.any?{|i| i.selected} transit_mode(:sel) else transit_mode(:nav) end end
move(key)
click to toggle source
# File lib/eclair/grid.rb, line 38 def move key return unless at(*@cursor) x,y = @cursor mx,my = { Curses::KEY_UP => [0,-1], ?k => [0,-1], Curses::KEY_DOWN => [0,1], ?j => [0,1], Curses::KEY_LEFT => [-1,0], ?h => [-1,0], Curses::KEY_RIGHT => [1,0], ?l => [1,0], }[key] newx = x loop do newx = (newx + mx) % @grid.length break if @grid[newx].length > 0 end newy = (y + my - @scroll[x] + @scroll[newx]) if my != 0 newy %= @grid[newx].length end if newy >= @grid[newx].length newy = @grid[newx].length-1 end move_cursor(newx, newy) end
resize()
click to toggle source
# File lib/eclair/grid.rb, line 121 def resize Curses.clear @scroll.fill(0) @cell_width = Curses.stdscr.maxx/config.columns @maxy = Curses.stdscr.maxy - @header_rows rescroll(*@cursor) draw_all end
space()
click to toggle source
# File lib/eclair/grid.rb, line 68 def space if @mode == :nav transit_mode(:sel) end at(*@cursor)&.toggle_select if @mode == :sel && @provider.items.all?{|i| !i.selected} transit_mode(:nav) end draw(*@cursor) end
start_search()
click to toggle source
# File lib/eclair/grid.rb, line 155 def start_search transit_mode(:search) end
transit_mode(to)
click to toggle source
# File lib/eclair/grid.rb, line 130 def transit_mode to return if to == @mode case @mode when :nav at(*@cursor)&.select(false) when :sel when :search when :assign end @mode = to case @mode when :nav at(*@cursor)&.select(true) when :sel when :search when :assign move_cursor(0,0) end draw_all end
Private Instance Methods
assign()
click to toggle source
# File lib/eclair/grid.rb, line 302 def assign old_mode = @mode transit_mode(:assign) @grid = config.columns.times.map{[]} visible_items = @provider.filter_items(@search_buffer) @groups = visible_items.group_by(&config.group_by) @groups.each do |name, items| group_name = "#{name} (#{items.length})" target = @grid.min_by(&:length) target << @provider.group_class.new(group_name, items) items.sort_by(&:label).each do |item| target << item end end transit_mode(old_mode) end
at(x, y)
click to toggle source
# File lib/eclair/grid.rb, line 247 def at x, y @grid[x][y] end
color(x, y)
click to toggle source
# File lib/eclair/grid.rb, line 269 def color x, y if @cursor == [x,y] Color.fetch(Curses::COLOR_BLACK, Curses::COLOR_CYAN) else Color.fetch(*@grid[x][y].color) end end
config()
click to toggle source
# File lib/eclair/grid.rb, line 319 def config Eclair.config end
draw(x, y)
click to toggle source
# File lib/eclair/grid.rb, line 292 def draw x, y target = @grid[x][y] draw_item(x, y) if target.is_a?(GroupItem) (y+1).upto(y+target.length).each do |ny| draw_item(x, ny) end end end
draw_all()
click to toggle source
# File lib/eclair/grid.rb, line 257 def draw_all @grid.each_with_index do |column, x| column.each_with_index do |_, y| draw_item(x,y) end end case @mode when :nav, :sel update_header(at(*@cursor)&.header || "No Match") end end
draw_item(x, y)
click to toggle source
# File lib/eclair/grid.rb, line 277 def draw_item x, y target = @grid[x].select{|item| item.visible}[y] drawy = y - @scroll[x] if drawy < 0 || drawy + @header_rows >= Curses.stdscr.maxy return end cell_color = color(x,y) Curses.setpos(drawy + @header_rows, x * @cell_width) Curses.attron(cell_color) do Curses.addstr make_label(target) end Curses.refresh end
make_label(target)
click to toggle source
# File lib/eclair/grid.rb, line 251 def make_label target ind = (@mode != :nav && target.selected) ? "*" : " " label = "#{target.label} #{ind}" label.slice(0, @cell_width).ljust(@cell_width) end
move_cursor(x, y)
click to toggle source
# File lib/eclair/grid.rb, line 192 def move_cursor x, y prev = @cursor.dup @cursor = [x, y] prev_item = at(*prev) curr_item = at(*@cursor) rescroll(*@cursor) if @mode == :nav prev_item.select(false) curr_item.select(true) end draw(*prev) if prev_item draw(*@cursor) if curr_item update_header(curr_item.header) if curr_item end
rescroll(x, y)
click to toggle source
# File lib/eclair/grid.rb, line 234 def rescroll x, y unless (@scroll[x]...@maxy+@scroll[x]).include? y if y < @scroll[x] @scroll[x] = y elsif y >= @maxy @scroll[x] = y - @maxy + 1 end (@scroll[x]...@maxy+@scroll[x]).each do |ty| draw_item(x, ty) end end end
update_header(str, pos = 0)
click to toggle source
# File lib/eclair/grid.rb, line 209 def update_header str, pos = 0 Curses.setpos(0, 0) Curses.clrtoeol Curses.addstr(@mode.to_s) str.split("\n").map(&:strip).each_with_index do |line, i| Curses.setpos(i + pos + 1, 0) Curses.clrtoeol Curses.addstr(line) end end
update_search()
click to toggle source
# File lib/eclair/grid.rb, line 220 def update_search assign Curses.clear draw_all Curses.setpos(@header_rows - 1, 0) Curses.clrtoeol if @mode != :search && @search_buffer.empty? update_header('/: Start search') else update_header("/#{@search_buffer}") end end