#!/usr/bin/env ruby
-require "time"
require "ncurses"
-require "inifile"
-require "open3"
-require 'optparse'
-require 'ostruct'
+require_relative 'ini_read'
+require_relative 'windows'
+require_relative 'buffer'
-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 OptParse
- def parse(args)
-
- options = OpenStruct.new()
- options.inifile = nil
-
- opt_parser = OptionParser.new() do |opts|
-
- opts.banner = "Usage: monitor [options]"
- opts.separator ""
-
- opts.on( '-f', "-f ini_file", "chose a different initialization file") do |ini|
- options.inifile = ini
- end
- end
- opt_parser.parse!(args)
- return options
- end
-end
-
-class List_Win
- def initialize(inifile)
- @params = inifile
- @win = Ncurses::WINDOW.new(0, Ncurses.COLS()/4, 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 do |section|
- if(@entry == i)
- @win.attron(Ncurses::A_REVERSE)
- end
- @win.move(i+1,1)
- print_line(@win,@params[section]['Name'])
- if(@entry == i)
- @win.attroff(Ncurses::A_REVERSE)
- end
- i = i+1
- end
- @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
- print_line(@win,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
-
-class Buffer
- def initialize(size)
- @size = size
- @buff = []
- @buff_type = []
- @current = 0
- @wrap = false
- @before = false
- @after = false
- end
- def size()
- return @buff.length
- end
- def maxlen()
- maxlen = 0
- @buff.each do |string|
- if string.length > maxlen
- maxlen = string.length
- end
- end
- return maxlen
- end
-
- def push(string,type=0)
- if(string.chomp.empty?) then string = " " end
- string.split( /\r?\n/ ).each do |line|
- @buff[@current] = line
- @buff_type[@current] = type
- if(@size > 0)
- @current = (1+@current) % @size
- else
- @current = 1+@current
- end
- if(@current == 0) then @wrap = true end
- end
- end
- def yield(size,offset=0,&block)
- if(size < 0) then size = 0 end
- range = Range.new(0,@current-1).to_a
- if(@wrap)
- range = Range.new(@current,@size-1).to_a + range
- end
- range = range.last(size+offset)[0,size]
- @before = (size+offset < @buff.length)
- @after = (offset != 0 and size < @buff.length)
- if(block)
- range.each do |i|
- yield [@buff[i],@buff_type[i]]
- end
- else
- return range.collect{|r| [@buff[r],@buff_type[r]]}
- end
- end
- def has_after?()
- return @after
- end
- def has_before?()
- return @before
- end
- def clear()
- @current = 0
- @buff = []
- @buff_type = []
- end
-end
-
-def find_ini(option_inifile)
- if(not option_inifile.nil?)
- inifile = option_inifile
- elsif(ENV.has_key?('MONITOR_RC'))
- inifile = ENV['MONITOR_RC']
- elsif(Process.uid == 0)
- inifile = "/etc/monitor.rc"
- else
- inifile = ENV['HOME']+"/.monitorrc"
- end
- return inifile
-end
-
-def read_ini(ini)
- inifile = IniFile.load(ini)
- if(inifile.nil?)
- puts "Initialization file not found or not readable"
- exit
- end
- return inifile
-end
-
-def print_line(win, 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)
- win.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 = win.getmaxx-win.getcurx-1
- if(strlen <= winlen)
- win.addstr(str + " "*(winlen-strlen))
- else
- win.addstr(str[0,winlen-1]+"…")
- end
- if(revert_color)
- win.attroff(Ncurses.COLOR_PAIR(10))
- end
-end
-
-def make_bufwins(inifile)
+def make_bufwins(sections,size)
bufwins = []
- inifile.each_section do |section|
- bufwin = Buff_Win.new(Ncurses.COLS()-Ncurses.COLS()/4,
- Ncurses.COLS()/4,
- inifile[section])
+ sections.each { |section_name,section|
+ bufwin = Buff_Win.new(Ncurses.COLS()-size*Ncurses.COLS()/100,
+ size*Ncurses.COLS()/100,
+ section)
bufwins.push(bufwin)
- end
+ }
return bufwins
end
end
end
-def redraw_all(list,bufwins,curr_bufwin)
+def redraw_all(list,bufwins,curr_bufwin, size)
bufwins.each do |bufwin|
- bufwin.move_resize(Ncurses.COLS()-Ncurses.COLS()/4,Ncurses.COLS()/4)
+ bufwin.move_resize(Ncurses.COLS()-size*Ncurses.COLS()/100,size*Ncurses.COLS()/100)
end
- list.resize(Ncurses.LINES(), Ncurses.COLS()/4)
+ list.resize(Ncurses.LINES(), size*Ncurses.COLS()/100)
list.clear()
list.print_list()
list.refresh()
end
-options = OptParse.new().parse(ARGV)
-inifile = read_ini(find_ini(options.inifile))
+inistruct = Ini_read.new()
begin
# initialize ncurses
Ncurses.initscr
Ncurses.init_pair(10, Ncurses::COLOR_WHITE, Ncurses::COLOR_BLACK)
- list = List_Win.new(inifile)
- bufwins = make_bufwins(inifile)
+ list = List_Win.new(inistruct.sections, inistruct.global['list_size'])
+ bufwins = make_bufwins(inistruct.sections, inistruct.global['list_size'])
entry = 0
cur_bufwin = bufwins[entry]
cur_bufwin.show_win()
cur_bufwin.show_win()
list.print_list(entry=entry)
when 12 #ctrl+L
- redraw_all(list,bufwins,cur_bufwin)
+ redraw_all(list,bufwins,cur_bufwin, inistruct.global['list_size'])
when 18 #ctrl+R
cur_bufwin.update(force=true)
when Ncurses::KEY_RESIZE
- redraw_all(list,bufwins,cur_bufwin)
+ redraw_all(list,bufwins,cur_bufwin, inistruct.global['list_size'])
when Ncurses::KEY_LEFT
cur_bufwin.hscroll(scroll=-1)
when Ncurses::KEY_RIGHT