#!/usr/bin/env ruby # -*- encoding: utf-8 -*- # Copyright Steffi Dorn , 2017 # License: GNU GPLv3 (or later) module Kernel def clear_screen print "\e[H\e[2J" end def clear_tmux_history system "tmux", "clear-history" end end class Panes class Section attr_reader :lines attr_accessor :divider def initialize @lines = [] @divider = nil end def <<(line) ; @lines << line ; end def size ; @lines.size ; end def empty? ; @lines.empty? ; end end attr_reader :width, :height, :columns attr_reader :column_width, :column_height attr_reader :remaining_columns, :remaining_lines attr_reader :sections def initialize columns: 2, separator: "|", divider: "=" # can't be bigger than the terminal @width, @height = HighLine::SystemExtensions.terminal_size @separator = separator @divider = divider seps = (columns-1) * separator.size @columns = columns @column_width = @width / columns - seps @column_height = @height @sections = [] # keep track of drawing positions @used_lines = 0 @need_divider = false end def last_section @sections << Section.new if @sections.empty? @sections.last end def new_section @sections << Section.new unless last_section.empty? @sections.last end def total_lines ; @height * @columns ; end def remaining_lines ; [total_lines - @used_lines, 0].max ; end def remaining_lines_on_column ; remaining_lines <= 0 ? 0 : (remaining_lines % @column_height) ; end def used_columns ; @used_lines / @height ; end def remaining_columns ; @columns - used_columns ; end def column_full? ; remaining_lines_on_column <= 0 ; end def new_column unless column_full? section [""]* remaining_lines_on_column last_section.divider = false last_section.lines << "" end end def section *lines, max: :all, tail: false, header: false lines = [*lines].flatten section = new_section left = remaining_lines_on_column rem = remaining_lines num = case max when :all ; lines.size when :column ; left == 0 ? @column_height : left # when :full_column ; @column_height else ; raise "unknown: #{max}" end num = [num, remaining_lines].min @used_lines += num case when header h = lines.first lines = lines[1..-1] div = h.sub(/^\s+/){|s| @divider*s.size}.sub(/\s+$/){|s| @divider*s.size} section.divider = div + @divider * (@column_width - div.str_length) when @need_divider @used_lines += 1 num -= 1 if max != :all or num >= rem # compensate for the divider section.divider = @divider * @column_width end num = [num, rem].min to_print = tail ? lines.last(num) : lines.first(num) @need_divider = ! column_full? # ap( # height: @height, # total: total_lines, # rem: rem, # left: left, # rem_lines: remaining_lines, # rem_column: remaining_lines_on_column, # lines: lines, # num: num # ) to_print.each do |line| section << line.truncate(@column_width, omission: "⇏") end end def show! output = [] @sections.each do |s| output << s.divider unless s.divider.nil? output += s.lines end # ap w: @width, h: @height, cw: @column_width, ch: @column_height, c: @columns # ap ul: @used_lines, os: output.size # ap output max_row = @column_height - 1 max_col = @columns - 1 clear_screen (0..max_row).each do |row| (0..max_col).each do |col| i = col * @column_height + row out = output[i]&.rstrip || "" print out print " " * (@column_width - out.str_length) print HighLine.color("", :reset) if col < max_col ; print @separator elsif row < max_row ; print "\n" else ; # skip end end end end end