rbcurse 1.5.0 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. data/Makefile +21 -0
  2. data/Manifest.txt +6 -0
  3. data/README.markdown +6 -4
  4. data/TODO +372 -0
  5. data/TODO2.txt +121 -0
  6. data/VERSION +1 -1
  7. data/examples/README.txt +67 -0
  8. data/examples/abasiclist.rb +33 -0
  9. data/examples/alpmenu.rb +42 -0
  10. data/examples/app.rb +859 -0
  11. data/examples/app.sample +17 -0
  12. data/examples/appdirtree.rb +74 -0
  13. data/examples/appemail.rb +191 -0
  14. data/examples/appemaillb.rb +308 -0
  15. data/examples/appgcompose.rb +315 -0
  16. data/examples/atree.rb +64 -0
  17. data/examples/common/file.rb +40 -0
  18. data/examples/common/rmail.rb +257 -0
  19. data/examples/data.txt +683 -0
  20. data/examples/data/README.markdown +9 -0
  21. data/examples/data/brew.txt +38 -0
  22. data/examples/data/color.2 +37 -0
  23. data/examples/data/gemlist.txt +60 -0
  24. data/examples/data/lotr.txt +12 -0
  25. data/examples/data/ports.txt +136 -0
  26. data/examples/data/tasks.txt +27 -0
  27. data/examples/data/todocsv.csv +28 -0
  28. data/examples/data/unix1.txt +21 -0
  29. data/examples/data/unix2.txt +11 -0
  30. data/examples/dbdemo.rb +495 -0
  31. data/examples/deprecated/appgmail.rb +952 -0
  32. data/examples/deprecated/splitp.rb +56 -0
  33. data/examples/deprecated/testscrolllb.rb +86 -0
  34. data/examples/deprecated/testscrollp.rb +88 -0
  35. data/examples/deprecated/testscrollta.rb +80 -0
  36. data/examples/deprecated/testscrolltable.rb +165 -0
  37. data/examples/deprecated/testsplit.rb +87 -0
  38. data/examples/deprecated/testsplit2.rb +123 -0
  39. data/examples/deprecated/testsplit3.rb +215 -0
  40. data/examples/deprecated/testsplit3_1.rb +244 -0
  41. data/examples/deprecated/testsplit3a.rb +215 -0
  42. data/examples/deprecated/testsplit3b.rb +237 -0
  43. data/examples/deprecated/testsplitta.rb +148 -0
  44. data/examples/deprecated/testsplittv.rb +142 -0
  45. data/examples/deprecated/testsplittvv.rb +144 -0
  46. data/examples/deprecated/testtpane.rb +215 -0
  47. data/examples/deprecated/testtpane2.rb +145 -0
  48. data/examples/deprecated/testtpanetable.rb +203 -0
  49. data/examples/dirtree.rb +88 -0
  50. data/examples/experimental/resultsetdemo.rb +280 -0
  51. data/examples/experimental/testmform.rb +35 -0
  52. data/examples/experimental/testscroller.rb +117 -0
  53. data/examples/experimental/teststackflow.rb +111 -0
  54. data/examples/menu1.rb +112 -0
  55. data/examples/multispl.rb +86 -0
  56. data/examples/newmessagebox.rb +131 -0
  57. data/examples/newtabbedwindow.rb +100 -0
  58. data/examples/newtesttabp.rb +121 -0
  59. data/examples/qdfilechooser.rb +68 -0
  60. data/examples/rfe.rb +1239 -0
  61. data/examples/rfe_renderer.rb +121 -0
  62. data/examples/sqlc.rb +454 -0
  63. data/examples/sqlm.rb +437 -0
  64. data/examples/sqlt.rb +408 -0
  65. data/examples/status.txt +68 -0
  66. data/examples/table1.rb +24 -0
  67. data/examples/term2.rb +84 -0
  68. data/examples/test1.rb +239 -0
  69. data/examples/test2.rb +674 -0
  70. data/examples/testapp.rb +44 -0
  71. data/examples/testapp2.rb +58 -0
  72. data/examples/testchars.rb +137 -0
  73. data/examples/testcombo.rb +91 -0
  74. data/examples/testkeypress.rb +66 -0
  75. data/examples/testlistbox.rb +113 -0
  76. data/examples/testmenu.rb +101 -0
  77. data/examples/testmulticomp.rb +70 -0
  78. data/examples/testmulticontainer.rb +94 -0
  79. data/examples/testmultispl.rb +199 -0
  80. data/examples/testree.rb +106 -0
  81. data/examples/testtable.rb +264 -0
  82. data/examples/testtabp.rb +107 -0
  83. data/examples/testtodo.rb +584 -0
  84. data/examples/testvimsplit.rb +112 -0
  85. data/examples/testwsshortcuts.rb +64 -0
  86. data/examples/testwsshortcuts2.rb +126 -0
  87. data/examples/todo.db +0 -0
  88. data/examples/todo.yml +191 -0
  89. data/examples/viewtodo.rb +574 -0
  90. data/lib/rbcurse/deprecated/README.markdown +12 -0
  91. data/lib/rbcurse/deprecated/rpad.rb +375 -0
  92. data/lib/rbcurse/deprecated/rscrollpane.rb +512 -0
  93. data/lib/rbcurse/deprecated/rsplitpane.rb +894 -0
  94. data/lib/rbcurse/deprecated/rsplitpane2.rb +1009 -0
  95. data/lib/rbcurse/deprecated/rviewport.rb +204 -0
  96. data/lib/rbcurse/deprecated/widgets/mapper.rb +130 -0
  97. data/lib/rbcurse/deprecated/widgets/rmessagebox.rb +348 -0
  98. data/lib/rbcurse/deprecated/widgets/rtabbedpane.rb +1158 -0
  99. data/lib/rbcurse/deprecated/widgets/rtabbedwindow.rb +167 -0
  100. data/lib/rbcurse/deprecated/widgets/scrollable.rb +301 -0
  101. data/lib/rbcurse/deprecated/widgets/stdscrwindow.rb +309 -0
  102. data/lib/ver/keyboard2.rb +170 -0
  103. data/test/test_rbcurse.rb +0 -0
  104. metadata +131 -9
