rbcurse 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. data/CHANGELOG +1570 -0
  2. data/History.txt +6 -0
  3. data/Manifest.txt +54 -0
  4. data/README.txt +304 -0
  5. data/Rakefile +28 -0
  6. data/examples/qdfilechooser.rb +68 -0
  7. data/examples/rfe.rb +853 -0
  8. data/examples/rfe_renderer.rb +69 -0
  9. data/examples/test1.rb +242 -0
  10. data/examples/test2.rb +498 -0
  11. data/examples/testcombo.rb +95 -0
  12. data/examples/testkeypress.rb +61 -0
  13. data/examples/testmenu.rb +105 -0
  14. data/examples/testtable.rb +266 -0
  15. data/examples/testtabp.rb +106 -0
  16. data/examples/testtodo.rb +532 -0
  17. data/examples/viewtodo.rb +512 -0
  18. data/lib/rbcurse/action.rb +31 -0
  19. data/lib/rbcurse/applicationheader.rb +57 -0
  20. data/lib/rbcurse/celleditor.rb +120 -0
  21. data/lib/rbcurse/checkboxcellrenderer.rb +69 -0
  22. data/lib/rbcurse/colormap.rb +133 -0
  23. data/lib/rbcurse/comboboxcellrenderer.rb +45 -0
  24. data/lib/rbcurse/defaultlistselectionmodel.rb +49 -0
  25. data/lib/rbcurse/keylabelprinter.rb +143 -0
  26. data/lib/rbcurse/listcellrenderer.rb +99 -0
  27. data/lib/rbcurse/listkeys.rb +33 -0
  28. data/lib/rbcurse/listscrollable.rb +216 -0
  29. data/lib/rbcurse/listselectable.rb +67 -0
  30. data/lib/rbcurse/mapper.rb +108 -0
  31. data/lib/rbcurse/orderedhash.rb +77 -0
  32. data/lib/rbcurse/rcombo.rb +243 -0
  33. data/lib/rbcurse/rdialogs.rb +183 -0
  34. data/lib/rbcurse/rform.rb +845 -0
  35. data/lib/rbcurse/rinputdataevent.rb +36 -0
  36. data/lib/rbcurse/rlistbox.rb +804 -0
  37. data/lib/rbcurse/rmenu.rb +666 -0
  38. data/lib/rbcurse/rmessagebox.rb +325 -0
  39. data/lib/rbcurse/rpopupmenu.rb +754 -0
  40. data/lib/rbcurse/rtabbedpane.rb +259 -0
  41. data/lib/rbcurse/rtable.rb +1296 -0
  42. data/lib/rbcurse/rtextarea.rb +673 -0
  43. data/lib/rbcurse/rtextview.rb +335 -0
  44. data/lib/rbcurse/rwidget.rb +1731 -0
  45. data/lib/rbcurse/scrollable.rb +301 -0
  46. data/lib/rbcurse/selectable.rb +94 -0
  47. data/lib/rbcurse/table/tablecellrenderer.rb +85 -0
  48. data/lib/rbcurse/table/tabledatecellrenderer.rb +102 -0
  49. data/lib/rbcurse.rb +7 -0
  50. data/lib/ver/keyboard.rb +150 -0
  51. data/lib/ver/keyboard2.rb +170 -0
  52. data/lib/ver/ncurses.rb +102 -0
  53. data/lib/ver/window.rb +369 -0
  54. data/test/test_rbcurse.rb +0 -0
  55. metadata +118 -0
