rbcurse 1.5.0 → 1.5.2

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 (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