@@ -0,0 +1,131 @@
1
+ # this is a test program, tests out tabbed panes. type F1 to exit
2
+ #
3
+ require 'rbcurse'
4
+ require 'rbcurse/core/widgets/rmessagebox'
5
+
6
+ def alertme mess, config={}
7
+
8
+ _title = config[:title] || "Alert"
9
+ tp = Messagebox.new config do
10
+ title _title
11
+ button_type :ok
12
+ message mess
13
+ #text mess
14
+ end
15
+ tp.run
16
+ end
17
+ def textdialog mess, config={}
18
+ config[:title] ||= "Alert"
19
+ tp = Messagebox.new config do
20
+ button_type :ok
21
+ text mess
22
+ end
23
+ tp.run
24
+ end
25
+ #
26
+ # FIXME needs to return field entered if OK, else nil
27
+ def newget_string label, config={}
28
+ config[:title] ||= "Entry"
29
+ label_config = config[:label_config] || {}
30
+ label_config[:row] ||= 2
31
+ label_config[:col] ||= 2
32
+ label_config[:text] = label
33
+
34
+ field_config = config[:field_config] || {}
35
+ field_config[:row] ||= 3
36
+ field_config[:col] ||= 2
37
+ field_config[:attr] = :reverse
38
+ field_config[:maxlen] ||= config[:maxlen]
39
+ field_config[:default] ||= config[:default]
40
+ #field_config[:display_length] ||= 50 # i want it to extend since i don't know the actual width
41
+ field_config[:width] ||= 50 # i want it to extend since i don't know the actual width
42
+
43
+ tp = Messagebox.new config do
44
+ button_type :ok_cancel
45
+ item Label.new nil, label_config
46
+ item Field.new nil, field_config
47
+ end
48
+ tp.run
49
+ end
50
+ include RubyCurses
51
+ class SetupMessagebox
52
+ def run
53
+ $config_hash ||= Variable.new Hash.new
54
+ #configvar.update_command(){ |v| $config_hash[v.source()] = v.value }
55
+
56
+ #tp = Messagebox.new :row => 3, :col => 7, :width => 60, :height => 20 , :color => :white, :bgcolor => :blue do
57
+ tp = Messagebox.new :color => :white, :bgcolor => :blue do
58
+ title "User Setup"
59
+ button_type :ok_apply_cancel
60
+ item Field.new nil, :row => 2, :col => 2, :text => "enter your name", :label => ' Name: '
61
+ item Field.new nil, :row => 3, :col => 2, :text => "enter your email", :label => 'Email: '
62
+ r = 4
63
+ item Label.new nil, :text => "Text", :row => r+1, :col => 2, :attr => :bold
64
+ item CheckBox.new nil, :row => r+2, :col => 2, :text => "Antialias text"
65
+ item CheckBox.new nil, :row => r+3, :col => 2, :text => "Use bold fonts"
66
+ item CheckBox.new nil, :row => r+4, :col => 2, :text => "Allow blinking text"
67
+ item CheckBox.new nil, :row => r+5, :col => 2, :text => "Display ANSI Colors"
68
+ =begin
69
+ item Label.new nil, :text => "Cursor", :row => 7, :col => 2, :attr => 'bold'
70
+ $config_hash.set_value Variable.new, :cursor
71
+ item RadioButton.new nil, :row => 8, :col => 2, :text => "Block", :value => "block", :variable => $config_hash[:cursor]
72
+ item RadioButton.new nil, :row => 9, :col => 2, :text => "Blink", :value => "blink", :variable => $config_hash[:cursor]
73
+ item RadioButton.new nil, :row => 10, :col => 2, :text => "Underline", :value => "underline", :variable => $config_hash[:cursor]
74
+ end
75
+ tab "&Term" do
76
+
77
+ item Label.new nil, :text => "Arrow Key in Combos", :row => 2, :col => 2, :attr => 'bold'
78
+ x = Variable.new
79
+ $config_hash.set_value x, :term
80
+ item RadioButton.new nil, :row => 3, :col => 2, :text => "ignore", :value => "ignore", :variable => $config_hash[:term]
81
+ item RadioButton.new nil, :row => 4, :col => 2, :text => "popup", :value => "popup", :variable => $config_hash[:term]
82
+ item RadioButton.new nil, :row => 5, :col => 2, :text => "next", :value => "next", :variable => $config_hash[:term]
83
+ cb = ComboBox.new nil, :row => 7, :col => 2, :display_length => 15,
84
+ :list => %w[xterm xterm-color xterm-256color screen vt100 vt102],
85
+ :label => "Declare terminal as: "
86
+ #radio.update_command() {|rb| ENV['TERM']=rb.value }
87
+ item cb
88
+ x.update_command do |rb|
89
+ cb.arrow_key_policy=rb.value.to_sym
90
+ end
91
+
92
+ end
93
+ tab "Conta&iner" do
94
+ item r
95
+ end
96
+ # tell tabbedpane what to do if a button is pressed (ok/apply/cancel)
97
+ =end
98
+ command do |eve|
99
+ case eve.event
100
+ when 0,2 # ok cancel
101
+ newget_string "Enter name: ", :default => "john", :maxlen => 50
102
+ alertme "user pressed button index:#{eve.event}, #{eve.action_command} "
103
+ throw :close, eve.event
104
+ when 1 # apply
105
+ textdialog "user pressed apply: #{eve.to_s.length} : #{eve} "
106
+ end
107
+ end
108
+ end
109
+ tp.run
110
+ end
111
+
112
+ end
113
+ if $0 == __FILE__
114
+ # Initialize curses
115
+ begin
116
+ # XXX update with new color and kb
117
+ VER::start_ncurses # this is initializing colors via ColorMap.setup
118
+ $log = Logger.new((File.join(ENV["LOGDIR"] || "./" ,"rbc13.log")))
119
+ $log.level = Logger::DEBUG
120
+ tp = SetupMessagebox.new()
121
+ buttonindex = tp.run
122
+ $log.debug "XXX: MESSAGEBOX retirned #{buttonindex} "
123
+ rescue => ex
124
+ ensure
125
+ VER::stop_ncurses
126
+ p ex if ex
127
+ p(ex.backtrace.join("\n")) if ex
128
+ $log.debug( ex) if ex
129
+ $log.debug(ex.backtrace.join("\n")) if ex
130
+ end
131
+ end
@@ -0,0 +1,100 @@
1
+ # this is a test program, tests out tabbed panes. type F1 to exit
2
+ #
3
+ require 'logger'
4
+ require 'rbcurse'
5
+ require 'rbcurse/core/widgets/tabbedpane'
6
+ require 'rbcurse/core/widgets/rcontainer'
7
+ require 'rbcurse/core/widgets/rcombo'
8
+ require 'rbcurse/core/widgets/tabbedwindow'
9
+
10
+ include RubyCurses
11
+ class SetupTabbedPane
12
+ def run
13
+ $config_hash ||= Variable.new Hash.new
14
+ #configvar.update_command(){ |v| $config_hash[v.source()] = v.value }
15
+
16
+ r = Container.new nil, :suppress_borders => true
17
+ l1 = Label.new nil, :name => "profile", :attr => 'bold', :text => "Profile"
18
+ f1 = Field.new nil, :name => "name", :maxlen => 20, :display_length => 20, :bgcolor => :white,
19
+ :color => :black, :text => "abc", :label => ' Name: '
20
+ f2 = Field.new nil, :name => "email", :display_length => 20, :bgcolor => :white,
21
+ :color => :blue, :text => "me@google.com", :label => 'Email: '
22
+ f3 = RadioButton.new nil, :variable => $config_hash, :text => "red", :value => "RED", :color => :red
23
+ f4 = RadioButton.new nil, :variable => $config_hash, :text => "blue", :value => "BLUE", :color => :blue
24
+ f5 = RadioButton.new nil, :variable => $config_hash, :text => "green", :value => "GREEN", :color => :green
25
+ r.add(l1,f1)
26
+ r.add(f2)
27
+ r.add(f3,f4,f5)
28
+
29
+ tp = TabbedWindow.new :row => 3, :col => 7, :width => 60, :height => 20 do
30
+ title "User Setup"
31
+ button_type :ok_apply_cancel
32
+ tab "&Profile" do
33
+ item Field.new nil, :row => 2, :col => 2, :text => "enter your name", :label => ' Name: '
34
+ item Field.new nil, :row => 3, :col => 2, :text => "enter your email", :label => 'Email: '
35
+ end
36
+ tab "&Settings" do
37
+ item Label.new nil, :text => "Text", :row => 1, :col => 2, :attr => 'bold'
38
+ item CheckBox.new nil, :row => 2, :col => 2, :text => "Antialias text"
39
+ item CheckBox.new nil, :row => 3, :col => 2, :text => "Use bold fonts"
40
+ item CheckBox.new nil, :row => 4, :col => 2, :text => "Allow blinking text"
41
+ item CheckBox.new nil, :row => 5, :col => 2, :text => "Display ANSI Colors"
42
+ item Label.new nil, :text => "Cursor", :row => 7, :col => 2, :attr => 'bold'
43
+ $config_hash.set_value Variable.new, :cursor
44
+ item RadioButton.new nil, :row => 8, :col => 2, :text => "Block", :value => "block", :variable => $config_hash[:cursor]
45
+ item RadioButton.new nil, :row => 9, :col => 2, :text => "Blink", :value => "blink", :variable => $config_hash[:cursor]
46
+ item RadioButton.new nil, :row => 10, :col => 2, :text => "Underline", :value => "underline", :variable => $config_hash[:cursor]
47
+ end
48
+ tab "&Term" do
49
+
50
+ item Label.new nil, :text => "Arrow Key in Combos", :row => 2, :col => 2, :attr => 'bold'
51
+ x = Variable.new
52
+ $config_hash.set_value x, :term
53
+ item RadioButton.new nil, :row => 3, :col => 2, :text => "ignore", :value => "ignore", :variable => $config_hash[:term]
54
+ item RadioButton.new nil, :row => 4, :col => 2, :text => "popup", :value => "popup", :variable => $config_hash[:term]
55
+ item RadioButton.new nil, :row => 5, :col => 2, :text => "next", :value => "next", :variable => $config_hash[:term]
56
+ cb = ComboBox.new nil, :row => 7, :col => 2, :display_length => 15,
57
+ :list => %w[xterm xterm-color xterm-256color screen vt100 vt102],
58
+ :label => "Declare terminal as: "
59
+ #radio.update_command() {|rb| ENV['TERM']=rb.value }
60
+ item cb
61
+ x.update_command do |rb|
62
+ cb.arrow_key_policy=rb.value.to_sym
63
+ end
64
+
65
+ end
66
+ tab "Conta&iner" do
67
+ item r
68
+ end
69
+ # tell tabbedpane what to do if a button is pressed (ok/apply/cancel)
70
+ command do |eve|
71
+ alert "user pressed button index:#{eve.event} , Name: #{eve.action_command}, Tab: #{eve.source.current_tab} "
72
+ case eve.event
73
+ when 0,2 # ok cancel
74
+ throw :close, eve.event
75
+ when 1 # apply
76
+ end
77
+ end
78
+ end
79
+ tp.run
80
+ end
81
+
82
+ end
83
+ if $0 == __FILE__
84
+ # Initialize curses
85
+ begin
86
+ # XXX update with new color and kb
87
+ VER::start_ncurses # this is initializing colors via ColorMap.setup
88
+ $log = Logger.new((File.join(ENV["LOGDIR"] || "./" ,"rbc13.log")))
89
+ $log.level = Logger::DEBUG
90
+ tp = SetupTabbedPane.new()
91
+ buttonindex = tp.run
92
+ rescue => ex
93
+ ensure
94
+ VER::stop_ncurses
95
+ p ex if ex
96
+ p(ex.backtrace.join("\n")) if ex
97
+ $log.debug( ex) if ex
98
+ $log.debug(ex.backtrace.join("\n")) if ex
99
+ end
100
+ end
@@ -0,0 +1,121 @@
1
+ # this is a test program, tests out tabbed panes. type F1 to exit
2
+ #
3
+ require 'logger'
4
+ require 'rbcurse'
5
+ #require 'rbcurse/core/widgets/newtabbedpane'
6
+ require 'rbcurse/core/widgets/rtabbedpane'
7
+
8
+ class TestTabbedPane
9
+ def initialize
10
+ acolor = $reversecolor
11
+ #$config_hash ||= {}
12
+ end
13
+ def run
14
+ $config_hash ||= Variable.new Hash.new
15
+ #configvar.update_command(){ |v| $config_hash[v.source()] = v.value }
16
+ @window = VER::Window.root_window
17
+ @form = Form.new @window
18
+ r = 1; c = 30;
19
+ @tp = RubyCurses::TabbedPane.new @form do
20
+ height 12
21
+ width 50
22
+ row 13
23
+ col 10
24
+ button_type :ok
25
+ end
26
+ @tab1 = @tp.add_tab "&Language"
27
+ #f1 = @tab1.form
28
+ f1 = @tp.form @tab1
29
+ #$radio = Variable.new
30
+ radio1 = RadioButton.new f1 do
31
+ #variable $radio
32
+ variable $config_hash
33
+ name "radio1"
34
+ text "ruby"
35
+ value "ruby"
36
+ color "red"
37
+ row 4
38
+ col 5
39
+ end
40
+ radio2 = RadioButton.new f1 do
41
+ #variable $radio
42
+ variable $config_hash
43
+ name "radio1"
44
+ text "jruby"
45
+ value "jruby"
46
+ color "green"
47
+ row 5
48
+ col 5
49
+ end
50
+ radio3 = RadioButton.new f1 do
51
+ #variable $radio
52
+ variable $config_hash
53
+ name "radio1"
54
+ text "macruby"
55
+ value "macruby"
56
+ color "cyan"
57
+ row 6
58
+ col 5
59
+ end
60
+ @tab2 = @tp.add_tab "&Settings"
61
+ #f2 = @tab2.form
62
+ f2 = @tp.form @tab2
63
+ r = 4
64
+ butts = [ "Use &HTTP/1.0", "Use &frames", "&Use SSL" ]
65
+ bcodes = %w[ HTTP, FRAMES, SSL ]
66
+ butts.each_with_index do |t, i|
67
+ RubyCurses::CheckBox.new f2 do
68
+ text butts[i]
69
+ variable $config_hash
70
+ name bcodes[i]
71
+ row r+i
72
+ col 5
73
+ end
74
+ end
75
+ @tab3 = @tp.add_tab "&Editors"
76
+ #f3 = @tab3.form
77
+ f3 = @tp.form @tab3
78
+ butts = %w[ &Vim E&macs &Jed &Other ]
79
+ bcodes = %w[ VIM EMACS JED OTHER]
80
+ row = 4
81
+ butts.each_with_index do |name, i|
82
+ RubyCurses::CheckBox.new f3 do
83
+ text name
84
+ variable $config_hash
85
+ name bcodes[i]
86
+ row row+i
87
+ col 5
88
+ end
89
+ end
90
+ @help = "q to quit. Use any key of key combination to see what's caught. Check logger too"
91
+ RubyCurses::Label.new @form, {'text' => @help, "row" => 11, "col" => 2, "color" => "yellow"}
92
+ @form.repaint
93
+ @window.wrefresh
94
+ Ncurses::Panel.update_panels
95
+ while((ch = @window.getchar()) != ?q.getbyte(0) )
96
+ # @tp.repaint
97
+ @form.handle_key(ch)
98
+ @window.wrefresh
99
+ end
100
+ #@tp.show
101
+ #@tp.handle_keys
102
+ end
103
+ end
104
+ if $0 == __FILE__
105
+ # Initialize curses
106
+ begin
107
+ # XXX update with new color and kb
108
+ VER::start_ncurses # this is initializing colors via ColorMap.setup
109
+ $log = Logger.new("rbc13.log")
110
+ $log.level = Logger::DEBUG
111
+ n = TestTabbedPane.new
112
+ n.run
113
+ rescue => ex
114
+ ensure
115
+ VER::stop_ncurses
116
+ p ex if ex
117
+ p(ex.backtrace.join("\n")) if ex
118
+ $log.debug( ex) if ex
119
+ $log.debug(ex.backtrace.join("\n")) if ex
120
+ end
121
+ end
@@ -0,0 +1,68 @@
1
+ # this is a test program, tests out messageboxes. type F1 to exit
2
+ # a quick dirty file chooser in 2 lines of code.
3
+ require 'logger'
4
+ require 'rbcurse/core/system/ncurses'
5
+ require 'rbcurse/core/system/window'
6
+ require 'rbcurse/core/widgets/rwidget'
7
+
8
+ ##
9
+ # a quick dirty file chooser - only temporary till we make something better.
10
+ class QDFileChooser
11
+ attr_accessor :show_folders # bool
12
+ attr_accessor :traverse_folders # bool
13
+ attr_accessor :default_pattern # e.g. "*.*"
14
+ attr_accessor :dialog_title # File Chooser
15
+ def initialize
16
+
17
+ end
18
+ def show_open_dialog
19
+ @form = RubyCurses::Form.new nil
20
+ label = RubyCurses::Label.new @form, {'text' => 'File', 'row'=>3, 'col'=>4, 'color'=>'black', 'bgcolor'=>'white', 'mnemonic'=>'F'}
21
+ field = RubyCurses::Field.new @form do
22
+ name "file"
23
+ row 3
24
+ col 10
25
+ display_length 40
26
+ set_label label
27
+ end
28
+ default_pattern ||= "*.*"
29
+ flist = Dir.glob(default_pattern)
30
+ @listb = RubyCurses::Listbox.new @form do
31
+ name "mylist"
32
+ row 5
33
+ col 10
34
+ width 40
35
+ height 10
36
+ list flist
37
+ title "File list"
38
+ title_attrib 'bold'
39
+ end
40
+ #@listb.list.bind(:ENTER_ROW) { field.set_buffer @listb.selected_item }
41
+ listb = @listb
42
+ field.bind(:CHANGE) do |f|
43
+ flist = Dir.glob(f.getvalue+"*")
44
+ l = listb.list
45
+ l.remove_all
46
+ l.insert 0, *flist
47
+ end
48
+ atitle = @dialog_title || "Quick Dirty(TM) File Chooser"
49
+ @mb = RubyCurses::MessageBox.new @form do
50
+ title atitle
51
+ type :override
52
+ height 20
53
+ width 60
54
+ top 5
55
+ left 20
56
+ default_button 0
57
+ button_type :ok_cancel
58
+ end
59
+ #$log.debug "MBOX :selected #{@listb.selected_item}, #{@listb[@listb.getvalue[0]]} "
60
+ return @mb.selected_index == 0 ? :OK : :CANCEL
61
+ end
62
+ def get_selected_file
63
+ #return @mb.selected_index == 0 ? @listb.selected_item : nil
64
+ #return @mb.selected_index == 0 ? @listb[@listb.getvalue[0]] : nil
65
+ # return either the selected_value or if user pressed okay, then focussed item
66
+ return @mb.selected_index == 0 ? @listb.selected_value || @listb.selected_item : nil
67
+ end
68
+ end
data/examples/rfe.rb ADDED
@@ -0,0 +1,1239 @@
1
+ #####################################################
2
+ # This is a sample program demonstrating a 2 pane file explorer using
3
+ # rbcurse's widgets.
4
+ # I have used a listbox here, perhaps a Table would be more configurable
5
+ # than a listbox.
6
+ #
7
+ # FIXME many popups use the old Messagebox which will crash. i've updated
8
+ # grep not the others.
9
+ # Copyright rkumar 2009, 2010 under Ruby License.
10
+ #
11
+ ####################################################
12
+ #require 'rubygems'
13
+ #require 'ncurses'
14
+ #require 'logger'
15
+ require 'rbcurse'
16
+ require 'rbcurse/core/widgets/rcombo'
17
+ require 'rbcurse/extras/widgets/rlistbox'
18
+ require './rfe_renderer'
19
+ require 'rbcurse/core/widgets/keylabelprinter'
20
+ require 'rbcurse/core/widgets/applicationheader'
21
+ require 'rbcurse/core/include/action'
22
+ require 'fileutils'
23
+ require 'yaml' ## added for 1.9
24
+ #$LOAD_PATH << "/Users/rahul/work/projects/rbcurse/"
25
+
26
+ # TODO
27
+ # operations on selected files: move, delete, zip, copy
28
+ # - delete should move to Trash if exists - DONE
29
+ # global - don't ask confirm
30
+ # Select based on pattern.
31
+ # This class represents the finder pane. There are 2
32
+ # on this sample app
33
+ # NOTE: rfe_renderer uses entries so you may need to sync it with list_data_model
34
+ # actually, renderer should refer back to list data model!
35
+ class FileExplorer
36
+ include FileUtils
37
+ attr_reader :wdir
38
+ attr_reader :list # listbox
39
+ attr_reader :dir
40
+ attr_reader :prev_dirs
41
+ attr_reader :other_list # the opposite list
42
+ attr_reader :entries # avoid, can be outdated
43
+ attr_accessor :filter_pattern
44
+
45
+ def initialize form, rfe, row, col, height, width
46
+ @form = form
47
+ @rfe = rfe
48
+ @row, @col, @ht, @wid = row, col, height, width
49
+ @dir = Dir.new(Dir.getwd)
50
+ @wdir = @dir.path
51
+ @filter_pattern = '*'
52
+ @prev_dirs=[]
53
+ @inside_block = false
54
+ $entry_count = 0 # just for show... may not be accurate after deletes etc
55
+
56
+ end
57
+ def title str
58
+ @list.title = str
59
+ end
60
+ def selected_color
61
+ @list.selected_color
62
+ end
63
+ def selected_bgcolor
64
+ @list.selected_bgcolor
65
+ end
66
+
67
+ # changes to given dir
68
+ # ensure that path is provided since other list
69
+ # may have cd'd elsewhere
70
+ def change_dir adir
71
+ list = @list
72
+ begin
73
+ #dir = File.expand_path dir
74
+ #cd "#{@dir.path}/#{adir}"
75
+ cd adir
76
+ list.title = pwd()
77
+ @dir = Dir.new(Dir.getwd)
78
+ @wdir = @dir.path
79
+ @prev_dirs << @wdir
80
+ rescan
81
+ rescue => err
82
+ @rfe.status_row.text = err.to_s
83
+ end
84
+ end
85
+ def goto_previous_dir
86
+ #alert "Previous dirs contain #{@prev_dirs} "
87
+ d = @prev_dirs.pop
88
+ if !d.nil? && d == @wdir
89
+ d = @prev_dirs.pop
90
+ end
91
+ d = @wdir unless d # for those cases where we are showing some result and user doesn't know how t get back
92
+ change_dir d unless d.nil?
93
+ end
94
+ def filter list
95
+ list.delete_if { |f|
96
+ !File.directory? @wdir +"/"+ f and !File.fnmatch?(@filter_pattern, f)
97
+ }
98
+ #$log.debug " FILTER CALLED AFTER #{list.size}, #{list.entries}"
99
+ end
100
+ def rescan
101
+ flist = @dir.entries
102
+ $entry_count = flist.size # just for show... may not be accurate after deletes etc
103
+ flist.shift
104
+ #populate @entries
105
+ populate flist
106
+ end
107
+ def populate flist
108
+ #fl << format_string("..", nil)
109
+ #fl = []
110
+ #flist.each {|f| ff = "#{@wdir}/#{f}"; stat = File.stat(ff)
111
+ # fl << format_string(f, stat)
112
+ #}
113
+ filter(flist) if @filter_pattern != '*'
114
+ @entries = flist
115
+ list.list_data_model.remove_all
116
+ #list.list_data_model.insert 0, *fl
117
+ list.list_data_model.insert 0, *flist
118
+ list.set_form_row
119
+ #$entry_count = list.size # just for show... may not be accurate after deletes etc
120
+ end
121
+ def sort key, reverse=false
122
+ # remove parent before sorting, keep at top
123
+ first = @entries.delete_at(0) if @entries[0]==".."
124
+ key ||= @sort_key
125
+ cdir=cur_dir()+"/"
126
+ case key
127
+ when :size
128
+ @entries.sort! {|x,y| xs = File.stat(cdir+x); ys = File.stat(cdir+y);
129
+ if reverse
130
+ xs.size <=> ys.size
131
+ else
132
+ ys.size <=> xs.size
133
+ end
134
+ }
135
+ when :mtime
136
+ @entries.sort! {|x,y| xs = File.stat(cdir+x); ys = File.stat(cdir+y);
137
+ if reverse
138
+ xs.mtime <=> ys.mtime
139
+ else
140
+ ys.mtime <=> xs.mtime
141
+ end
142
+ }
143
+ when :atime
144
+ @entries.sort! {|x,y| xs = File.stat(cdir+x); ys = File.stat(cdir+y);
145
+ if reverse
146
+ xs.atime <=> ys.atime
147
+ else
148
+ ys.atime <=> xs.atime
149
+ end
150
+ }
151
+ when :name
152
+ @entries.sort! {|x,y| x <=> y
153
+ if reverse
154
+ x <=> y
155
+ else
156
+ y <=> x
157
+ end
158
+ }
159
+ when :ext
160
+ @entries.sort! {|x,y|
161
+ if reverse
162
+ File.extname(cdir+x) <=> File.extname(cdir+y)
163
+ else
164
+ File.extname(cdir+y) <=> File.extname(cdir+x)
165
+ end
166
+ }
167
+ end
168
+ @sort_key = key
169
+ @entries.insert 0, first unless first.nil? # keep parent on top
170
+ populate @entries
171
+ end
172
+ GIGA_SIZE = 1073741824.0
173
+ MEGA_SIZE = 1048576.0
174
+ KILO_SIZE = 1024.0
175
+
176
+ # Return the file size with a readable style.
177
+ def readable_file_size(size, precision)
178
+ case
179
+ #when size == 1 : "1 B"
180
+ when size < KILO_SIZE then "%d B" % size
181
+ when size < MEGA_SIZE then "%.#{precision}f K" % (size / KILO_SIZE)
182
+ when size < GIGA_SIZE then "%.#{precision}f M" % (size / MEGA_SIZE)
183
+ else "%.#{precision}f G" % (size / GIGA_SIZE)
184
+ end
185
+ end
186
+ def date_format t
187
+ t.strftime "%Y/%m/%d"
188
+ end
189
+ def oldformat_string fn, stat
190
+ max_len = 30
191
+ f = fn.dup
192
+ if File.directory? f
193
+ #"%-*s\t(dir)" % [max_len,f]
194
+ #f = "/"+f # disallows search on keypress
195
+ f = f + "/ "
196
+ end
197
+ if f.size > max_len
198
+ f = f[0..max_len-1]
199
+ end
200
+ "%-*s\t%10s\t%s" % [max_len,f, readable_file_size(stat.size,1), date_format(stat.mtime)]
201
+ end
202
+ def cur_dir
203
+ @dir.path
204
+ end
205
+ alias :current_dir :cur_dir
206
+ def draw_screen dir=nil
207
+ # I get an error here if dir in yaml file is non-existent, like deleted or copied from another machine
208
+ # 2010-08-22 19:25
209
+ if dir
210
+ if File.exists?(dir) && File.directory?(dir)
211
+ cd dir unless dir.nil?
212
+ else
213
+ dir = nil
214
+ end
215
+ end
216
+
217
+ wdir = FileUtils.pwd
218
+ @prev_dirs << wdir
219
+ @dir = Dir.new(Dir.getwd)
220
+ @wdir = @dir.path
221
+ r = @row
222
+ c = @col
223
+ #cola = 1
224
+ #colb = Ncurses.COLS/2
225
+ ht = @ht
226
+ wid = @wid
227
+ #fl = Dir.glob(default_pattern)
228
+ #flist << format_string("..", nil)
229
+ fl = @dir.entries
230
+ fl.shift
231
+ filter(fl)
232
+ #flist = []
233
+ #fl.each {|f| stat = File.stat(f)
234
+ # flist << format_string(f, stat)
235
+ #}
236
+ @entries = fl
237
+ $entry_count = @entries.size
238
+ title = pwd()
239
+ @wdir = title
240
+ rfe = self
241
+
242
+ lista = Listbox.new @form do
243
+ name "lista"
244
+ row r
245
+ col c
246
+ width wid
247
+ height ht
248
+ #list flist
249
+ list fl
250
+ title wdir
251
+ #title_attrib 'reverse'
252
+ cell_renderer RfeRenderer.new "", {"color"=>@color, "bgcolor"=>@bgcolor, "parent" => rfe, "display_length"=> wid-2}
253
+ KEY_ROW_SELECTOR 0 # C-space since space used for preview
254
+ end
255
+ @list = lista
256
+ lista.bind(:ENTER) {|l| @rfe.current_list(self); l.title_attrib 'reverse'; }
257
+ lista.bind(:LEAVE) {|l| l.title_attrib 'normal'; }
258
+
259
+
260
+ #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 }
261
+ row_cmd = lambda {|lb, list| file = list.entries[lb.current_index]; @rfe.status_row.text = file; # File.stat("#{cur_dir()}/#{file}").inspect
262
+ }
263
+ lista.bind(:ENTER_ROW, self) {|lb,list| row_cmd.call(lb,list) }
264
+
265
+ end
266
+ def list_data
267
+ @list.list_data_model
268
+ end
269
+ def current_index
270
+ @list.current_index
271
+ end
272
+ def filename ix=current_index()
273
+ #@entries[@list.current_index]
274
+ list_data()[ix]
275
+ end
276
+ def filepath ix=current_index()
277
+ f = filename(ix)
278
+ return unless f
279
+ if f[0,1]=='/'
280
+ f
281
+ else
282
+ cur_dir() + "/" + f
283
+ end
284
+ end
285
+ # delete the item at position i
286
+ def delete_at i=@list.current_index
287
+ ret = @list.list_data_model.delete_at i
288
+ ret = @entries.delete_at i
289
+ end
290
+ def delete obj
291
+ ret = @list.list_data_model.delete obj
292
+ ret = @entries.delete_at obj
293
+ end
294
+ def insert_at obj, ix = @list.current_index
295
+ @list.list_data_model.insert ix, f
296
+ @entries.insert ix, obj
297
+ end
298
+ def remove_selected_rows
299
+ rows = @list.selected_rows
300
+ rows=rows.sort! {|x,y| y <=> x }
301
+ rows.each do |i|
302
+ ret = @list.list_data_model.delete_at i
303
+ ret = @entries.delete_at i
304
+ end
305
+ end
306
+
307
+ # ADD
308
+ end
309
+ class RFe
310
+ attr_reader :status_row
311
+ def initialize
312
+ @window = VER::Window.root_window
313
+ @form = Form.new @window
314
+ # made in invisible since i am using chunks to print. however, we do set this variable
315
+ status_row = RubyCurses::Label.new @form, {'text' => "", :row => Ncurses.LINES-4, :col => 0, :display_length=>Ncurses.COLS-2, :visible => false}
316
+ @status_row = status_row
317
+ colb = Ncurses.COLS/2
318
+ ht = Ncurses.LINES - 4
319
+ wid = Ncurses.COLS/2 - 0
320
+ @trash_path = File.expand_path("~/.Trash")
321
+ @trash_exists = File.directory? @trash_path
322
+ $log.debug " trash_path #{@trash_path}, #{@trash_exists}"
323
+ @lista = FileExplorer.new @form, self, row=1, col=1, ht, wid
324
+ @listb = FileExplorer.new @form, self, row=1, col=colb, ht, wid
325
+
326
+ init_vars
327
+ end
328
+ def init_vars
329
+ @bookmarks=[]
330
+ @config_name = File.expand_path("~/.rfe.yml")
331
+ if File.exist? @config_name
332
+ @config = YAML::load( File.open(@config_name));
333
+ if !@config.nil?
334
+ @bookmarks = @config["bookmarks"]||[]
335
+ @last_dirs = @config["last_dirs"]
336
+ end
337
+ end
338
+ @config ||={}
339
+ @stopping = false
340
+ end
341
+ def save_config
342
+ @config["last_dirs"]=[@lista.current_dir(),@listb.current_dir()]
343
+ File.open(@config_name, "w") { | f | YAML.dump( @config, f )}
344
+ end
345
+ def move
346
+ fp = @current_list.filepath #.gsub(' ',"\ ")
347
+ fn = @current_list.filename
348
+ $log.debug " FP #{fp}"
349
+ other_list = [@lista, @listb].index(@current_list)==0 ? @listb : @lista
350
+ other_dir = other_list.cur_dir
351
+ $log.debug " OL #{other_list.cur_dir}"
352
+ if @current_list.list.selected_row_count == 0
353
+ str= "#{fn}"
354
+ else
355
+ str= "#{@current_list.list.selected_row_count} files "
356
+ end
357
+
358
+ mb = RubyCurses::MessageBox.new :width => 80 do
359
+ title "Move"
360
+ message "Move #{str} to"
361
+ add Field.new :default => other_dir, :bgcolor => :cyan, :name => "name"
362
+ button_type :ok_cancel
363
+ default_button 0
364
+ end
365
+ index = mb.run
366
+ fld = mb.widget("name")
367
+
368
+ #mb = RubyCurses::MessageBox.new do
369
+ #title "Move"
370
+ #message "Move #{str} to"
371
+ #type :input
372
+ #width 80
373
+ #default_value other_dir
374
+ #button_type :ok_cancel
375
+ #default_button 0
376
+ #end
377
+ #confirm "selected :#{mb.input_value}, #{mb.selected_index}"
378
+ if index == 0
379
+ begin
380
+ if @current_list.list.selected_row_count == 0
381
+ FileUtils.move(fp, fld.text)
382
+ #ret = @current_list.list.list().delete_at @current_list.list.current_index # ???
383
+ # @current_list.entries.delete_at @current_list.current_index
384
+ @current_list.delete_at
385
+ else
386
+ each_selected_row do |f|
387
+ FileUtils.move(f, fld.text)
388
+ end
389
+ @current_list.remove_selected_rows
390
+ @current_list.list.clear_selection
391
+ end
392
+ rescue => err
393
+ textdialog err
394
+ $log.debug "XXX: Exception in rfe, move #{err.to_s} "
395
+ end
396
+ other_list.rescan
397
+ end
398
+ end
399
+ def each_selected_row #title, message, default_value
400
+ rows = @current_list.list.selected_rows
401
+ rows = rows.dup
402
+ rows.each do |i|
403
+ fp = @current_list.filepath i
404
+ #$log.debug " moving #{i}: #{fp}"
405
+ #FileUtils.move(fp, mb.input_value)
406
+ yield fp
407
+ end
408
+ end
409
+ def copy
410
+ fp = @current_list.filepath #.gsub(' ',"\ ")
411
+ fn = @current_list.filename
412
+ $log.debug " FP #{fp}"
413
+ other_list = [@lista, @listb].index(@current_list)==0 ? @listb : @lista
414
+ other_dir = other_list.cur_dir
415
+ $log.debug " OL #{other_list.cur_dir}"
416
+ if @current_list.list.selected_row_count == 0
417
+ str= "#{fn}"
418
+ else
419
+ str= "#{@current_list.list.selected_row_count} files "
420
+ end
421
+ mb = RubyCurses::MessageBox.new do
422
+ title "Copy"
423
+ message "Copy #{str} to"
424
+ type :input
425
+ width 80
426
+ default_value other_dir
427
+ button_type :ok_cancel
428
+ default_button 0
429
+ end
430
+ if mb.selected_index == 0
431
+ if @current_list.list.selected_row_count == 0
432
+ FileUtils.copy(fp, mb.input_value)
433
+ else
434
+ each_selected_row do |f|
435
+ FileUtils.copy(f, mb.input_value)
436
+ end
437
+ @current_list.list.clear_selection
438
+ end
439
+ other_list.rescan
440
+ end
441
+ end
442
+ def delete
443
+ fp = @current_list.filepath #.gsub(' ',"\ ")
444
+ fn = @current_list.filename
445
+ if @current_list.list.selected_row_count == 0
446
+ str= "#{fn}"
447
+ else
448
+ str= "#{@current_list.list.selected_row_count} files "
449
+ end
450
+ if confirm("delete #{str}")
451
+ if @current_list.list.selected_row_count == 0
452
+ if @trash_exists
453
+ FileUtils.mv fp, @trash_path
454
+ else
455
+ FileUtils.rm fp
456
+ end
457
+ ret=@current_list.delete_at
458
+ else
459
+ each_selected_row do |f|
460
+ if @trash_exists
461
+ FileUtils.mv f, @trash_path
462
+ else
463
+ FileUtils.rm f
464
+ end
465
+ end
466
+ @current_list.remove_selected_rows
467
+ @current_list.list.clear_selection
468
+ end
469
+ end
470
+ end
471
+ def copy1
472
+ fp = @current_list.filepath
473
+ fn = @current_list.filename
474
+ $log.debug " FP #{fp}"
475
+ other_list = [@lista, @listb].index(@current_list)==0 ? @listb : @lista
476
+ other_dir = other_list.cur_dir
477
+ $log.debug " OL #{other_list.cur_dir}"
478
+ str= "copy #{fn} to #{other_list.cur_dir}"
479
+ $log.debug " copy #{fp}"
480
+ #confirm "#{str}"
481
+ mb = RubyCurses::MessageBox.new do
482
+ title "Copy"
483
+ message "Copy #{fn} to"
484
+ type :input
485
+ width 60
486
+ default_value other_dir
487
+ button_type :ok_cancel
488
+ default_button 0
489
+ end
490
+ #confirm "selected :#{mb.input_value}, #{mb.selected_index}"
491
+ if mb.selected_index == 0
492
+ # need to redraw directories
493
+ FileUtils.copy(fp, mb.input_value)
494
+ other_list.rescan
495
+ end
496
+ end
497
+ ## TODO : make this separate and callable with its own keylabels
498
+ # Now you can just use viewer() instead of having to write this. See Utils in rwidget.rb
499
+ def view content=nil # can throw IO errors
500
+ require 'rbcurse/core/widgets/rtextview'
501
+ wt = 0
502
+ wl = 0
503
+ wh = Ncurses.LINES-wt
504
+ ww = Ncurses.COLS-wl
505
+ if content.nil?
506
+ begin
507
+ fp = @current_list.filepath
508
+ content = get_contents(fp)
509
+ rescue => err
510
+ $log.debug err.to_s
511
+ $log.debug(err.backtrace.join("\n"))
512
+ alert err.to_s
513
+ return
514
+ end
515
+ else
516
+ fp=""
517
+ end
518
+ @layout = { :height => wh, :width => ww, :top => wt, :left => wl }
519
+ @v_window = VER::Window.new(@layout)
520
+ @v_form = RubyCurses::Form.new @v_window
521
+ @textview = TextView.new @v_form do
522
+ name "myView"
523
+ row 0
524
+ col 0
525
+ width ww
526
+ height wh-0
527
+ title fp
528
+ title_attrib 'bold'
529
+ print_footer true
530
+ footer_attrib 'bold'
531
+ end
532
+ #content = File.open(fp,"r").readlines
533
+ begin
534
+ @textview.set_content content #, :WRAP_WORD
535
+ @v_form.repaint
536
+ @v_window.wrefresh
537
+ Ncurses::Panel.update_panels
538
+ while((ch = @v_window.getchar()) != ?\C-q.getbyte(0) )
539
+ break if ch == FFI::NCurses::KEY_F3 || ch == KEY_F10 || ch == ?q.getbyte(0)
540
+ @v_form.handle_key ch
541
+ @v_form.repaint
542
+ ##@v_window.wrefresh
543
+ end
544
+ rescue => err
545
+ alert err.to_s
546
+ ensure
547
+ @v_window.destroy if !@v_window.nil?
548
+ end
549
+ end
550
+ def get_contents fp
551
+ return nil unless File.readable? fp
552
+ return Dir.new(fp).entries if File.directory? fp
553
+ case File.extname(fp)
554
+ when '.tgz','.gz'
555
+ cmd = "tar -ztvf #{fp}"
556
+ content = %x[#{cmd}]
557
+ when '.zip'
558
+ cmd = "unzip -l #{fp}"
559
+ content = %x[#{cmd}]
560
+ else
561
+ content = File.open(fp,"r").readlines
562
+ end
563
+ end
564
+ def opt_file c
565
+ fp = @current_list.filepath
566
+ fn = @current_list.filename
567
+ other_list = [@lista, @listb].index(@current_list)==0 ? @listb : @lista
568
+ case c
569
+ when 'c'
570
+ copy
571
+ when 'm'
572
+ move
573
+ when 'd'
574
+ delete
575
+ when 'u'
576
+ str= "move #{fn} to #{other_list.cur_dir}"
577
+ if confirm("#{str}")
578
+ $log.debug " MOVE #{str}"
579
+ end
580
+ when 'v'
581
+ str= "view #{fp}"
582
+ #if confirm("#{str}")==:YES
583
+ $log.debug " VIEW #{fp}"
584
+ view
585
+ #end
586
+ when 'r'
587
+ str= "ruby #{fn}"
588
+ if confirm("#{str}")
589
+ $log.debug " #{str} "
590
+ end
591
+ when 'e'
592
+ str= "edit #{fp}"
593
+ #if confirm("#{str}")==:YES
594
+ edit fp
595
+ when 'x'
596
+ str= "exec #{fp}"
597
+ exec_popup fp
598
+ when 'p'
599
+ page fp
600
+ when 'q'
601
+ qlmanage fp
602
+ end
603
+ end
604
+ def opt_dir c
605
+ fp = @current_list.filepath
606
+ fn = @current_list.filename
607
+ case c
608
+ when 'O'
609
+ # str= "copy #{fn} to #{other_list.cur_dir}"
610
+ if File.directory? @current_list.filepath
611
+ @current_list.change_dir fp
612
+ end
613
+ when 'o'
614
+ if File.directory? @current_list.filepath
615
+ @other_list.change_dir fp
616
+ end
617
+ @open_in_other = true # ???basically keep opening in other
618
+ when 'd'
619
+ str= "delete #{fn} "
620
+ if confirm("#{str}")
621
+ $log.debug " delete #{fp}"
622
+ FileUtils.rm fp
623
+ ret=@current_list.list.list_data_model.delete_at @current_list.list.current_index # ???
624
+ $log.debug " DEL RET #{ret},#{@current_list.list.current_index}"
625
+ end
626
+ when 'u'
627
+ str= "move #{fn} to #{other_list.cur_dir}"
628
+ if confirm("#{str}")
629
+ $log.debug " MOVE #{str}"
630
+ end
631
+ when 'b'
632
+ dd = @current_list.wdir
633
+ @bookmarks << dd unless @bookmarks.include? dd
634
+ when 'u'
635
+ dd = @current_list.wdir
636
+ @bookmarks.delete dd
637
+ when 'l'
638
+ @current_list.populate @bookmarks
639
+ when 's'
640
+ @config["bookmarks"] = @bookmarks
641
+ save_config
642
+ when 'e'
643
+ str= "edit #{fp}"
644
+ #if confirm("#{str}")==:YES
645
+ edit fp
646
+ when 'm'
647
+ f = get_string("Enter a directory to create", 20 )
648
+ if f != ""
649
+ FileUtils.mkdir f
650
+ @current_list.list.list_data_model.insert @current_list.list.current_index, f # ???
651
+ @current_list.entries.insert @current_list.list.current_index, f # ???
652
+ end
653
+
654
+ when 'x'
655
+ str= "exec #{fp}"
656
+ exec_popup fp
657
+ end
658
+ end
659
+ def exec_popup fp
660
+ last_exec_def1 = @last_exec_def1 || ""
661
+ last_exec_def2 = @last_exec_def2 || false
662
+
663
+ 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]})
664
+ if sel == 0
665
+ @last_exec_def1 = inp
666
+ @last_exec_def2 = hash["view result"]
667
+ cmd = "#{inp} #{fp}"
668
+ filestr = %x[ #{cmd} 2>/dev/null ]
669
+ if hash["view result"]==true
670
+ view filestr
671
+ end
672
+ end
673
+ end
674
+ def edit fp=@current_list.filepath
675
+ $log.debug " edit #{fp}"
676
+ editor = ENV['EDITOR'] || 'vi'
677
+ vimp = %x[which #{editor}].chomp
678
+ shell_out "#{vimp} #{fp}"
679
+ end
680
+
681
+ # TODO we need to move these to some common file so differnt programs and demos
682
+ # can use them on pressing space or enter.
683
+ def page fp=@current_list.filepath
684
+ ft=%x[file #{fp}]
685
+ if ft.index("text")
686
+ pager = ENV['PAGER'] || 'less'
687
+ vimp = %x[which #{pager}].chomp
688
+ shell_out "#{vimp} #{fp}"
689
+ elsif ft.index(/zip/i)
690
+ shell_out "tar tvf #{fp} | less"
691
+ elsif ft.index(/directory/i)
692
+ shell_out "ls -lh #{fp} | less"
693
+ else
694
+ alert "#{fp} is not text, not paging "
695
+ #use_on_file "als", fp # only zip or archive
696
+ end
697
+ end
698
+ def qlmanage fp=@current_list.filepath
699
+ begin
700
+ a=%x[which qlmanage]
701
+ if a != ""
702
+ cmd="qlmanage -p #{@current_list.filepath} 2>/dev/null"
703
+ %x[#{cmd}]
704
+ else
705
+ alert "qlmanage not present on your system. Trying pager"
706
+ page fp
707
+ end
708
+ rescue Interrupt
709
+ rescue => err
710
+ alert err.to_s
711
+ end
712
+ end
713
+ # also if calling program gives output but does not stop
714
+ # or take control, then nothing will show up
715
+ def use_on_file prog, args, fp=@current_list.filepath
716
+ vimp = %x[which #{prog}].chomp
717
+ if vimp != ""
718
+ alert "using #{prog} "
719
+ shell_out "#{vimp} #{args } #{fp}"
720
+ else
721
+ alert "could not locate #{prog} "
722
+ end
723
+ end
724
+ def stopping?
725
+ @stopping
726
+ end
727
+ def draw_screens
728
+ lasta = lastb = nil
729
+ if !@config["last_dirs"].nil?
730
+ lasta = @config["last_dirs"][0]
731
+ lastb = @config["last_dirs"][1]
732
+ end
733
+ @lista.draw_screen lasta
734
+ @listb.draw_screen lastb
735
+
736
+ # bind dd to delete file
737
+ # actually this should be in listbox, and we should listen for row delete and then call opt_file
738
+ @form.bind_key([?d,?d], 'delete'){
739
+ opt_file 'd'
740
+ }
741
+ # list traps 'q' so this won't work
742
+ @form.bind_key([?q,?q], 'quit'){
743
+ @stopping = true
744
+ }
745
+ # this won't work since the listbox will consume the d first
746
+ @form.bind_key(?@, 'home'){
747
+ @current_list.change_dir File.expand_path("~/")
748
+ }
749
+ @form.bind_key(?^, 'previous dir'){
750
+ @current_list.change_dir @current_list.prev_dirs[0] unless @current_list.prev_dirs.empty?
751
+ }
752
+ @form.bind_key(?\C-f, 'file menu'){
753
+ @klp.mode :file
754
+ @klp.repaint
755
+ while((ch = @window.getchar()) != ?\C-c.getbyte(0) )
756
+ if ch < 33 || ch > 126
757
+ Ncurses.beep
758
+ elsif "cmdsuvrexpq".index(ch.chr) == nil
759
+ Ncurses.beep
760
+ else
761
+ opt_file ch.chr
762
+ break
763
+ end
764
+ end
765
+ @klp.mode :normal
766
+ }
767
+ # C-d has been bound to scroll-down
768
+ @form.bind_key(?\C-w, 'dir menu'){
769
+ @klp.mode :dir
770
+ @klp.repaint
771
+ keys = @klp.get_current_keys
772
+ while((ch = @window.getchar()) != ?\C-c.getbyte(0) )
773
+ if ch < 33 || ch > 126
774
+ Ncurses.beep
775
+ elsif !keys.include?(ch.chr)
776
+ Ncurses.beep
777
+ else
778
+ opt_dir ch.chr
779
+ break
780
+ end
781
+ end
782
+ @klp.mode :normal
783
+ }
784
+ # backspace KEY_BS
785
+ @form.bind_key(127, 'previous dir'){
786
+ @current_list.goto_previous_dir
787
+ }
788
+ # form gives this to list which consumes it for selection.
789
+ # need to bind to list's LIST_SELECTION_EVENT
790
+ @form.bind_key(32, 'pager'){
791
+ fp = @current_list.filepath
792
+ page fp
793
+ }
794
+ @form.bind_key(FFI::NCurses::KEY_F3, 'view'){
795
+ begin
796
+ view()
797
+ rescue => err
798
+ alert err.to_s
799
+ end
800
+ }
801
+ @form.bind_key(FFI::NCurses::KEY_F1, 'help'){
802
+ #Io.view(["this is some help text","hello there"])
803
+ color0 = get_color($promptcolor, 'black','green')
804
+ color1 = get_color($reversecolor, 'green','black')
805
+ color2 = get_color($reversecolor, 'magenta','black')
806
+ arr = []
807
+ #arr << " FILE BROWSER HELP "
808
+ arr << [color0," FILE BROWSER HELP ", FFI::NCurses::A_NORMAL]
809
+ arr << " "
810
+ arr << [[color1," <tab> ",nil],[color2, "- switch between windows", nil]]
811
+ arr << [[color1," <enter> ",nil],[color2, "- open dir", nil]]
812
+ arr << [[color1," F3 ",nil],[color2, "- view file/dir/zip contents (toggle) ", nil]]
813
+ arr << [[color1," F4 ",nil],[color2, "- edit file content", nil]]
814
+ arr << [[color1," <char> ", nil],[color2, "first file starting with <char>",nil]]
815
+ #arr << " VIM MODE "
816
+ arr << [color0," VIM MODE ", FFI::NCurses::A_NORMAL]
817
+ arr << [[color1," M",nil],[color2, "-v - Vim like bindings for navigation (toggle)", nil]]
818
+ arr << " jk gg G up down motion, C-n C-p, Alt-0, Alt-9 "
819
+ arr << [[color1," p or Space ",nil],[color2, "- use pager on current file", nil]]
820
+ arr << [[color1," q ",nil],[color2, "- use qlmanage on file ",nil],[$promptcolor, " (OSX)", nil]]
821
+ arr << [[color1," f<char> ",nil],[color2, "- first file starting with <char>", nil]]
822
+
823
+ arr << " "
824
+ arr << " < > ^ V - move help window "
825
+ arr << " "
826
+ # next line does not work due to chunks
827
+ w = arr.max_by(&:length).length
828
+ #arr = ["this is some help text","hello there"]
829
+
830
+ require 'rbcurse/core/util/viewer'
831
+ RubyCurses::Viewer.view(arr, :layout => [10,10, 4+arr.size, w+2],:close_key => KEY_RETURN, :title => "<Enter> to close", :print_footer => false) do |t|
832
+ # you may configure textview further here.
833
+ #t.suppress_borders true
834
+ #t.color = :black
835
+ #t.bgcolor = :white
836
+ # or
837
+ #t.attr = :reverse
838
+ t.attr = :normal
839
+ #t.bind_key(KEY_F1){ alert "closing up!"; throw :close }
840
+ # just for kicks move window around
841
+ t.bind_key('<'){ f = t.form.window; c = f.left - 1; f.hide; f.mvwin(f.top, c); f.show;
842
+ f.reset_layout([f.height, f.width, f.top, c]);
843
+ }
844
+ t.bind_key('>'){ f = t.form.window; c = f.left + 1; f.hide; f.mvwin(f.top, c);
845
+ f.reset_layout([f.height, f.width, f.top, c]); f.show;
846
+ }
847
+ t.bind_key('^'){ f = t.form.window; c = f.top - 1 ; f.hide; f.mvwin(c, f.left);
848
+ f.reset_layout([f.height, f.width, c, f.left]) ; f.show;
849
+ }
850
+ t.bind_key('V'){ f = t.form.window; c = f.top + 1 ; f.hide; f.mvwin(c, f.left);
851
+ f.reset_layout([f.height, f.width, c, f.left]); f.show;
852
+ }
853
+ end
854
+ }
855
+ @form.bind_key(FFI::NCurses::KEY_F4, 'edit'){
856
+ edit()
857
+ }
858
+ @form.bind_key(FFI::NCurses::KEY_F6, 'sort'){
859
+ selected_index, sort_key, reverse, case_sensitive = sort_popup
860
+ if selected_index == 0
861
+ @current_list.sort(sort_key, reverse)
862
+ end
863
+ }
864
+ @form.bind_key(FFI::NCurses::KEY_F5, 'filter'){
865
+ filter()
866
+ }
867
+ @form.bind_key(FFI::NCurses::KEY_F7, 'grep'){
868
+ grep_popup()
869
+ }
870
+ @form.bind_key(FFI::NCurses::KEY_F8, 'system'){
871
+ system_popup()
872
+ }
873
+ # will work if you are in vim mode
874
+ @form.bind_key(?p, 'pager'){
875
+ page
876
+ }
877
+ @form.bind_key(?z, 'qlmanage OSX'){
878
+ qlmanage
879
+ }
880
+ # will no longer come here. list event has to be used
881
+ #@form.bind_key(?\C-m){ # listbox has eaten it up
882
+ @lista.list.bind(:PRESS){
883
+ dir = @current_list.filepath
884
+ if File.directory? @current_list.filepath
885
+ @current_list.change_dir dir
886
+ end
887
+ }
888
+ @listb.list.bind(:PRESS){
889
+ dir = @current_list.filepath
890
+ if File.directory? @current_list.filepath
891
+ @current_list.change_dir dir
892
+ end
893
+ }
894
+ gw = get_color($reversecolor, 'green', 'black')
895
+ bw = get_color($datacolor, 'blue', 'black')
896
+ @klp = RubyCurses::KeyLabelPrinter.new @form, get_key_labels
897
+ @klp.footer_color_pair = bw
898
+ @klp.footer_mnemonic_color_pair = gw
899
+ @klp.set_key_labels get_key_labels(:file), :file
900
+ @klp.set_key_labels get_key_labels(:view), :view
901
+ @klp.set_key_labels get_key_labels(:dir), :dir
902
+ @form.repaint
903
+ @window.wrefresh
904
+ Ncurses::Panel.update_panels
905
+ begin
906
+ chunks=["File","Key"]
907
+ color0 = get_color($promptcolor, 'white','blue')
908
+ color1 = get_color($datacolor, 'black','green')
909
+
910
+ ## qq stops program, but only if M-v (vim mode)
911
+ while(!stopping? && (ch = @window.getchar()) != ?\C-q.getbyte(0) )
912
+ break if ch == KEY_F10
913
+ s = keycode_tos ch
914
+ #status_row.text = "| Pressed #{ch} , #{s}"
915
+ @form.handle_key(ch)
916
+
917
+ # the following is just a test of show_colored_chunks
918
+ # Please use status_line introduced in 1.4.x
919
+ #count = @current_list.list.size
920
+ count1 = @lista.list.size
921
+ count2 = @listb.list.size
922
+ x, y = FFI::NCurses::getyx @window.get_window
923
+ chunks[0]=[color0, "%-30s" % status_row.text, FFI::NCurses::A_BOLD]
924
+ chunks[1]=[color1, "%-18s" % " | #{ch}, #{s} |", FFI::NCurses::A_NORMAL]
925
+ chunks[2]=[color0, " Total: #{count1}, #{count2}"]
926
+ @window.wmove(Ncurses.LINES-3,0)
927
+ @window.color_set(color0, nil)
928
+ @window.print_empty_line
929
+ @window.wmove(Ncurses.LINES-3,0)
930
+ @window.show_colored_chunks chunks
931
+ @window.wmove(x,y)
932
+
933
+ #@form.repaint
934
+ @window.wrefresh
935
+ end
936
+ ensure
937
+ @window.destroy if !@window.nil?
938
+ save_config
939
+ end
940
+
941
+ end
942
+ # TODO
943
+ #
944
+ #
945
+ #
946
+
947
+ # current_list
948
+ ##
949
+ # getter and setter for current_list
950
+ def current_list(*val)
951
+ if val.empty?
952
+ @current_list
953
+ else
954
+ @current_list = val[0]
955
+ @other_list = [@lista, @listb].index(@current_list)==0 ? @listb : @lista
956
+ end
957
+ end
958
+ def get_key_labels categ=nil
959
+ if categ.nil?
960
+ key_labels = [
961
+ ['C-q', 'Exit'], ['C-v', 'View'],
962
+ ['C-f', 'File'], ['C-w', 'Dir'],
963
+ ['C-Sp','Select'], ['Spc', "Preview"],
964
+ ['F3', 'View'], ['F4', 'Edit'],
965
+ ['F5', 'Filter'], ['F6', 'Sort'],
966
+ ['F7', 'Grep'], ['F8', 'System'],
967
+ ['M-0', 'Top'], ['M-9', 'End'],
968
+ ['C-p', 'PgUp'], ['C-n', 'PgDn'],
969
+ ['M-v', 'Vim Mode'], ['BSpc', 'PrevDir']
970
+ ]
971
+ elsif categ == :file
972
+ key_labels = [
973
+ ['c', 'Copy'], ['m', 'Move'],
974
+ ['d', 'Delete'], ['v', 'View'],
975
+ ['s', 'Select'], ['u', 'Unselect'],
976
+ ['p', 'Page'], ['x', 'Exec Cmd'],
977
+ ['r', 'ruby'], ['e', "Edit"],
978
+ ['C-c', 'Cancel']
979
+ ]
980
+ elsif categ == :view
981
+ key_labels = [
982
+ ['c', 'Date'], ['m', 'Size'],
983
+ ['d', 'Delete'], ['v', 'View'],
984
+ ['C-c', 'Cancel']
985
+ ]
986
+ elsif categ == :dir
987
+ key_labels = [
988
+ ['o', 'open'], ['O', 'Open in right'],
989
+ ['d', 'Delete'], ['R', 'Del Recurse'],
990
+ ['t', 'tree'], ['p', 'Previous'],
991
+ ['b', 'Bookmark'], ['u', 'Unbookmark'],
992
+ ['l', 'List'], ['s', 'Save'],
993
+ ['m', 'mkdir'], nil,
994
+ ['C-c', 'Cancel']
995
+ ]
996
+ end
997
+ return key_labels
998
+ end
999
+ def get_key_labels_table
1000
+ key_labels = [
1001
+ ['M-n','NewRow'], ['M-d','DelRow'],
1002
+ ['C-x','Select'], nil,
1003
+ ['M-0', 'Top'], ['M-9', 'End'],
1004
+ ['C-p', 'PgUp'], ['C-n', 'PgDn'],
1005
+ ['M-Tab','Nxt Fld'], ['Tab','Nxt Col'],
1006
+ ['+','Widen'], ['-','Narrow']
1007
+ ]
1008
+ return key_labels
1009
+ end
1010
+ def sort_popup
1011
+ #mform = RubyCurses::Form.new nil
1012
+ mform = nil
1013
+ field_list = []
1014
+ r = 4
1015
+ $radio = RubyCurses::Variable.new
1016
+ rtextvalue = [:name, :ext, :size, :mtime, :atime]
1017
+ ["Name", "Extension", "Size", "Modify Time", "Access Time" ].each_with_index do |rtext,ix|
1018
+ field = RubyCurses::RadioButton.new mform do
1019
+ variable $radio
1020
+ text rtext
1021
+ value rtextvalue[ix]
1022
+ color 'black'
1023
+ bgcolor 'white'
1024
+ #row r
1025
+ #col 5
1026
+ end
1027
+ field_list << field
1028
+ r += 1
1029
+ end
1030
+ r = 4
1031
+ ["Reverse", "case sensitive"].each do |cbtext|
1032
+ field = RubyCurses::CheckBox.new mform do
1033
+ text cbtext
1034
+ name cbtext
1035
+ color 'black'
1036
+ bgcolor 'white'
1037
+ #row r
1038
+ #col 30
1039
+ end
1040
+ field_list << field
1041
+ r += 1
1042
+ end
1043
+ mb = RubyCurses::MessageBox.new :width => 50 do
1044
+ title "Sort Options"
1045
+ button_type :ok_cancel
1046
+ default_button 0
1047
+ end
1048
+ field_list.each { |e| mb.add(e) }
1049
+ index = mb.run
1050
+ if index == 0
1051
+ $log.debug " SORT POPUP #{$radio.value}"
1052
+ #$log.debug " SORT POPUP #{mb.inspect}"
1053
+ $log.debug " SORT POPUP #{mb.widget("Reverse").value}"
1054
+ $log.debug " SORT POPUP #{mb.widget("case sensitive").value}"
1055
+ end
1056
+ return index, $radio.value, mb.widget("Reverse").value, mb.widget("case sensitive").value
1057
+ end
1058
+ def filter
1059
+ f = get_string("Enter a filter pattern", :maxlen => 20, :default => "*")
1060
+ f = "*" if f.nil? or f == ""
1061
+ @current_list.filter_pattern = f
1062
+ @current_list.rescan
1063
+ end
1064
+
1065
+ # ask user for pattern to grep through files
1066
+ # and display file names in same list
1067
+ # Please see testmessagebox.rb for cleaner ways of creating messageboxes.
1068
+
1069
+ def grep_popup
1070
+ last_regex = @last_regex || ""
1071
+ last_pattern = @last_pattern || "*"
1072
+ r = 4
1073
+ mform = nil
1074
+ field = RubyCurses::Field.new mform do
1075
+ name "regex"
1076
+ #row r
1077
+ #col 30
1078
+ set_buffer last_regex
1079
+ label 'Regex'
1080
+ #set_label Label.new @form, {'text' => 'Regex', 'col'=>5, 'mnemonic'=> 'R'}
1081
+ end
1082
+ r += 1
1083
+ field1 = RubyCurses::Field.new mform do
1084
+ name "filepattern"
1085
+ #row r
1086
+ #col 30
1087
+ set_buffer last_pattern
1088
+ label 'File Pattern'
1089
+ #set_label Label.new @form, {'text' => 'File Pattern','col'=>5, :color=>'black',:bgcolor=>'white','mnemonic'=> 'F'}
1090
+ end
1091
+ r += 1
1092
+ fields = []
1093
+ ["Recurse", "case insensitive"].each do |cbtext|
1094
+ fields.push(RubyCurses::CheckBox.new(mform) do
1095
+ text cbtext
1096
+ name cbtext
1097
+ #color 'black'
1098
+ #bgcolor 'white'
1099
+ #row r
1100
+ #col 5
1101
+ end
1102
+ )
1103
+ r += 1
1104
+ end
1105
+ mb = RubyCurses::MessageBox.new :width => 50 do
1106
+ title "Grep Options"
1107
+ button_type :ok_cancel
1108
+ default_button 0
1109
+ item field
1110
+ item field1
1111
+ item fields.first
1112
+ item fields.last
1113
+ end
1114
+ selected_index = mb.run
1115
+ if selected_index == 0
1116
+ return if mb.form.by_name["regex"].getvalue()==""
1117
+ @last_regex = mb.form.by_name["regex"].getvalue
1118
+ inp = mb.form.by_name["regex"].getvalue
1119
+ fp = mb.form.by_name["filepattern"].getvalue
1120
+ @last_pattern = fp
1121
+ flags=""
1122
+ #flags << " -i " if mb.form.by_name["case insensitive"].value==true
1123
+ #flags << " -R " if mb.form.by_name["Recurse"].value==true
1124
+ flags << " -i " if fields[0].value==true
1125
+ flags << " -R " if fields[1].value==true
1126
+ # sometimes grep pukes "No such file or directory if you specify some
1127
+ # filespec that is not present. I don't want it to come in filestr
1128
+ # so i am not piping stderr to stdout
1129
+ cmd = "cd #{@current_list.cur_dir()};grep -l #{flags} #{inp} #{fp}"
1130
+ filestr = %x[ #{cmd} ]
1131
+ files = nil
1132
+ files = filestr.split(/\n/) unless filestr.nil?
1133
+ #view filestr
1134
+ if !files || files.empty?
1135
+ alert "Sorry! No files for regex #{inp}"
1136
+ return
1137
+ end
1138
+ @current_list.title "grep #{inp}"
1139
+ @current_list.populate files
1140
+ # Use backspace to go back
1141
+ end
1142
+ return selected_index, mb.form.by_name["regex"].getvalue, mb.form.by_name["filepattern"].getvalue, fields[1].value, fields[0].value
1143
+ end
1144
+
1145
+ def system_popup
1146
+ deflt = @last_system || ""
1147
+ options=["run in shell","view output","file explorer"]
1148
+ #inp = get_string("Enter a system command", 30, deflt)
1149
+
1150
+ mb = MessageBox.new :title => "System Command" , :width => 80 do
1151
+ add Field.new :label => 'Enter command', :name => "cmd", :display_length => 50, :bgcolor => :cyan,
1152
+ :text => deflt
1153
+ $radio = RubyCurses::Variable.new
1154
+ add RadioButton.new :text => "run in shell", :color => :blue, :variable => $radio
1155
+ add RadioButton.new :text => "view output", :color => :red, :variable => $radio
1156
+ add RadioButton.new :text => "file explorer", :color => :red, :variable => $radio
1157
+ button_type :ok_cancel
1158
+ end
1159
+ sel = mb.run
1160
+ inp = mb.widget("cmd").text
1161
+ $log.debug "XXX: value of radio is #{$radio.value}, inp : #{inp} "
1162
+ #sel, inp, hash = get_string_with_options("Enter a system command", 40, deflt, {"radiobuttons" => options, "radio_default"=>@last_system_radio || options[0]})
1163
+ if sel == 0
1164
+ if !inp.nil?
1165
+ @last_system = inp
1166
+ @last_system_radio = $radio.value
1167
+ case $radio.value
1168
+ when options[0]
1169
+ shell_out inp
1170
+ when options[1]
1171
+ filestr = %x[ #{inp} ]
1172
+ view filestr
1173
+ when options[2]
1174
+ filestr = %x[ #{inp} ]
1175
+ files = nil
1176
+ files = filestr.split(/\n/) unless filestr.nil?
1177
+ @current_list.title inp
1178
+ @current_list.populate files
1179
+ $log.debug " SYSTEM got #{files.size}, #{files.inspect}"
1180
+ else
1181
+ shell_out inp
1182
+ end
1183
+ end
1184
+ end
1185
+ end
1186
+ # This will notwork, dunno if its being called
1187
+ def popup
1188
+ deflt = @last_regexp || ""
1189
+ #sel, inp, hash = get_string_with_options("Enter a filter pattern", 20, "*", {"checkboxes" => ["case sensitive","reverse"], "checkbox_defaults"=>[true, false]})
1190
+ sel, inp, hash = get_string_with_options("Enter a grep pattern", 20, deflt, {"checkboxes" => ["case insensitive","not-including"]})
1191
+ if sel == 0
1192
+ @last_regexp = inp
1193
+ flags=""
1194
+ flags << " -i " if hash["case insensitive"]==true
1195
+ flags << " -v " if hash["not-including"]==true
1196
+ cmd = "grep -l #{flags} #{inp} *"
1197
+ filestr = %x[ #{cmd} ]
1198
+ files = nil
1199
+ files = filestr.split(/\n/) unless filestr.nil?
1200
+ view filestr
1201
+ end
1202
+ $log.debug " POPUP: #{sel}: #{inp}, #{hash['case sensitive']}, #{hash['reverse']}"
1203
+ end
1204
+ # This won't work if you do something like 'ls -l', you will need to do 'ls -l | less'
1205
+ def shell_out command
1206
+ @window.hide
1207
+ Ncurses.endwin
1208
+ ret = system command
1209
+ Ncurses.refresh
1210
+ #Ncurses.curs_set 0 # why ?
1211
+ @window.show
1212
+ ret
1213
+ end
1214
+ end
1215
+ if $0 == __FILE__
1216
+ include RubyCurses
1217
+ include RubyCurses::Utils
1218
+
1219
+ begin
1220
+ # Initialize curses
1221
+ VER::start_ncurses # this is initializing colors via ColorMap.setup
1222
+ #$log = Logger.new("rbc13.log")
1223
+ $log = Logger.new(ENV['LOGDIR'] || "" + "rbc13.log")
1224
+
1225
+ $log.level = Logger::DEBUG
1226
+
1227
+ catch(:close) do
1228
+ t = RFe.new
1229
+ t.draw_screens
1230
+ end
1231
+ rescue => ex
1232
+ ensure
1233
+ VER::stop_ncurses
1234
+ p ex if ex
1235
+ p(ex.backtrace.join("\n")) if ex
1236
+ $log.debug( ex) if ex
1237
+ $log.debug(ex.backtrace.join("\n")) if ex
1238
+ end
1239
+ end