rbcurse 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +33 -0
- data/README.markdown +7 -1
- data/TODO2.txt +21 -15
- data/VERSION +1 -1
- data/examples/abasiclist.rb +2 -2
- data/examples/alpmenu.rb +1 -1
- data/examples/app.rb +0 -1
- data/examples/appdirtree.rb +4 -2
- data/examples/appemail.rb +7 -3
- data/examples/appemaillb.rb +1 -1
- data/examples/appgcompose.rb +2 -2
- data/examples/appgmail.rb +1 -1
- data/examples/appmethods.rb +20 -2
- data/examples/atree.rb +9 -1
- data/examples/dbdemo.rb +460 -0
- data/examples/dirtree.rb +1 -1
- data/examples/menu1.rb +37 -5
- data/examples/multispl.rb +1 -1
- data/examples/rfe.rb +9 -2
- data/examples/splitp.rb +1 -1
- data/examples/sqlc.rb +6 -10
- data/examples/sqlm.rb +2 -20
- data/examples/sqlt.rb +408 -0
- data/examples/term2.rb +1 -1
- data/examples/test2.rb +169 -97
- data/examples/testapp.rb +1 -1
- data/examples/testapp2.rb +1 -1
- data/examples/testkeypress.rb +4 -2
- data/examples/testtable.rb +6 -0
- data/examples/testtpane.rb +35 -23
- data/examples/testvimsplit.rb +3 -2
- data/lib/rbcurse.rb +1 -1
- data/lib/rbcurse/action.rb +8 -0
- data/lib/rbcurse/app.rb +39 -23
- data/lib/rbcurse/extras/bottomline.rb +101 -13
- data/lib/rbcurse/extras/directorylist.rb +14 -5
- data/lib/rbcurse/extras/divider.rb +1 -1
- data/lib/rbcurse/extras/listselectable.rb +42 -8
- data/lib/rbcurse/extras/masterdetail.rb +2 -2
- data/lib/rbcurse/extras/scrollbar.rb +11 -2
- data/lib/rbcurse/extras/statusline.rb +56 -0
- data/lib/rbcurse/extras/stdscrwindow.rb +11 -0
- data/lib/rbcurse/extras/tabular.rb +2 -1
- data/lib/rbcurse/extras/tabularwidget.rb +60 -17
- data/lib/rbcurse/extras/viewer.rb +16 -4
- data/lib/rbcurse/keylabelprinter.rb +34 -4
- data/lib/rbcurse/listeditable.rb +5 -1
- data/lib/rbcurse/listkeys.rb +1 -1
- data/lib/rbcurse/listscrollable.rb +15 -8
- data/lib/rbcurse/rbasiclistbox.rb +44 -23
- data/lib/rbcurse/rcommandwindow.rb +8 -14
- data/lib/rbcurse/rdialogs.rb +187 -2
- data/lib/rbcurse/rlistbox.rb +38 -19
- data/lib/rbcurse/rmenu.rb +313 -93
- data/lib/rbcurse/rmessagebox.rb +3 -2
- data/lib/rbcurse/rmulticontainer.rb +5 -3
- data/lib/rbcurse/rmultisplit.rb +2 -11
- data/lib/rbcurse/rmultitextview.rb +4 -5
- data/lib/rbcurse/rtabbedpane.rb +223 -69
- data/lib/rbcurse/rtable.rb +6 -10
- data/lib/rbcurse/rtextarea.rb +57 -36
- data/lib/rbcurse/rtextview.rb +12 -15
- data/lib/rbcurse/rtree.rb +79 -22
- data/lib/rbcurse/rvimsplit.rb +16 -25
- data/lib/rbcurse/rwidget.rb +376 -523
- data/lib/rbcurse/tree/treecellrenderer.rb +24 -11
- data/lib/rbcurse/tree/treemodel.rb +1 -1
- data/lib/ver/window.rb +130 -66
- metadata +5 -3
- data/examples/term.rb +0 -48
data/examples/testapp.rb
CHANGED
@@ -24,7 +24,7 @@ class Testy
|
|
24
24
|
app = App.new
|
25
25
|
$log.debug " APP : value #{value}" if $log.debug?
|
26
26
|
header = app.app_header "rbcurse #{Rbcurse::VERSION} " , :text_center => " #{@value} Demo", :text_right =>"New Improved!", :color => :black, :bgcolor => :white, :attr => :bold
|
27
|
-
app.message "Press
|
27
|
+
app.message "Press F10 to exit from here #{@value} "
|
28
28
|
|
29
29
|
app.stack :margin_top => 2, :margin => 5, :width => 30 do |s|
|
30
30
|
app.label "Hello: ", :attr => :reverse
|
data/examples/testapp2.rb
CHANGED
@@ -30,7 +30,7 @@ class Testy
|
|
30
30
|
App.new do |app|
|
31
31
|
$log.debug " APP : value #{value}" if $log.debug?
|
32
32
|
header = app.app_header "rbcurse #{Rbcurse::VERSION} ", :text_center => " #{@value} Demo", :text_right =>"New Improved!", :color => :black, :bgcolor => :white, :attr => :bold
|
33
|
-
app.message "Press
|
33
|
+
app.message "Press F10 to exit from here #{@value} "
|
34
34
|
|
35
35
|
app.stack :margin_top => 2, :margin => 5, :width => 30 do |s|
|
36
36
|
app.label "Hello: ", :attr => :reverse
|
data/examples/testkeypress.rb
CHANGED
@@ -36,8 +36,10 @@ if $0 == __FILE__
|
|
36
36
|
auto_scroll true
|
37
37
|
title_attrib (Ncurses::A_REVERSE | Ncurses::A_BOLD)
|
38
38
|
end
|
39
|
-
|
40
|
-
|
39
|
+
help = "q to quit. Check keys. F1..10, C-a..z, Alt a-zA-Z0-9, C-left,rt, Sh-F5..10 .: #{$0}"
|
40
|
+
help1 = "Press in quick succession: 1) M-[, w and (2) M-[, M-w. (3) M-Sh-O, w."
|
41
|
+
RubyCurses::Label.new @form, {'text' => help, "row" => 21, "col" => 2, "color" => "yellow"}
|
42
|
+
RubyCurses::Label.new @form, {'text' => help1, "row" => 22, "col" => 2, "color" => "green"}
|
41
43
|
|
42
44
|
@form.repaint
|
43
45
|
@window.wrefresh
|
data/examples/testtable.rb
CHANGED
@@ -232,6 +232,7 @@ if $0 == __FILE__
|
|
232
232
|
@window.wrefresh
|
233
233
|
Ncurses::Panel.update_panels
|
234
234
|
while((ch = @window.getchar()) != ?\C-q.getbyte(0) )
|
235
|
+
begin
|
235
236
|
colcount = tcm.column_count-1
|
236
237
|
s = keycode_tos ch
|
237
238
|
keylabel.text = "Pressed #{ch} , #{s}"
|
@@ -248,6 +249,11 @@ if $0 == __FILE__
|
|
248
249
|
|
249
250
|
@form.repaint
|
250
251
|
@window.wrefresh
|
252
|
+
rescue => ex
|
253
|
+
$log.debug( ex) if ex
|
254
|
+
$log.debug(ex.backtrace.join("\n")) if ex
|
255
|
+
alert ex.to_s
|
256
|
+
end
|
251
257
|
end
|
252
258
|
end
|
253
259
|
rescue => ex
|
data/examples/testtpane.rb
CHANGED
@@ -15,9 +15,6 @@
|
|
15
15
|
# M-l in button form will scroll. M-h to scroll left.
|
16
16
|
# dd to kill a tab, u to undo kill, or p/P to paste deleted tab
|
17
17
|
#
|
18
|
-
#$LOAD_PATH << "/Users/rahul/work/projects/rbcurse/"
|
19
|
-
require 'rubygems'
|
20
|
-
#require 'ncurses' # FFI
|
21
18
|
require 'logger'
|
22
19
|
require 'rbcurse'
|
23
20
|
require 'rbcurse/rtabbedpane'
|
@@ -45,13 +42,16 @@ class TestTabbedPane
|
|
45
42
|
col 8
|
46
43
|
#button_type :ok
|
47
44
|
end
|
45
|
+
@tab1 = @tp.add_tab "&TextView" #, textview
|
46
|
+
f1 = @tp.form(@tab1)
|
48
47
|
|
49
|
-
textview = TextView.new do
|
48
|
+
textview = TextView.new f1 do
|
50
49
|
name "myView"
|
51
|
-
row
|
50
|
+
row 0
|
52
51
|
col 0
|
53
|
-
|
52
|
+
width w-0
|
54
53
|
#height h-4
|
54
|
+
height h-2
|
55
55
|
title "README.mrku"
|
56
56
|
title_attrib 'bold'
|
57
57
|
print_footer true
|
@@ -61,20 +61,19 @@ class TestTabbedPane
|
|
61
61
|
textview.set_content content #, :WRAP_WORD
|
62
62
|
#textview.show_caret = true
|
63
63
|
|
64
|
-
|
65
|
-
|
66
|
-
#f1
|
64
|
+
#@tab1 = @tp.add_tab "&TextView" #, textview
|
65
|
+
#f1 = @tp.form(@tab1)
|
66
|
+
#textview.set_form(f1)
|
67
|
+
#@tp.configure_component(textview)
|
67
68
|
|
68
69
|
|
69
70
|
|
70
71
|
#f2 = @tab2.form
|
72
|
+
#@tab2 = @tp.add_tab "&Settings" #, texta
|
73
|
+
#f2 = @tp.form(@tab2)
|
71
74
|
r = 4
|
72
75
|
texta = TextArea.new do
|
73
|
-
name
|
74
|
-
#row r
|
75
|
-
#col 2
|
76
|
-
#width w-5
|
77
|
-
#height h-5
|
76
|
+
name "myText"
|
78
77
|
title "EditMe.txt"
|
79
78
|
title_attrib 'bold'
|
80
79
|
print_footer true
|
@@ -105,9 +104,25 @@ class TestTabbedPane
|
|
105
104
|
col 5
|
106
105
|
end
|
107
106
|
end
|
108
|
-
|
109
|
-
|
110
|
-
|
107
|
+
x = RubyCurses::Field.new f3 do
|
108
|
+
name 'username'
|
109
|
+
row row+6
|
110
|
+
bgcolor 'white'
|
111
|
+
color 'black'
|
112
|
+
col 15
|
113
|
+
display_length 20
|
114
|
+
set_label Label.new f3, {'text' => 'User Name', 'mnemonic'=> 'u'}
|
115
|
+
end
|
116
|
+
x = RubyCurses::Field.new f3 do
|
117
|
+
name 'nick'
|
118
|
+
row row+7
|
119
|
+
bgcolor 'white'
|
120
|
+
color 'black'
|
121
|
+
col 15
|
122
|
+
display_length 10
|
123
|
+
set_label Label.new f3, {'text' => 'Nick Name', 'mnemonic'=> 'n'}
|
124
|
+
end
|
125
|
+
|
111
126
|
data = [["Pathetique",3,"Tchaikovsky",3.21, true, "WIP"],
|
112
127
|
["Ali Maula Ali Maula",3,"NFAK",3.47, true, "WIP"],
|
113
128
|
["Tera Hijr Mera Nasib",92,"Razia Sultan",412, true, "Fin"],
|
@@ -138,17 +153,14 @@ class TestTabbedPane
|
|
138
153
|
# We can skip sizing too for large components, so comp will fill the TP.
|
139
154
|
atable = Table.new do
|
140
155
|
name "mytable"
|
141
|
-
#row row
|
142
|
-
#col 0
|
143
|
-
#width 76
|
144
|
-
#height h - 4
|
145
156
|
#title "A Table"
|
146
157
|
#title_attrib (Ncurses::A_REVERSE | Ncurses::A_BOLD)
|
147
158
|
cell_editing_allowed true
|
148
159
|
editing_policy :EDITING_AUTO
|
149
160
|
set_data data, colnames
|
150
161
|
end
|
151
|
-
tab3
|
162
|
+
tab3 = @tp.add_tab "S&ongs", atable
|
163
|
+
#tab3.component = atable
|
152
164
|
sel_col = Variable.new 0
|
153
165
|
sel_col.value = 0
|
154
166
|
tcm = atable.get_table_column_model
|
@@ -160,7 +172,7 @@ class TestTabbedPane
|
|
160
172
|
tcm.column(3).width 7
|
161
173
|
tcm.column(4).width 5
|
162
174
|
tcm.column(5).width 6
|
163
|
-
@help = "F1 to quit. M-s M-t M-e M-o, TAB
|
175
|
+
@help = "F1 to quit. M-s M-t M-e M-o, TAB. M-x to add tab #{$0} M-h/M-l to scroll tabs"
|
164
176
|
RubyCurses::Label.new @form, {'text' => @help, "row" => r+h+2, "col" => 2, "color" => "yellow"}
|
165
177
|
|
166
178
|
# M-x when inside the buttons form will create a new tab
|
data/examples/testvimsplit.rb
CHANGED
@@ -46,6 +46,7 @@ class Tester
|
|
46
46
|
@vim.add lb1, :FIRST, :AUTO #nil #0.7:AUTO
|
47
47
|
@vim.add ["mercury","venus","earth","mars","jupiter", "saturn"], :FIRST, :AUTO
|
48
48
|
@vim.add alist, :FIRST, 0.4, stfl
|
49
|
+
#@vim.add alist, :FIRST, nil, stfl
|
49
50
|
@vim.add alist.shuffle, :FIRST, nil, stfl
|
50
51
|
@vim.add lb2, :SECOND, :AUTO
|
51
52
|
@vim.add str, :SECOND, :AUTO
|
@@ -69,14 +70,14 @@ class Tester
|
|
69
70
|
k_button.command { |form| @vim.decrease_weight }
|
70
71
|
|
71
72
|
#
|
72
|
-
@help = "
|
73
|
+
@help = "F10 to quit. "
|
73
74
|
RubyCurses::Label.new @form, {'text' => @help, "row" => 1, "col" => 2, "color" => "yellow"}
|
74
75
|
@form.repaint
|
75
76
|
@window.wrefresh
|
76
77
|
Ncurses::Panel.update_panels
|
77
78
|
ctr = 0
|
78
79
|
row = 2
|
79
|
-
while((ch = @window.getchar()) !=
|
80
|
+
while((ch = @window.getchar()) != Ncurses::KEY_F10 )
|
80
81
|
ret = @form.handle_key(ch)
|
81
82
|
@window.wrefresh
|
82
83
|
#ret = @vim.handle_key ch
|
data/lib/rbcurse.rb
CHANGED
data/lib/rbcurse/action.rb
CHANGED
@@ -3,6 +3,14 @@ require 'rbcurse/rwidget'
|
|
3
3
|
include RubyCurses
|
4
4
|
module RubyCurses
|
5
5
|
## encapsulates behaviour allowing centralization
|
6
|
+
# == Example
|
7
|
+
# a = Action.new("&New Row") { commands }
|
8
|
+
# a.accelerator "Alt N"
|
9
|
+
# menu.add(a)
|
10
|
+
# b = Button.new form do
|
11
|
+
# action a
|
12
|
+
# ...
|
13
|
+
# end
|
6
14
|
class Action < Proc
|
7
15
|
include EventHandler
|
8
16
|
include ConfigSetup
|
data/lib/rbcurse/app.rb
CHANGED
@@ -9,7 +9,6 @@ Todo:
|
|
9
9
|
Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
10
10
|
|
11
11
|
=end
|
12
|
-
#require 'ncurses'
|
13
12
|
require 'logger'
|
14
13
|
require 'rbcurse'
|
15
14
|
|
@@ -19,9 +18,8 @@ $tt.name = "$tt"
|
|
19
18
|
require 'forwardable'
|
20
19
|
module Kernel
|
21
20
|
extend Forwardable
|
22
|
-
def_delegators :$tt, :ask, :say, :agree, :choose, :numbered_menu, :display_text, :display_text_interactive, :display_list, :say_with_pause
|
21
|
+
def_delegators :$tt, :ask, :say, :agree, :choose, :numbered_menu, :display_text, :display_text_interactive, :display_list, :say_with_pause, :hide_bottomline
|
23
22
|
end
|
24
|
-
#include Ncurses # FFI 2011-09-8
|
25
23
|
include RubyCurses
|
26
24
|
include RubyCurses::Utils
|
27
25
|
include Io
|
@@ -83,9 +81,6 @@ module RubyCurses
|
|
83
81
|
|
84
82
|
extend Forwardable
|
85
83
|
def_delegators :$tt, :ask, :say, :agree, :choose, :numbered_menu, :display_text, :display_text_interactive, :display_list
|
86
|
-
#@tt = Bottomline.new @window, @message_row
|
87
|
-
#extend Forwardable
|
88
|
-
#def_delegators :@tt, :ask, :say, :agree, :choose
|
89
84
|
|
90
85
|
# TODO: i should be able to pass window coords here in config
|
91
86
|
# :title
|
@@ -122,11 +117,12 @@ module RubyCurses
|
|
122
117
|
colors = Ncurses.COLORS
|
123
118
|
$log.debug "START #{colors} colors --------- #{$0} win: #{@window} "
|
124
119
|
end
|
120
|
+
=begin
|
121
|
+
# trying without 2011-10-8
|
125
122
|
require 'rbcurse/extras/stdscrwindow'
|
126
123
|
awin = StdscrWindow.new
|
127
124
|
$tt.window = awin; $tt.message_row = @message_row
|
128
|
-
|
129
|
-
#$tt.window = @window; $tt.message_row = @message_row
|
125
|
+
=end
|
130
126
|
end
|
131
127
|
def logger; return $log; end
|
132
128
|
def close
|
@@ -134,6 +130,7 @@ module RubyCurses
|
|
134
130
|
@window.destroy if !@window.nil?
|
135
131
|
$log.debug " INSIDE CLOSE, #{@stop_ncurses_on_close} "
|
136
132
|
if @stop_ncurses_on_close
|
133
|
+
$tt.destroy # added on 2011-10-9 since we created a window, but only hid it after use
|
137
134
|
VER::stop_ncurses
|
138
135
|
$log.debug " CLOSING NCURSES"
|
139
136
|
end
|
@@ -187,19 +184,24 @@ module RubyCurses
|
|
187
184
|
# updates a global var with text. Calling app has to set up a Variable with that name and attach to
|
188
185
|
# a label so it can be printed.
|
189
186
|
def message text
|
187
|
+
$status_message.value = text # trying out 2011-10-9
|
190
188
|
@message.value = text
|
191
189
|
end
|
192
190
|
def message_row row
|
193
|
-
|
191
|
+
raise "Please use create_message_label first as message_label is no longer default behaviour" unless @message_label
|
192
|
+
@message_label.row = row
|
194
193
|
end
|
195
194
|
# during a process, when you wish to update status, since ordinarily the thread is busy
|
196
195
|
# and form does not get control back, so the window won't refresh.
|
197
196
|
# NOTE: use this only if +message+ is not working
|
198
197
|
# XXX Not sure if this is working after move to ffi-ncurses, check the demos
|
199
198
|
def message_immediate text
|
199
|
+
$status_message.value = text # trying out 2011-10-9 user needs to use in statusline command
|
200
200
|
message text
|
201
|
-
@message_label
|
202
|
-
|
201
|
+
if @message_label
|
202
|
+
@message_label.repaint
|
203
|
+
@window.refresh
|
204
|
+
end
|
203
205
|
end
|
204
206
|
# NOTE XXX using stdscr results in the screen going black if a dialog
|
205
207
|
# or other window is popped up, this was great but has not worked out.
|
@@ -208,23 +210,29 @@ module RubyCurses
|
|
208
210
|
# so at end of printing raw_messages, use message() for final status.
|
209
211
|
# Usage: application is inside a long processing loop and wishes to print ongoing status
|
210
212
|
# (similar to message_immediate) but faster and less involved
|
213
|
+
# @deprecated since it uses stdscr. Use say_with_pause or use rdialogs status_window, see test2.rb
|
211
214
|
def raw_message text
|
215
|
+
$log.warn "WARNING: don't use this method as it uses stdscr. Use rdialogs statuswindow."
|
216
|
+
row = @message_label ? @message_label.row : Ncurses.LINES-1
|
212
217
|
# experimentally trying stdscr instead of label
|
213
218
|
scr = FFI::NCurses.stdscr
|
214
219
|
text = "%-80s" % text
|
215
|
-
Ncurses.mvprintw
|
220
|
+
Ncurses.mvprintw row ,0, text
|
216
221
|
#@_stext ||= ""
|
217
222
|
#@_stext << text
|
218
223
|
## appending is quite a pain, maybe we should make it separate.
|
219
224
|
#stext = "%-80s" % @_stext
|
220
|
-
#Ncurses.mvprintw
|
225
|
+
#Ncurses.mvprintw row ,0, stext[-80..-1]
|
221
226
|
#scr.refresh() # NW w FFI XXX
|
222
227
|
#FFI::NCurses.refresh
|
223
228
|
end
|
224
229
|
# shows a simple progress bar on last row, using stdscr
|
225
230
|
# @param [Float, Array<Fixnum,Fixnum>] percentage, or part/total
|
226
231
|
# If Array of two numbers is given then also print part/total on left of bar
|
232
|
+
# @deprecated - don't use stdscr at all, use rdialogs status_window (see test2.rb)
|
227
233
|
def raw_progress arg
|
234
|
+
$log.warning "WARNING: don't use this method as it uses stdscr"
|
235
|
+
row = @message_label ? @message_label.row : Ncurses.LINES-1
|
228
236
|
s = nil
|
229
237
|
case arg
|
230
238
|
when Array
|
@@ -241,8 +249,8 @@ module RubyCurses
|
|
241
249
|
startcol = endcol - 12
|
242
250
|
stext = ("=" * (pc*10).to_i)
|
243
251
|
text = "[" + "%-10s" % stext + "]"
|
244
|
-
Ncurses.mvprintw(
|
245
|
-
Ncurses.mvprintw
|
252
|
+
Ncurses.mvprintw( row ,startcol-10, s) if s
|
253
|
+
Ncurses.mvprintw row ,startcol, text
|
246
254
|
#scr.refresh() # XXX FFI NW
|
247
255
|
|
248
256
|
end
|
@@ -410,7 +418,7 @@ module RubyCurses
|
|
410
418
|
alert "#{self.class} does not respond to #{cmd} "
|
411
419
|
ret = false
|
412
420
|
ret = execute_this(cmd, *cmdline) if respond_to?(:execute_this, true)
|
413
|
-
|
421
|
+
say_with_pause("#{self.class} does not respond to #{cmd} ", :color_pair => $promptcolor) unless ret
|
414
422
|
# should be able to say in red as error
|
415
423
|
end
|
416
424
|
end
|
@@ -726,10 +734,13 @@ module RubyCurses
|
|
726
734
|
require 'rbcurse/applicationheader'
|
727
735
|
header = ApplicationHeader.new @form, title, config, &block
|
728
736
|
end
|
737
|
+
|
738
|
+
# prints pine-like key labels
|
729
739
|
def dock labels, config={}, &block
|
730
740
|
require 'rbcurse/keylabelprinter'
|
731
741
|
klp = RubyCurses::KeyLabelPrinter.new @form, labels, config, &block
|
732
742
|
end
|
743
|
+
|
733
744
|
def link *args, &block
|
734
745
|
require 'rbcurse/extras/rlink'
|
735
746
|
config = {}
|
@@ -1060,16 +1071,18 @@ module RubyCurses
|
|
1060
1071
|
return cmd if opts.include? cmd
|
1061
1072
|
matches = opts.grep Regexp.new("^#{cmd}")
|
1062
1073
|
end
|
1074
|
+
# Now i am not creating this unless user wants it. Pls avoid it.
|
1075
|
+
# Use either say_with_pause, or put $status_message in command of statusline
|
1076
|
+
# @deprecated
|
1077
|
+
def create_message_label row=Ncurses.LINES-1
|
1078
|
+
@message_label = RubyCurses::Label.new @form, {:text_variable => @message, :name=>"message_label",:row => row, :col => 0, :display_length => Ncurses.COLS, :height => 1, :color => :white}
|
1079
|
+
end
|
1063
1080
|
def run &block
|
1064
1081
|
begin
|
1065
1082
|
|
1066
1083
|
# check if user has passed window coord in config, else root window
|
1067
1084
|
@window = VER::Window.root_window
|
1068
|
-
#$tt.window = @window; $tt.message_row = @message_row
|
1069
1085
|
awin = @window
|
1070
|
-
#require 'rbcurse/extras/stdscrwindow'
|
1071
|
-
#awin = StdscrWindow.new
|
1072
|
-
#$tt.window = awin; $tt.message_row = @message_row
|
1073
1086
|
catch(:close) do
|
1074
1087
|
@form = Form.new @window
|
1075
1088
|
@form.bind_key([?\C-x, ?c]) { suspend(false) do
|
@@ -1103,7 +1116,7 @@ module RubyCurses
|
|
1103
1116
|
rcmd = _resolve_command(opts, cmd) if !opts.include?(cmd)
|
1104
1117
|
if rcmd.size == 1
|
1105
1118
|
cmd = rcmd.first
|
1106
|
-
|
1119
|
+
elsif !rcmd.empty?
|
1107
1120
|
say_with_pause "Cannot resolve #{cmd}. Matches are: #{rcmd} "
|
1108
1121
|
end
|
1109
1122
|
end
|
@@ -1121,14 +1134,17 @@ module RubyCurses
|
|
1121
1134
|
end
|
1122
1135
|
end
|
1123
1136
|
else
|
1124
|
-
|
1137
|
+
say_with_pause("Command [#{cmd}] not supported by #{self.class} ", :color_pair => $promptcolor)
|
1125
1138
|
end
|
1126
1139
|
end
|
1127
1140
|
}
|
1128
1141
|
@form.bind_key(KEY_F1){ display_app_help }
|
1142
|
+
@form.bind_key([?q,?q]){ throw :close } if $log.debug?
|
1143
|
+
|
1129
1144
|
@message = Variable.new
|
1130
1145
|
@message.value = ""
|
1131
|
-
|
1146
|
+
$status_message ||= Variable.new # remember there are multiple levels of apps
|
1147
|
+
$status_message.value = ""
|
1132
1148
|
$error_message.update_command { @message.set_value($error_message.value) }
|
1133
1149
|
if block
|
1134
1150
|
begin
|
@@ -15,6 +15,11 @@ require 'pathname'
|
|
15
15
|
|
16
16
|
May later use a Label and Field.
|
17
17
|
|
18
|
+
NOTE : Pls avoid directly using this class. I am trying to redo this so ask, agree and say
|
19
|
+
can create their own window and be done with it. The hurdle in that is that ask calls
|
20
|
+
say, so when to close the window is not clear within say. Some shakeup is expected by
|
21
|
+
1.4.0 or so.
|
22
|
+
|
18
23
|
=end
|
19
24
|
module RubyCurses
|
20
25
|
|
@@ -83,7 +88,20 @@ module RubyCurses
|
|
83
88
|
attr_accessor :name # for debugging
|
84
89
|
def initialize win=nil, row=nil
|
85
90
|
@window = win
|
86
|
-
|
91
|
+
#@window.wrefresh
|
92
|
+
#Ncurses::Panel.update_panels
|
93
|
+
#@message_row = row
|
94
|
+
@message_row = 0 # 2011-10-8
|
95
|
+
end
|
96
|
+
#
|
97
|
+
# create a window at bottom and show and hide it.
|
98
|
+
# Causing a stack overflow since Window creates a bottomline too !
|
99
|
+
#
|
100
|
+
def _create_footer_window h = 1 , w = Ncurses.COLS, t = Ncurses.LINES-1, l = 0
|
101
|
+
ewin = VER::Window.new(h, w , t, l)
|
102
|
+
#ewin.bkgd(Ncurses.COLOR_PAIR($promptcolor));
|
103
|
+
@window = ewin
|
104
|
+
return ewin
|
87
105
|
end
|
88
106
|
|
89
107
|
class QuestionError < StandardError
|
@@ -947,7 +965,10 @@ module RubyCurses
|
|
947
965
|
end
|
948
966
|
end
|
949
967
|
def ask(question, answer_type=String, &details)
|
950
|
-
|
968
|
+
$log.debug "XXXX inside ask win #{@window} "
|
969
|
+
#@window.show #unless @window.visible?
|
970
|
+
@window ||= _create_footer_window
|
971
|
+
|
951
972
|
@question ||= Question.new(question, answer_type, &details)
|
952
973
|
say(@question) #unless @question.echo == true
|
953
974
|
|
@@ -961,6 +982,7 @@ module RubyCurses
|
|
961
982
|
end
|
962
983
|
|
963
984
|
begin
|
985
|
+
# FIXME a C-c still returns default to user !
|
964
986
|
@answer = @question.answer_or_default(get_response)
|
965
987
|
unless @question.valid_answer?(@answer)
|
966
988
|
explain_error(:not_valid)
|
@@ -1010,10 +1032,38 @@ module RubyCurses
|
|
1010
1032
|
rescue Question::NoAutoCompleteMatch
|
1011
1033
|
explain_error(:no_completion)
|
1012
1034
|
retry
|
1035
|
+
rescue Interrupt
|
1036
|
+
$log.warn "User interrupted ask() get_response does not want operation to proceed"
|
1037
|
+
return nil
|
1013
1038
|
ensure
|
1014
1039
|
@question = nil # Reset Question object.
|
1040
|
+
hide # assuming this method made it visible, not sure if this is called.
|
1041
|
+
end
|
1042
|
+
end
|
1043
|
+
#
|
1044
|
+
# bottomline user has to hide window if he called say().
|
1045
|
+
# Call this if you find the window persists after using some method from here
|
1046
|
+
# usually say or ask.
|
1047
|
+
#
|
1048
|
+
# @param [int, float] time to sleep before hiding window.
|
1049
|
+
#
|
1050
|
+
def hide wait=nil
|
1051
|
+
if @window
|
1052
|
+
sleep(wait) if wait
|
1053
|
+
@window.hide
|
1054
|
+
@window.wrefresh
|
1055
|
+
#Ncurses::Panel.update_panels
|
1015
1056
|
end
|
1016
1057
|
end
|
1058
|
+
alias :hide_bottomline :hide
|
1059
|
+
#
|
1060
|
+
# destroy window, to be called by app when shutting down
|
1061
|
+
# since we are normally hiding the window only.
|
1062
|
+
def destroy
|
1063
|
+
$log.debug "bottomline destroy... #{@window} "
|
1064
|
+
@window.destroy if @window
|
1065
|
+
@window = nil
|
1066
|
+
end
|
1017
1067
|
|
1018
1068
|
#
|
1019
1069
|
# The basic output method for HighLine objects.
|
@@ -1025,14 +1075,21 @@ module RubyCurses
|
|
1025
1075
|
# question. Also, ansi color constants will not work. Be careful what ruby code
|
1026
1076
|
# you pass in.
|
1027
1077
|
#
|
1078
|
+
# NOTE: This uses a window, so it will persist in the last row. You must call
|
1079
|
+
# hide_bottomline to remove the window. It is preferable to call say_with_pause
|
1080
|
+
# from user programs
|
1081
|
+
#
|
1028
1082
|
def say statement, config={}
|
1083
|
+
@window ||= _create_footer_window
|
1084
|
+
#@window.show unless @window.visible? # this will need to be hidden manually NOTE
|
1085
|
+
$log.debug "XXX: inside say win #{@window} !"
|
1029
1086
|
case statement
|
1030
1087
|
when Question
|
1031
1088
|
|
1032
1089
|
if config.has_key? :color_pair
|
1033
1090
|
$log.debug "INSIDE QUESTION 2 " if $log.debug?
|
1034
1091
|
else
|
1035
|
-
$log.debug "XXXX SAY using #{statement.color_pair} " if $log.debug?
|
1092
|
+
$log.debug "XXXX SAY using colorpair: #{statement.color_pair} " if $log.debug?
|
1036
1093
|
config[:color_pair] = statement.color_pair
|
1037
1094
|
end
|
1038
1095
|
else
|
@@ -1041,15 +1098,22 @@ module RubyCurses
|
|
1041
1098
|
statement = statement.to_str
|
1042
1099
|
template = ERB.new(statement, nil, "%")
|
1043
1100
|
statement = template.result(binding)
|
1044
|
-
|
1101
|
+
|
1045
1102
|
@prompt_length = statement.length # required by ask since it prints after
|
1046
1103
|
@statement = statement #
|
1047
1104
|
clear_line
|
1048
1105
|
print_str statement, config
|
1049
1106
|
end
|
1107
|
+
#
|
1108
|
+
# display some text at bottom and wait for a key before hiding window
|
1109
|
+
#
|
1050
1110
|
def say_with_pause statement, config={}
|
1111
|
+
@window ||= _create_footer_window
|
1051
1112
|
say statement, config
|
1113
|
+
@window.wrefresh
|
1114
|
+
Ncurses::Panel.update_panels
|
1052
1115
|
ch=@window.getchar()
|
1116
|
+
hide
|
1053
1117
|
end
|
1054
1118
|
# A helper method for sending the output stream and error and repeat
|
1055
1119
|
# of the question.
|
@@ -1065,10 +1129,14 @@ module RubyCurses
|
|
1065
1129
|
end
|
1066
1130
|
end
|
1067
1131
|
|
1132
|
+
#
|
1133
|
+
# Internal method for printing a string
|
1134
|
+
#
|
1068
1135
|
def print_str(text, config={})
|
1069
1136
|
win = config.fetch(:window, @window) # assuming its in App
|
1070
|
-
x = config.fetch :x, @message_row # Ncurses.LINES-1
|
1137
|
+
x = config.fetch :x, 0 # @message_row # Ncurses.LINES-1, 0 since one line window 2011-10-8
|
1071
1138
|
y = config.fetch :y, 0
|
1139
|
+
$log.debug "XXX: print_str #{win} with text : #{text} at #{x} #{y} "
|
1072
1140
|
color = config[:color_pair] || $datacolor
|
1073
1141
|
raise "no window for ask print in #{self.class} name: #{name} " unless win
|
1074
1142
|
color=Ncurses.COLOR_PAIR(color);
|
@@ -1151,12 +1219,14 @@ module RubyCurses
|
|
1151
1219
|
curpos -= 1 if curpos > 0
|
1152
1220
|
len -= 1 if len > @prompt_length
|
1153
1221
|
win.move r, c+len # since getchar is not going back on del and bs wmove to move FFIWINDOW
|
1222
|
+
win.wrefresh
|
1154
1223
|
next
|
1155
1224
|
when KEY_RIGHT
|
1156
1225
|
if curpos < str.length
|
1157
1226
|
curpos += 1 #if curpos < str.length
|
1158
1227
|
len += 1
|
1159
1228
|
win.move r, c+len # since getchar is not going back on del and bs
|
1229
|
+
win.wrefresh
|
1160
1230
|
end
|
1161
1231
|
next
|
1162
1232
|
when ?\C-a.getbyte(0)
|
@@ -1323,6 +1393,7 @@ module RubyCurses
|
|
1323
1393
|
print_str(@question.echo * str.length, :y => @prompt_length+0)
|
1324
1394
|
end
|
1325
1395
|
win.move r, c+len # more for arrow keys, curpos may not be end
|
1396
|
+
win.wrefresh # 2011-10-10
|
1326
1397
|
prevchar = ch
|
1327
1398
|
end
|
1328
1399
|
$log.debug "XXXW bottomline: after while loop"
|
@@ -1374,6 +1445,9 @@ module RubyCurses
|
|
1374
1445
|
if ret == 0
|
1375
1446
|
return @question.change_case(@question.remove_whitespace(str))
|
1376
1447
|
end
|
1448
|
+
if ret == -1
|
1449
|
+
raise Interrupt
|
1450
|
+
end
|
1377
1451
|
return ""
|
1378
1452
|
end
|
1379
1453
|
def agree( yes_or_no_question, character = nil )
|
@@ -1441,22 +1515,28 @@ module RubyCurses
|
|
1441
1515
|
end
|
1442
1516
|
# Allows a selection in which options are shown over prompt. As user types
|
1443
1517
|
# options are narrowed down.
|
1518
|
+
# NOTE: For a directory we are not showing a slash, so currently you
|
1519
|
+
# have to enter the slash manually when searching.
|
1444
1520
|
# FIXME we can put remarks in fron as in memacs such as [No matches] or [single completion]
|
1445
1521
|
# @param [Array] a list of items to select from
|
1446
1522
|
# NOTE: if you use this please copy it to your app. This does not conform to highline's
|
1447
1523
|
# choose, and I'd like to somehow get it to be identical.
|
1448
1524
|
#
|
1449
1525
|
def choose list1, config={}
|
1526
|
+
dirlist = true
|
1450
1527
|
case list1
|
1451
1528
|
when NilClass
|
1452
|
-
list1 = Dir.glob("*")
|
1529
|
+
#list1 = Dir.glob("*")
|
1530
|
+
list1 = Dir.glob("*").collect { |f| File.directory?(f) ? f+"/" : f }
|
1453
1531
|
when String
|
1454
|
-
list1 = Dir.glob(list1)
|
1532
|
+
list1 = Dir.glob(list1).collect { |f| File.directory?(f) ? f+"/" : f }
|
1455
1533
|
when Array
|
1534
|
+
dirlist = false
|
1456
1535
|
# let it be, that's how it should come
|
1457
1536
|
else
|
1458
1537
|
# Dir listing as default
|
1459
|
-
list1 = Dir.glob("*")
|
1538
|
+
#list1 = Dir.glob("*")
|
1539
|
+
list1 = Dir.glob("*").collect { |f| File.directory?(f) ? f+"/" : f }
|
1460
1540
|
end
|
1461
1541
|
require 'rbcurse/rcommandwindow'
|
1462
1542
|
prompt = config[:prompt] || "Choose: "
|
@@ -1466,12 +1546,24 @@ module RubyCurses
|
|
1466
1546
|
w = rc.window
|
1467
1547
|
rc.display_menu list1
|
1468
1548
|
# earlier wmove bombed, now move is (window.rb 121)
|
1469
|
-
str = ask(prompt) { |q| q.change_proc = Proc.new { |str| w.wmove(1,1) ; w.wclrtobot;
|
1549
|
+
str = ask(prompt) { |q| q.change_proc = Proc.new { |str| w.wmove(1,1) ; w.wclrtobot;
|
1550
|
+
l = list1.select{|e| e.index(str)==0} ;
|
1551
|
+
if (l.size == 0 || str[-1]=='/') && dirlist
|
1552
|
+
# used to help complete directories so we can drill up and down
|
1553
|
+
#l = Dir.glob(str+"*")
|
1554
|
+
l = Dir.glob(str +"*").collect { |f| File.directory?(f) ? f+"/" : f }
|
1555
|
+
end
|
1556
|
+
rc.display_menu l;
|
1557
|
+
l
|
1558
|
+
} }
|
1470
1559
|
# need some validation here that its in the list TODO
|
1471
1560
|
ensure
|
1472
1561
|
rc.destroy
|
1473
1562
|
rc = nil
|
1563
|
+
hide_bottomline # since we called ask() we need to close bottomline
|
1474
1564
|
end
|
1565
|
+
hide_bottomline # since we called ask() we need to close bottomline
|
1566
|
+
return str
|
1475
1567
|
end
|
1476
1568
|
def display_text_interactive text, config={}
|
1477
1569
|
require 'rbcurse/rcommandwindow'
|
@@ -1630,10 +1722,6 @@ if __FILE__ == $PROGRAM_NAME
|
|
1630
1722
|
App.new do
|
1631
1723
|
header = app_header "rbcurse 1.2.0", :text_center => "**** Demo", :text_right =>"New Improved!", :color => :black, :bgcolor => :white, :attr => :bold
|
1632
1724
|
message "Press F1 to exit from here"
|
1633
|
-
######## $tt.window = @window; $tt.message_row = @message_row
|
1634
|
-
#@tt = Bottomline.new @window, @message_row
|
1635
|
-
#extend Forwardable
|
1636
|
-
#def_delegators :@tt, :ask, :say, :agree, :choose
|
1637
1725
|
|
1638
1726
|
#stack :margin_top => 2, :margin => 5, :width => 30 do
|
1639
1727
|
#end # stack
|