]>
Commit | Line | Data |
---|---|---|
1 | require "time" | |
2 | require "open3" | |
3 | ||
4 | class IO | |
5 | def readline_nonblock | |
6 | buffer = "" | |
7 | buffer << read_nonblock(1) while buffer[-1] != "\n" | |
8 | buffer | |
9 | rescue IO::WaitReadable => blocking | |
10 | if (not buffer.empty?) | |
11 | ungetc(buffer) | |
12 | end | |
13 | raise blocking | |
14 | end | |
15 | end | |
16 | ||
17 | ||
18 | class Ncurses::WINDOW | |
19 | def print_line(str, hscroll=0) | |
20 | revert_color = false | |
21 | str[0,5].match(/\033\[3(.)m/) { |c| #Line starts with an escape sequence. We handle that `a la xterm` | |
22 | Ncurses.init_pair(10, c[1].to_i, Ncurses::COLOR_BLACK) | |
23 | self.attron(Ncurses.COLOR_PAIR(10)) | |
24 | revert_color = true | |
25 | str = str[5,str.length] | |
26 | } | |
27 | str = str.gsub("\011"," ") | |
28 | #Any other control char is ignored and escaped | |
29 | str = str.gsub(/[[:cntrl:]]/) { |m| | |
30 | "^"+(m.ord + 64).chr | |
31 | } | |
32 | if(hscroll > 0) | |
33 | strcut = str[hscroll,str.length] | |
34 | if(strcut.nil? or strcut.empty?) | |
35 | str = "" | |
36 | else | |
37 | str = "…"+strcut | |
38 | end | |
39 | end | |
40 | strlen = str.length | |
41 | winlen = self.getmaxx-self.getcurx-1 | |
42 | if(strlen <= winlen) | |
43 | self.addstr(str + " "*(winlen-strlen)) | |
44 | else | |
45 | self.addstr(str[0,winlen-1]+"…") | |
46 | end | |
47 | if(revert_color) | |
48 | self.attroff(Ncurses.COLOR_PAIR(10)) | |
49 | end | |
50 | end | |
51 | end | |
52 | ||
53 | ||
54 | class List_Win | |
55 | def initialize(sections) | |
56 | @params = sections | |
57 | @win = Ncurses::WINDOW.new(0, Ncurses.COLS()/4, 0, 0) | |
58 | @win.border(*([0]*8)) | |
59 | @win.keypad(true) | |
60 | @win.timeout(1000) | |
61 | @win.refresh() | |
62 | @entry = 0 | |
63 | end | |
64 | ||
65 | def getch() | |
66 | @win.getch() | |
67 | end | |
68 | def clear() | |
69 | @win.clear() | |
70 | end | |
71 | def resize(x,y) | |
72 | @win.resize(x,y) | |
73 | end | |
74 | def move(x,y) | |
75 | @win.move(x,y) | |
76 | end | |
77 | def refresh() | |
78 | @win.refresh() | |
79 | end | |
80 | ||
81 | def print_list(entry=nil) | |
82 | if(not entry.nil?) | |
83 | @entry = entry | |
84 | end | |
85 | i = 0 | |
86 | @params.each { |section_name,section| | |
87 | if(@entry == i) | |
88 | @win.attron(Ncurses::A_REVERSE) | |
89 | end | |
90 | @win.move(i+1,1) | |
91 | @win.print_line(section['Name']) | |
92 | if(@entry == i) | |
93 | @win.attroff(Ncurses::A_REVERSE) | |
94 | end | |
95 | i = i+1 | |
96 | } | |
97 | @win.border(*([0]*8)) | |
98 | @win.move(0,3) | |
99 | @win.addstr("Menu") | |
100 | @win.refresh() | |
101 | end | |
102 | end | |
103 | ||
104 | class Buff_Win | |
105 | def initialize(winsize,winpos,params) | |
106 | @params = params | |
107 | @win = Ncurses::WINDOW.new(0, winsize, 0, winpos) | |
108 | @panel = Ncurses::Panel::PANEL.new(@win) | |
109 | if(@params['Type'] == 'oneshot') | |
110 | @buffer = Buffer.new(0) | |
111 | else | |
112 | @buffer = Buffer.new(@params['Buffer'].to_i) | |
113 | end | |
114 | @proc = nil | |
115 | @curr_offset = 0 | |
116 | @hscroll = 0 | |
117 | update_date() | |
118 | ||
119 | spawn_proc() | |
120 | print_buffer() | |
121 | end | |
122 | ||
123 | def move_resize(winsize,winpos) | |
124 | newwin = Ncurses::WINDOW.new(0, winsize, 0, winpos) | |
125 | Ncurses::Panel.replace_panel(@panel, newwin) | |
126 | Ncurses.delwin(@win) | |
127 | @win = newwin | |
128 | print_buffer() | |
129 | end | |
130 | def update_date() | |
131 | @last_update = Time.now | |
132 | @date = @last_update.strftime("%F %R:%S") | |
133 | end | |
134 | ||
135 | def win_border() | |
136 | @win.border(*([0]*8)) | |
137 | win_header() | |
138 | end | |
139 | def win_header() | |
140 | @win.move(0,3) | |
141 | @win.addnstr(@params['Name'],@win.getmaxx-@date.length-10) | |
142 | @win.move(0,@win.getmaxx-@date.length-2) | |
143 | @win.addstr(@date) | |
144 | end | |
145 | def refresh() | |
146 | @win.refresh() | |
147 | end | |
148 | def clear() | |
149 | @win.clear() | |
150 | end | |
151 | ||
152 | def show_win() | |
153 | Ncurses::Panel.top_panel(@panel) | |
154 | Ncurses::Panel.update_panels | |
155 | end | |
156 | ||
157 | def hscroll(scroll=0) | |
158 | @hscroll += scroll | |
159 | if(@hscroll < 0) | |
160 | @hscroll = 0 | |
161 | end | |
162 | if(@hscroll > @buffer.maxlen()-@win.getmaxx+3) | |
163 | @hscroll = @buffer.maxlen()-@win.getmaxx+3 | |
164 | end | |
165 | print_buffer() | |
166 | refresh() | |
167 | end | |
168 | def scroll(scroll=0,goto=nil,fact=nil) | |
169 | if (not fact.nil?) | |
170 | scroll = (fact * @win.getmaxy.to_f).to_i | |
171 | elsif (not goto.nil?) | |
172 | @curr_offset = (goto * @buffer.size()).to_i | |
173 | scroll = 0 | |
174 | end | |
175 | #@curr_offset -= @win.getmaxy/2 | |
176 | @curr_offset += scroll | |
177 | if(@curr_offset < 0) | |
178 | @curr_offset = 0 | |
179 | end | |
180 | if(@curr_offset > @buffer.size()-@win.getmaxy+2) | |
181 | @curr_offset = @buffer.size()-@win.getmaxy+2 | |
182 | end | |
183 | print_buffer() | |
184 | refresh() | |
185 | end | |
186 | ||
187 | def print_buffer() | |
188 | #clear() | |
189 | win_border() | |
190 | j = 1 | |
191 | @buffer.yield(@win.getmaxy-2,@curr_offset) { |l,type| | |
192 | @win.move(j,1) | |
193 | if(type == 1) then @win.attron(Ncurses.COLOR_PAIR(1)) end | |
194 | @win.print_line(l,hscroll=@hscroll) | |
195 | if(type == 1) then @win.attroff(Ncurses.COLOR_PAIR(1)) end | |
196 | j = j+1 | |
197 | } | |
198 | if(@buffer.has_before?) | |
199 | @win.move(2,@win.getmaxx-1) | |
200 | @win.attron(Ncurses::A_REVERSE) | |
201 | @win.addstr("↑") | |
202 | @win.attroff(Ncurses::A_REVERSE) | |
203 | end | |
204 | if(@buffer.has_after?) | |
205 | @win.move(@win.getmaxy-2,@win.getmaxx-1) | |
206 | @win.attron(Ncurses::A_REVERSE) | |
207 | @win.addstr("↓") | |
208 | @win.attroff(Ncurses::A_REVERSE) | |
209 | end | |
210 | end | |
211 | ||
212 | def proc_readlines() | |
213 | begin | |
214 | while true | |
215 | @buffer.push(@proc.readline_nonblock) | |
216 | update_date() | |
217 | end | |
218 | rescue IO::WaitReadable | |
219 | end | |
220 | end | |
221 | ||
222 | def update(force=false) | |
223 | if(@params['Type'] == 'continuous') | |
224 | proc_readlines() | |
225 | end | |
226 | if(@params['Type'] == 'oneshot') | |
227 | if(force or (Time.now - @last_update > @params['Periodic'].to_i)) | |
228 | @buffer.clear() | |
229 | spawn_proc() | |
230 | clear() | |
231 | end | |
232 | end | |
233 | print_buffer() | |
234 | end | |
235 | ||
236 | def spawn_proc() | |
237 | if(@params['Type'] == 'oneshot') | |
238 | update_date() | |
239 | Open3.popen3(@params["Command"]) { |i,o,e,t| | |
240 | while ((not o.eof?) or (not e.eof?)) | |
241 | rs = IO.select([o,e],nil)[0] | |
242 | r = (rs[0].eof?)? rs[1] : rs[0] | |
243 | ||
244 | if r.fileno == o.fileno | |
245 | @buffer.push(r.readline) | |
246 | elsif r.fileno == e.fileno | |
247 | @buffer.push(r.readline,type=1) | |
248 | end | |
249 | end | |
250 | } | |
251 | elsif(@params['Type'] == 'continuous') | |
252 | @proc = IO.popen(@params["Command"]) | |
253 | proc_readlines() | |
254 | end | |
255 | end | |
256 | end | |
257 | ||
258 |