data/examples/rfe.rb ADDED
@@ -0,0 +1,853 @@
1
+ require 'rubygems'
2
+ require 'ncurses'
3
+ require 'logger'
4
+ require 'rbcurse'
5
+ require 'rbcurse/rcombo'
6
+ require 'rbcurse/rlistbox'
7
+ require 'rfe_renderer'
8
+ #require 'lib/rbcurse/table/tablecellrenderer'
9
+ require 'rbcurse/keylabelprinter'
10
+ require 'rbcurse/applicationheader'
11
+ require 'rbcurse/action'
12
+ require 'fileutils'
13
+ #$LOAD_PATH << "/Users/rahul/work/projects/rbcurse/"
14
+
15
+ # TODO
16
+ # operations on selected files: move, delete, zip
17
+ # This class represents the finder pane. There are 2
18
+ # on this sample app
19
+ class FileExplorer
20
+ include FileUtils
21
+ attr_reader :wdir
22
+ attr_reader :list # listbox
23
+ attr_reader :dir
24
+ attr_reader :prev_dirs
25
+ attr_reader :other_list # the opposite list
26
+ attr_reader :entries # avoid, can be outdated
27
+ attr_accessor :filter_pattern
28
+
29
+ def initialize form, rfe, row, col, height, width
30
+ @form = form
31
+ @rfe = rfe
32
+ @row, @col, @ht, @wid = row, col, height, width
33
+ @dir = Dir.new(Dir.getwd)
34
+ @wdir = @dir.path
35
+ @filter_pattern = '*'
36
+ @prev_dirs=[]
37
+ end
38
+ def title str
39
+ @list.title = str
40
+ end
41
+ def selected_color
42
+ @list.selected_color
43
+ end
44
+ def selected_bgcolor
45
+ @list.selected_bgcolor
46
+ end
47
+
48
+ # changes to given dir
49
+ # ensure that path is provided since other list
50
+ # may have cd'd elsewhere
51
+ def change_dir adir
52
+ list = @list
53
+ begin
54
+ #dir = File.expand_path dir
55
+ #cd "#{@dir.path}/#{adir}"
56
+ cd adir
57
+ list.title = pwd()
58
+ @dir = Dir.new(Dir.getwd)
59
+ @wdir = @dir.path
60
+ @prev_dirs << @wdir
61
+ rescan
62
+ rescue => err
63
+ @rfe.status_row.text = err.to_s
64
+ end
65
+ end
66
+ def goto_previous_dir
67
+ d = @prev_dirs.pop
68
+ if !d.nil? and d == @wdir
69
+ d = @prev_dirs.pop
70
+ end
71
+ change_dir d unless d.nil?
72
+ end
73
+ def filter list
74
+ list.delete_if { |f|
75
+ !File.directory? @wdir +"/"+ f and !File.fnmatch?(@filter_pattern, f)
76
+ }
77
+ #$log.debug " FILTER CALLED AFTER #{list.size}, #{list.entries}"
78
+ end
79
+ def rescan
80
+ flist = @dir.entries
81
+ flist.shift
82
+ #populate @entries
83
+ populate flist
84
+ end
85
+ def populate flist
86
+ #fl << format_string("..", nil)
87
+ #fl = []
88
+ #flist.each {|f| ff = "#{@wdir}/#{f}"; stat = File.stat(ff)
89
+ # fl << format_string(f, stat)
90
+ #}
91
+ filter(flist) if @filter_pattern != '*'
92
+ @entries = flist
93
+ list.list_data_model.remove_all
94
+ #list.list_data_model.insert 0, *fl
95
+ list.list_data_model.insert 0, *flist
96
+ end
97
+ def sort key, reverse=false
98
+ # remove parent before sorting, keep at top
99
+ first = @entries.delete_at(0) if @entries[0]==".."
100
+ key ||= @sort_key
101
+ cdir=cur_dir()+"/"
102
+ case key
103
+ when :size
104
+ @entries.sort! {|x,y| xs = File.stat(cdir+x); ys = File.stat(cdir+y);
105
+ if reverse
106
+ xs.size <=> ys.size
107
+ else
108
+ ys.size <=> xs.size
109
+ end
110
+ }
111
+ when :mtime
112
+ @entries.sort! {|x,y| xs = File.stat(cdir+x); ys = File.stat(cdir+y);
113
+ if reverse
114
+ xs.mtime <=> ys.mtime
115
+ else
116
+ ys.mtime <=> xs.mtime
117
+ end
118
+ }
119
+ when :atime
120
+ @entries.sort! {|x,y| xs = File.stat(cdir+x); ys = File.stat(cdir+y);
121
+ if reverse
122
+ xs.atime <=> ys.atime
123
+ else
124
+ ys.atime <=> xs.atime
125
+ end
126
+ }
127
+ when :name
128
+ @entries.sort! {|x,y| x <=> y
129
+ if reverse
130
+ x <=> y
131
+ else
132
+ y <=> x
133
+ end
134
+ }
135
+ when :ext
136
+ @entries.sort! {|x,y|
137
+ if reverse
138
+ File.extname(cdir+x) <=> File.extname(cdir+y)
139
+ else
140
+ File.extname(cdir+y) <=> File.extname(cdir+x)
141
+ end
142
+ }
143
+ end
144
+ @sort_key = key
145
+ @entries.insert 0, first unless first.nil? # keep parent on top
146
+ populate @entries
147
+ end
148
+ GIGA_SIZE = 1073741824.0
149
+ MEGA_SIZE = 1048576.0
150
+ KILO_SIZE = 1024.0
151
+
152
+ # Return the file size with a readable style.
153
+ def readable_file_size(size, precision)
154
+ case
155
+ #when size == 1 : "1 B"
156
+ when size < KILO_SIZE : "%d B" % size
157
+ when size < MEGA_SIZE : "%.#{precision}f K" % (size / KILO_SIZE)
158
+ when size < GIGA_SIZE : "%.#{precision}f M" % (size / MEGA_SIZE)
159
+ else "%.#{precision}f G" % (size / GIGA_SIZE)
160
+ end
161
+ end
162
+ def date_format t
163
+ t.strftime "%Y/%m/%d"
164
+ end
165
+ def oldformat_string fn, stat
166
+ max_len = 30
167
+ f = fn.dup
168
+ if File.directory? f
169
+ #"%-*s\t(dir)" % [max_len,f]
170
+ #f = "/"+f # disallows search on keypress
171
+ f = f + "/ "
172
+ end
173
+ if f.size > max_len
174
+ f = f[0..max_len-1]
175
+ end
176
+ "%-*s\t%10s\t%s" % [max_len,f, readable_file_size(stat.size,1), date_format(stat.mtime)]
177
+ end
178
+ def cur_dir
179
+ @dir.path
180
+ end
181
+ alias :current_dir :cur_dir
182
+ def draw_screen dir=nil
183
+ cd dir unless dir.nil?
184
+ wdir = FileUtils.pwd
185
+ @prev_dirs << wdir
186
+ @dir = Dir.new(Dir.getwd)
187
+ @wdir = @dir.path
188
+ r = @row
189
+ c = @col
190
+ #cola = 1
191
+ #colb = Ncurses.COLS/2
192
+ ht = @ht
193
+ wid = @wid
194
+ #fl = Dir.glob(default_pattern)
195
+ #flist << format_string("..", nil)
196
+ fl = @dir.entries
197
+ fl.shift
198
+ filter(fl)
199
+ #flist = []
200
+ #fl.each {|f| stat = File.stat(f)
201
+ # flist << format_string(f, stat)
202
+ #}
203
+ @entries = fl
204
+ title = pwd()
205
+ @wdir = title
206
+ rfe = self
207
+
208
+ lista = Listbox.new @form do
209
+ name "lista"
210
+ row r
211
+ col c
212
+ width wid
213
+ height ht
214
+ #list flist
215
+ list fl
216
+ title wdir
217
+ #title_attrib 'reverse'
218
+ cell_renderer RfeRenderer.new "", {"color"=>@color, "bgcolor"=>@bgcolor, "parent" => rfe, "display_length"=> wid-2}
219
+ end
220
+ @list = lista
221
+ lista.bind(:ENTER) {|l| @rfe.current_list(self); l.title_attrib 'reverse'; }
222
+ lista.bind(:LEAVE) {|l| l.title_attrib 'normal'; }
223
+
224
+
225
+ #row_cmd = lambda {|list| file = list.list_data_model[list.current_index].split(/\t/)[0].strip; @rfe.status_row.text = File.stat("#{cur_dir()}/#{file}").inspect }
226
+ row_cmd = lambda {|lb, list| file = list.entries[lb.current_index]; @rfe.status_row.text = file; # File.stat("#{cur_dir()}/#{file}").inspect
227
+ }
228
+ lista.bind(:ENTER_ROW, self) {|lb,list| row_cmd.call(lb,list) }
229
+
230
+ end
231
+ def list_data
232
+ @list.list_data_model
233
+ end
234
+ def current_index
235
+ @list.current_index
236
+ end
237
+ def filename
238
+ #@entries[@list.current_index]
239
+ list_data()[current_index()]
240
+ end
241
+ def filepath
242
+ f = filename()
243
+ if f[0,1]=='/'
244
+ f
245
+ else
246
+ cur_dir() + "/" + filename()
247
+ end
248
+ end
249
+
250
+ end
251
+ class RFe
252
+ attr_reader :status_row
253
+ def initialize
254
+ @window = VER::Window.root_window
255
+ @form = Form.new @window
256
+ status_row = RubyCurses::Label.new @form, {'text' => "", :row => Ncurses.LINES-4, :col => 0, :display_length=>Ncurses.COLS-2}
257
+ @status_row = status_row
258
+ colb = Ncurses.COLS/2
259
+ ht = Ncurses.LINES - 7
260
+ wid = Ncurses.COLS/2 - 0
261
+ @lista = FileExplorer.new @form, self, row=2, col=1, ht, wid
262
+ @listb = FileExplorer.new @form, self, row=2, col=colb, ht, wid
263
+
264
+ init_vars
265
+ end
266
+ def init_vars
267
+ @bookmarks=[]
268
+ @config_name = File.expand_path("~/.rfe.yml")
269
+ if File.exist? @config_name
270
+ @config = YAML::load( File.open(@config_name));
271
+ if !@config.nil?
272
+ @bookmarks = @config["bookmarks"]||[]
273
+ @last_dirs = @config["last_dirs"]
274
+ end
275
+ end
276
+ @config ||={}
277
+ end
278
+ def save_config
279
+ @config["last_dirs"]=[@lista.current_dir(),@listb.current_dir()]
280
+ File.open(@config_name, "w") { | f | YAML.dump( @config, f )}
281
+ end
282
+ def move
283
+ fp = @current_list.filepath
284
+ fn = @current_list.filename
285
+ $log.debug " FP #{fp}"
286
+ other_list = [@lista, @listb].index(@current_list)==0 ? @listb : @lista
287
+ other_dir = other_list.cur_dir
288
+ $log.debug " OL #{other_list.cur_dir}"
289
+ str= "move #{fn} to #{other_list.cur_dir}"
290
+ $log.debug " MOVE #{fp}"
291
+ #confirm "#{str}"
292
+ mb = RubyCurses::MessageBox.new do
293
+ title "Move"
294
+ message "Move #{fn} to"
295
+ type :input
296
+ width 60
297
+ default_value other_dir
298
+ button_type :ok_cancel
299
+ default_button 0
300
+ end
301
+ #confirm "selected :#{mb.input_value}, #{mb.selected_index}"
302
+ if mb.selected_index == 0
303
+ # need to redraw directories
304
+ FileUtils.move(fp, mb.input_value)
305
+ @current_list.list.list_data_model.delete_at @current_list.list.current_index # ???
306
+ other_list.rescan
307
+ end
308
+ end
309
+ def copy
310
+ fp = @current_list.filepath
311
+ fn = @current_list.filename
312
+ $log.debug " FP #{fp}"
313
+ other_list = [@lista, @listb].index(@current_list)==0 ? @listb : @lista
314
+ other_dir = other_list.cur_dir
315
+ $log.debug " OL #{other_list.cur_dir}"
316
+ str= "copy #{fn} to #{other_list.cur_dir}"
317
+ $log.debug " copy #{fp}"
318
+ #confirm "#{str}"
319
+ mb = RubyCurses::MessageBox.new do
320
+ title "Copy"
321
+ message "Copy #{fn} to"
322
+ type :input
323
+ width 60
324
+ default_value other_dir
325
+ button_type :ok_cancel
326
+ default_button 0
327
+ end
328
+ #confirm "selected :#{mb.input_value}, #{mb.selected_index}"
329
+ if mb.selected_index == 0
330
+ # need to redraw directories
331
+ FileUtils.copy(fp, mb.input_value)
332
+ other_list.rescan
333
+ end
334
+ end
335
+ ## TODO : make this separate and callable with its own keylabels
336
+ def view content=nil
337
+ require 'rbcurse/rtextview'
338
+ wt = 0
339
+ wl = 0
340
+ wh = Ncurses.LINES-wt
341
+ ww = Ncurses.COLS-wl
342
+ if content.nil?
343
+ fp = @current_list.filepath
344
+ content = get_contents(fp)
345
+ else
346
+ fp=""
347
+ end
348
+ @layout = { :height => wh, :width => ww, :top => wt, :left => wl }
349
+ @v_window = VER::Window.new(@layout)
350
+ @v_form = RubyCurses::Form.new @v_window
351
+ @textview = TextView.new @v_form do
352
+ name "myView"
353
+ row 0
354
+ col 0
355
+ width ww
356
+ height wh-2
357
+ title fp
358
+ title_attrib 'bold'
359
+ print_footer true
360
+ footer_attrib 'bold'
361
+ end
362
+ #content = File.open(fp,"r").readlines
363
+ @textview.set_content content #, :WRAP_WORD
364
+ @v_form.repaint
365
+ @v_window.wrefresh
366
+ Ncurses::Panel.update_panels
367
+ begin
368
+ while((ch = @v_window.getchar()) != ?\C-q )
369
+ break if ch == KEY_F3
370
+ @v_form.handle_key ch
371
+ @v_form.repaint
372
+ ##@v_window.wrefresh
373
+ end
374
+ ensure
375
+ @v_window.destroy if !@v_window.nil?
376
+ end
377
+ end
378
+ def get_contents fp
379
+ return nil unless File.readable? fp
380
+ return Dir.new(fp).entries if File.directory? fp
381
+ case File.extname(fp)
382
+ when '.tgz','.gz'
383
+ cmd = "tar -ztvf #{fp}"
384
+ content = %x[#{cmd}]
385
+ else
386
+ content = File.open(fp,"r").readlines
387
+ end
388
+ end
389
+ def opt_file c
390
+ fp = @current_list.filepath
391
+ fn = @current_list.filename
392
+ other_list = [@lista, @listb].index(@current_list)==0 ? @listb : @lista
393
+ case c
394
+ when 'c'
395
+ # str= "copy #{fn} to #{other_list.cur_dir}"
396
+ copy
397
+ when 'm'
398
+ str= "move #{fn} to #{other_list.cur_dir}"
399
+ move
400
+ #if confirm("#{str}")==:YES
401
+ #$log.debug " MOVE #{str}"
402
+ #end
403
+ when 'd'
404
+ str= "delete #{fn} "
405
+ if confirm("#{str}")==:YES
406
+ $log.debug " delete #{fp}"
407
+ FileUtils.rm fp
408
+ ret=@current_list.list.list_data_model.delete_at @current_list.list.current_index # ???
409
+ $log.debug " DEL RET #{ret},#{@current_list.list.current_index}"
410
+ end
411
+ when 'u'
412
+ str= "move #{fn} to #{other_list.cur_dir}"
413
+ if confirm("#{str}")==:YES
414
+ $log.debug " MOVE #{str}"
415
+ end
416
+ when 'v'
417
+ str= "view #{fp}"
418
+ #if confirm("#{str}")==:YES
419
+ $log.debug " VIEW #{fp}"
420
+ view
421
+ #end
422
+ when 'r'
423
+ str= "ruby #{fn}"
424
+ if confirm("#{str}")=='y'
425
+ $log.debug " #{str} "
426
+ end
427
+ when 'e'
428
+ str= "edit #{fp}"
429
+ #if confirm("#{str}")==:YES
430
+ edit fp
431
+ when 'x'
432
+ str= "exec #{fp}"
433
+ exec_popup fp
434
+ end
435
+ end
436
+ def opt_dir c
437
+ fp = @current_list.filepath
438
+ fn = @current_list.filename
439
+ case c
440
+ when 'O'
441
+ # str= "copy #{fn} to #{other_list.cur_dir}"
442
+ if File.directory? @current_list.filepath
443
+ @current_list.change_dir fp
444
+ end
445
+ when 'o'
446
+ if File.directory? @current_list.filepath
447
+ @other_list.change_dir fp
448
+ end
449
+ @open_in_other = true # ???basically keep opening in other
450
+ when 'd'
451
+ str= "delete #{fn} "
452
+ if confirm("#{str}")==:YES
453
+ $log.debug " delete #{fp}"
454
+ FileUtils.rm fp
455
+ ret=@current_list.list.list_data_model.delete_at @current_list.list.current_index # ???
456
+ $log.debug " DEL RET #{ret},#{@current_list.list.current_index}"
457
+ end
458
+ when 'u'
459
+ str= "move #{fn} to #{other_list.cur_dir}"
460
+ if confirm("#{str}")==:YES
461
+ $log.debug " MOVE #{str}"
462
+ end
463
+ when 'b'
464
+ dd = @current_list.wdir
465
+ @bookmarks << dd unless @bookmarks.include? dd
466
+ when 'u'
467
+ dd = @current_list.wdir
468
+ @bookmarks.delete dd
469
+ when 'l'
470
+ @current_list.populate @bookmarks
471
+ when 's'
472
+ @config["bookmarks"] = @bookmarks
473
+ save_config
474
+ when 'e'
475
+ str= "edit #{fp}"
476
+ #if confirm("#{str}")==:YES
477
+ edit fp
478
+ when 'x'
479
+ str= "exec #{fp}"
480
+ exec_popup fp
481
+ end
482
+ end
483
+ def exec_popup fp
484
+ last_exec_def1 = @last_exec_def1 || ""
485
+ last_exec_def2 = @last_exec_def2 || false
486
+
487
+ sel, inp, hash = get_string_with_options("Enter a command to execute on #{fp}", 30, last_exec_def1, {"checkboxes" => ["view result"], "checkbox_defaults"=>[last_exec_def2]})
488
+ if sel == 0
489
+ @last_exec_def1 = inp
490
+ @last_exec_def2 = hash["view result"]
491
+ cmd = "#{inp} #{fp}"
492
+ filestr = %x[ #{cmd} 2>/dev/null ]
493
+ if hash["view result"]==true
494
+ view filestr
495
+ end
496
+ end
497
+ end
498
+ def edit fp=@current_list.filepath
499
+ $log.debug " edit #{fp}"
500
+ shell_out "/opt/local/bin/vim #{fp}"
501
+ end
502
+ def draw_screens
503
+ lasta = lastb = nil
504
+ if !@config["last_dirs"].nil?
505
+ lasta = @config["last_dirs"][0]
506
+ lastb = @config["last_dirs"][1]
507
+ end
508
+ @lista.draw_screen lasta
509
+ @listb.draw_screen lastb
510
+
511
+ @form.bind_key(?@){
512
+ @current_list.change_dir File.expand_path("~/")
513
+ }
514
+ @form.bind_key(?^){
515
+ @current_list.change_dir @current_list.prev_dirs[0] unless @current_list.prev_dirs.empty?
516
+ }
517
+ @form.bind_key(?\C-f){
518
+ @klp.mode :file
519
+ @klp.repaint
520
+ ## FIXME chr could fail !!
521
+ while((ch = @window.getchar()) != ?\C-c )
522
+ if "cmdsuvrex".index(ch.chr) == nil
523
+ Ncurses.beep
524
+ else
525
+ opt_file ch.chr
526
+ break
527
+ end
528
+ end
529
+ @klp.mode :normal
530
+ }
531
+ @form.bind_key(?\C-d){
532
+ @klp.mode :dir
533
+ @klp.repaint
534
+ keys = @klp.get_current_keys
535
+ ## FIXME chr could fail !!
536
+ while((ch = @window.getchar()) != ?\C-c )
537
+ if !keys.include?(ch.chr)
538
+ Ncurses.beep
539
+ else
540
+ opt_dir ch.chr
541
+ break
542
+ end
543
+ end
544
+ @klp.mode :normal
545
+ }
546
+ # backspace
547
+ @form.bind_key(127){
548
+ @current_list.goto_previous_dir
549
+ }
550
+ @form.bind_key(32){
551
+ begin
552
+ cmd="qlmanage -p #{@current_list.filepath} 2>/dev/null"
553
+ %x[#{cmd}]
554
+ rescue Interrupt
555
+ end
556
+ }
557
+ @form.bind_key(KEY_F3){
558
+ view()
559
+ }
560
+ @form.bind_key(KEY_F4){
561
+ edit()
562
+ }
563
+ @form.bind_key(KEY_F6){
564
+ selected_index, sort_key, reverse, case_sensitive = sort_popup
565
+ if selected_index == 0
566
+ @current_list.sort(sort_key, reverse)
567
+ end
568
+ }
569
+ @form.bind_key(KEY_F5){
570
+ filter()
571
+ }
572
+ @form.bind_key(KEY_F7){
573
+ grep_popup()
574
+ }
575
+ @form.bind_key(KEY_F8){
576
+ system_popup()
577
+ }
578
+ @form.bind_key(?\C-m){
579
+ dir = @current_list.filepath
580
+ if File.directory? @current_list.filepath
581
+ @current_list.change_dir dir
582
+ end
583
+ }
584
+ @klp = RubyCurses::KeyLabelPrinter.new @form, get_key_labels
585
+ @klp.set_key_labels get_key_labels(:file), :file
586
+ @klp.set_key_labels get_key_labels(:view), :view
587
+ @klp.set_key_labels get_key_labels(:dir), :dir
588
+ @form.repaint
589
+ @window.wrefresh
590
+ Ncurses::Panel.update_panels
591
+ begin
592
+ while((ch = @window.getchar()) != ?\C-q )
593
+ s = keycode_tos ch
594
+ status_row.text = "Pressed #{ch} , #{s}"
595
+ @form.handle_key(ch)
596
+
597
+ @form.repaint
598
+ @window.wrefresh
599
+ end
600
+ ensure
601
+ @window.destroy if !@window.nil?
602
+ save_config
603
+ end
604
+
605
+ end
606
+ # TODO
607
+ #
608
+ #
609
+ #
610
+
611
+ # current_list
612
+ ##
613
+ # getter and setter for current_list
614
+ def current_list(*val)
615
+ if val.empty?
616
+ @current_list
617
+ else
618
+ @current_list = val[0]
619
+ @other_list = [@lista, @listb].index(@current_list)==0 ? @listb : @lista
620
+ end
621
+ end
622
+ def get_key_labels categ=nil
623
+ if categ.nil?
624
+ key_labels = [
625
+ ['C-q', 'Exit'], ['C-v', 'View'],
626
+ ['C-f', 'File'], ['C-d', 'Dir'],
627
+ ['C-x','Select'], nil,
628
+ ['F3', 'View'], ['F4', 'Edit'],
629
+ ['F5', 'Filter'], ['F6', 'Sort'],
630
+ ['F7', 'Grep'], ['F8', 'System'],
631
+ ['M-0', 'Top'], ['M-9', 'End'],
632
+ ['C-p', 'PgUp'], ['C-n', 'PgDn']
633
+ ]
634
+ elsif categ == :file
635
+ key_labels = [
636
+ ['c', 'Copy'], ['m', 'Move'],
637
+ ['d', 'Delete'], ['v', 'View'],
638
+ ['s', 'Select'], ['u', 'Unselect'],
639
+ ['p', 'Page'], ['x', 'Exec Cmd'],
640
+ ['r', 'ruby'], ['e', "Edit"],
641
+ ['C-c', 'Cancel']
642
+ ]
643
+ elsif categ == :view
644
+ key_labels = [
645
+ ['c', 'Date'], ['m', 'Size'],
646
+ ['d', 'Delete'], ['v', 'View'],
647
+ ['C-c', 'Cancel']
648
+ ]
649
+ elsif categ == :dir
650
+ key_labels = [
651
+ ['o', 'open'], ['O', 'Open in right'],
652
+ ['d', 'Delete'], ['R', 'Del Recurse'],
653
+ ['t', 'tree'], ['p', 'Previous'],
654
+ ['b', 'Bookmark'], ['u', 'Unbookmark'],
655
+ ['l', 'List'], ['s', 'Save'],
656
+ ['C-c', 'Cancel']
657
+ ]
658
+ end
659
+ return key_labels
660
+ end
661
+ def get_key_labels_table
662
+ key_labels = [
663
+ ['M-n','NewRow'], ['M-d','DelRow'],
664
+ ['C-x','Select'], nil,
665
+ ['M-0', 'Top'], ['M-9', 'End'],
666
+ ['C-p', 'PgUp'], ['C-n', 'PgDn'],
667
+ ['M-Tab','Nxt Fld'], ['Tab','Nxt Col'],
668
+ ['+','Widen'], ['-','Narrow']
669
+ ]
670
+ return key_labels
671
+ end
672
+ def sort_popup
673
+ mform = RubyCurses::Form.new nil
674
+ field_list = []
675
+ r = 4
676
+ $radio = RubyCurses::Variable.new
677
+ rtextvalue = [:name, :ext, :size, :mtime, :atime]
678
+ ["Name", "Extension", "Size", "Modify Time", "Access Time" ].each_with_index do |rtext,ix|
679
+ field = RubyCurses::RadioButton.new mform do
680
+ variable $radio
681
+ text rtext
682
+ value rtextvalue[ix]
683
+ color 'black'
684
+ bgcolor 'white'
685
+ row r
686
+ col 5
687
+ end
688
+ field_list << field
689
+ r += 1
690
+ end
691
+ r = 4
692
+ ["Reverse", "case sensitive"].each do |cbtext|
693
+ field = RubyCurses::CheckBox.new mform do
694
+ text cbtext
695
+ name cbtext
696
+ color 'black'
697
+ bgcolor 'white'
698
+ row r
699
+ col 30
700
+ end
701
+ field_list << field
702
+ r += 1
703
+ end
704
+ mb = RubyCurses::MessageBox.new mform do
705
+ title "Sort Options"
706
+ button_type :ok_cancel
707
+ default_button 0
708
+ end
709
+ if mb.selected_index == 0
710
+ $log.debug " SORT POPUP #{$radio.value}"
711
+ #$log.debug " SORT POPUP #{mb.inspect}"
712
+ $log.debug " SORT POPUP #{mform.by_name["Reverse"].value}"
713
+ $log.debug " SORT POPUP #{mform.by_name["case sensitive"].value}"
714
+ end
715
+ return mb.selected_index, $radio.value, mform.by_name["Reverse"].value, mform.by_name["case sensitive"].value
716
+ end
717
+ def filter
718
+ f = get_string("Enter a filter pattern", 20, "*")
719
+ f = "*" if f.nil? or f == ""
720
+ @current_list.filter_pattern = f
721
+ @current_list.rescan
722
+ end
723
+ def grep_popup
724
+ last_regex = @last_regex || ""
725
+ last_pattern = @last_pattern || "*"
726
+ mform = RubyCurses::Form.new nil
727
+ r = 4
728
+ field = RubyCurses::Field.new mform do
729
+ name "regex"
730
+ row r
731
+ col 30
732
+ set_buffer last_regex
733
+ set_label Label.new @form, {'text' => 'Regex', 'col'=>5, :color=>'black',:bgcolor=>'white','mnemonic'=> 'R'}
734
+ end
735
+ r += 1
736
+ field = RubyCurses::Field.new mform do
737
+ name "filepattern"
738
+ row r
739
+ col 30
740
+ set_buffer last_pattern
741
+ set_label Label.new @form, {'text' => 'File Pattern','col'=>5, :color=>'black',:bgcolor=>'white','mnemonic'=> 'F'}
742
+ end
743
+ r += 1
744
+ ["Recurse", "case insensitive"].each do |cbtext|
745
+ field = RubyCurses::CheckBox.new mform do
746
+ text cbtext
747
+ name cbtext
748
+ color 'black'
749
+ bgcolor 'white'
750
+ row r
751
+ col 5
752
+ end
753
+ r += 1
754
+ end
755
+ mb = RubyCurses::MessageBox.new mform do
756
+ title "Grep Options"
757
+ button_type :ok_cancel
758
+ default_button 0
759
+ end
760
+ if mb.selected_index == 0
761
+ return if mform.by_name["regex"].getvalue()==""
762
+ @last_regex = mform.by_name["regex"].getvalue
763
+ inp = mform.by_name["regex"].getvalue
764
+ fp = mform.by_name["filepattern"].getvalue
765
+ @last_pattern = fp
766
+ flags=""
767
+ flags << " -i " if mform.by_name["case insensitive"].value==true
768
+ flags << " -R " if mform.by_name["Recurse"].value==true
769
+ cmd = "cd #{@current_list.cur_dir()};grep -l #{flags} #{inp} #{fp}"
770
+ filestr = %x[ #{cmd} ]
771
+ files = nil
772
+ files = filestr.split(/\n/) unless filestr.nil?
773
+ #view filestr
774
+ @current_list.title "grep #{inp}"
775
+ @current_list.populate files
776
+ end
777
+ return mb.selected_index, mform.by_name["regex"].getvalue, mform.by_name["filepattern"].getvalue, mform.by_name["Recurse"].value, mform.by_name["case insensitive"].value
778
+ end
779
+ def system_popup
780
+ deflt = @last_system || ""
781
+ options=["run in shell","view output","file explorer"]
782
+ #inp = get_string("Enter a system command", 30, deflt)
783
+ sel, inp, hash = get_string_with_options("Enter a system command", 40, deflt, {"radiobuttons" => options, "radio_default"=>@last_system_radio || options[0]})
784
+ if sel == 0
785
+ if !inp.nil?
786
+ @last_system = inp
787
+ @last_system_radio = hash["radio"]
788
+ case hash["radio"]
789
+ when options[0]
790
+ shell_out inp
791
+ when options[1]
792
+ filestr = %x[ #{inp} ]
793
+ view filestr
794
+ when options[2]
795
+ filestr = %x[ #{inp} ]
796
+ files = nil
797
+ files = filestr.split(/\n/) unless filestr.nil?
798
+ @current_list.title inp
799
+ @current_list.populate files
800
+ $log.debug " SYSTEM got #{files.size}, #{files.inspect}"
801
+ end
802
+ end
803
+ end
804
+ end
805
+ def popup
806
+ deflt = @last_regexp || ""
807
+ #sel, inp, hash = get_string_with_options("Enter a filter pattern", 20, "*", {"checkboxes" => ["case sensitive","reverse"], "checkbox_defaults"=>[true, false]})
808
+ sel, inp, hash = get_string_with_options("Enter a grep pattern", 20, deflt, {"checkboxes" => ["case insensitive","not-including"]})
809
+ if sel == 0
810
+ @last_regexp = inp
811
+ flags=""
812
+ flags << " -i " if hash["case insensitive"]==true
813
+ flags << " -v " if hash["not-including"]==true
814
+ cmd = "grep -l #{flags} #{inp} *"
815
+ filestr = %x[ #{cmd} ]
816
+ files = nil
817
+ files = filestr.split(/\n/) unless filestr.nil?
818
+ view filestr
819
+ end
820
+ $log.debug " POPUP: #{sel}: #{inp}, #{hash['case sensitive']}, #{hash['reverse']}"
821
+ end
822
+ def shell_out command
823
+ @window.hide
824
+ Ncurses.endwin
825
+ system command
826
+ Ncurses.refresh
827
+ #Ncurses.curs_set 0 # why ?
828
+ @window.show
829
+ end
830
+ end
831
+ if $0 == __FILE__
832
+ include RubyCurses
833
+ include RubyCurses::Utils
834
+
835
+ begin
836
+ # Initialize curses
837
+ VER::start_ncurses # this is initializing colors via ColorMap.setup
838
+ $log = Logger.new("view.log")
839
+ $log.level = Logger::DEBUG
840
+
841
+ catch(:close) do
842
+ t = RFe.new
843
+ t.draw_screens
844
+ end
845
+ rescue => ex
846
+ ensure
847
+ VER::stop_ncurses
848
+ p ex if ex
849
+ p(ex.backtrace.join("\n")) if ex
850
+ $log.debug( ex) if ex
851
+ $log.debug(ex.backtrace.join("\n")) if ex
852
+ end
853
+ end