aboutsummaryrefslogblamecommitdiff
path: root/windows.rb
blob: 5d195dd3edaa49be7d62d6ef5f7b6939a899ca3a (plain) (tree)




















































                                                                                                         
              
                                
                      
                                                                



























                           
                                         



                                       
                                      



                                        
     
































































































                                                               
                                         































































                                                                       
require "time"
require "open3"

class IO
    def readline_nonblock
      buffer = ""
      buffer << read_nonblock(1) while buffer[-1] != "\n"
      buffer
    rescue IO::WaitReadable => blocking
      if (not buffer.empty?)
        ungetc(buffer)
      end
      raise blocking
    end
end


class Ncurses::WINDOW
  def print_line(str, hscroll=0)
    revert_color = false
    str[0,5].match(/\033\[3(.)m/) { |c| #Line starts with an escape sequence. We handle that `a la xterm`
      Ncurses.init_pair(10, c[1].to_i,   Ncurses::COLOR_BLACK)
      self.attron(Ncurses.COLOR_PAIR(10))
      revert_color = true
      str = str[5,str.length]
    }
    str = str.gsub("\011","    ")
    #Any other control char is ignored and escaped
    str = str.gsub(/[[:cntrl:]]/) { |m|
      "^"+(m.ord + 64).chr
    }
    if(hscroll > 0)
      strcut = str[hscroll,str.length]
      if(strcut.nil? or strcut.empty?)
        str = ""
      else
        str = "…"+strcut
      end
    end
    strlen = str.length
    winlen = self.getmaxx-self.getcurx-1
    if(strlen <= winlen)
      self.addstr(str + " "*(winlen-strlen))
    else
      self.addstr(str[0,winlen-1]+"…")
    end
    if(revert_color)
      self.attroff(Ncurses.COLOR_PAIR(10))
    end
  end
end


class List_Win
  def initialize(sections, size)
    @params = sections
    @win = Ncurses::WINDOW.new(0, size*Ncurses.COLS()/100, 0, 0)
    @win.border(*([0]*8))
    @win.keypad(true)
    @win.timeout(1000)
    @win.refresh()
    @entry = 0
  end

  def getch()
    @win.getch()
  end
  def clear()
    @win.clear()
  end
  def resize(x,y)
    @win.resize(x,y)
  end
  def move(x,y)
    @win.move(x,y)
  end
  def refresh()
    @win.refresh()
  end

  def print_list(entry=nil)
    if(not entry.nil?)
      @entry = entry
    end
    i = 0
    @params.each { |section_name,section|
      if(@entry == i)
        @win.attron(Ncurses::A_REVERSE)
      end
      @win.move(i+1,1)
      @win.print_line(section['Name'])
      if(@entry == i)
        @win.attroff(Ncurses::A_REVERSE)
      end
      i = i+1
    }
    @win.border(*([0]*8))
    @win.move(0,3)
    @win.addstr("Menu")
    @win.refresh()
  end
end

class Buff_Win
  def initialize(winsize,winpos,params)
    @params = params
    @win = Ncurses::WINDOW.new(0, winsize, 0, winpos)
    @panel = Ncurses::Panel::PANEL.new(@win)
    if(@params['Type'] == 'oneshot')
      @buffer = Buffer.new(0)
    else
      @buffer = Buffer.new(@params['Buffer'].to_i)
    end
    @proc = nil
    @curr_offset = 0
    @hscroll = 0
    update_date()

    spawn_proc()
    print_buffer()
  end

  def move_resize(winsize,winpos)
    newwin = Ncurses::WINDOW.new(0, winsize, 0, winpos)
    Ncurses::Panel.replace_panel(@panel, newwin)
    Ncurses.delwin(@win)
    @win = newwin
    print_buffer()
  end
  def update_date()
    @last_update = Time.now
    @date = @last_update.strftime("%F %R:%S")
  end

  def win_border()
    @win.border(*([0]*8))
    win_header()
  end
  def win_header()
    @win.move(0,3)
    @win.addnstr(@params['Name'],@win.getmaxx-@date.length-10)
    @win.move(0,@win.getmaxx-@date.length-2)
    @win.addstr(@date)
  end
  def refresh()
    @win.refresh()
  end
  def clear()
    @win.clear()
  end

  def show_win()
    Ncurses::Panel.top_panel(@panel)
    Ncurses::Panel.update_panels
  end

  def hscroll(scroll=0)
    @hscroll += scroll
    if(@hscroll < 0)
      @hscroll = 0
    end
    if(@hscroll > @buffer.maxlen()-@win.getmaxx+3)
      @hscroll = @buffer.maxlen()-@win.getmaxx+3
    end
    print_buffer()
    refresh()
  end
  def scroll(scroll=0,goto=nil,fact=nil)
    if (not fact.nil?)
      scroll = (fact * @win.getmaxy.to_f).to_i
    elsif (not goto.nil?)
      @curr_offset = (goto * @buffer.size()).to_i
      scroll = 0
    end
    #@curr_offset -= @win.getmaxy/2
    @curr_offset += scroll
    if(@curr_offset < 0)
      @curr_offset = 0
    end
    if(@curr_offset > @buffer.size()-@win.getmaxy+2)
      @curr_offset = @buffer.size()-@win.getmaxy+2
    end
    print_buffer()
    refresh()
  end

  def print_buffer()
    #clear()
    win_border()
    j = 1
    @buffer.yield(@win.getmaxy-2,@curr_offset) { |l,type|
      @win.move(j,1)
      if(type == 1) then @win.attron(Ncurses.COLOR_PAIR(1)) end
      @win.print_line(l,hscroll=@hscroll)
      if(type == 1) then @win.attroff(Ncurses.COLOR_PAIR(1)) end
      j = j+1
    }
    if(@buffer.has_before?)
      @win.move(2,@win.getmaxx-1)
      @win.attron(Ncurses::A_REVERSE)
      @win.addstr("↑")
      @win.attroff(Ncurses::A_REVERSE)
    end
    if(@buffer.has_after?)
      @win.move(@win.getmaxy-2,@win.getmaxx-1)
      @win.attron(Ncurses::A_REVERSE)
      @win.addstr("↓")
      @win.attroff(Ncurses::A_REVERSE)
    end
  end

  def proc_readlines()
    begin
      while true
        @buffer.push(@proc.readline_nonblock)
        update_date()
      end
    rescue IO::WaitReadable
    end
  end

  def update(force=false)
    if(@params['Type'] == 'continuous')
      proc_readlines()
    end
    if(@params['Type'] == 'oneshot')
      if(force or (Time.now - @last_update > @params['Periodic'].to_i))
        @buffer.clear()
        spawn_proc()
        clear()
      end
    end
    print_buffer()
  end

  def spawn_proc()
    if(@params['Type'] == 'oneshot')
      update_date()
      Open3.popen3(@params["Command"]) { |i,o,e,t|
        while ((not o.eof?) or (not e.eof?))
          rs = IO.select([o,e],nil)[0]
          r = (rs[0].eof?)? rs[1] : rs[0]

          if r.fileno == o.fileno
            @buffer.push(r.readline)
          elsif r.fileno == e.fileno
            @buffer.push(r.readline,type=1)
          end
        end
      }
    elsif(@params['Type'] == 'continuous')
      @proc = IO.popen(@params["Command"])
      proc_readlines()
    end
  end
end