rubytext 0.1.22 → 0.1.26
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.
- checksums.yaml +4 -4
- data/examples/topmenu.rb +56 -0
- data/lib/.yardoc/checksums +11 -0
- data/lib/.yardoc/complete +0 -0
- data/lib/.yardoc/object_types +0 -0
- data/lib/.yardoc/objects/root.dat +0 -0
- data/lib/.yardoc/proxy_types +0 -0
- data/lib/color.rb +22 -0
- data/lib/doc/RubyText/Color.html +366 -0
- data/lib/doc/RubyText/Effects.html +658 -0
- data/lib/doc/RubyText/Keys.html +300 -0
- data/lib/doc/RubyText/Settings.html +593 -0
- data/lib/doc/RubyText/Window/GetString.html +812 -0
- data/lib/doc/RubyText/Window.html +5074 -0
- data/lib/doc/RubyText.html +1410 -0
- data/lib/doc/WindowIO.html +541 -0
- data/lib/doc/_index.html +195 -0
- data/lib/doc/class_list.html +51 -0
- data/lib/doc/css/common.css +1 -0
- data/lib/doc/css/full_list.css +58 -0
- data/lib/doc/css/style.css +496 -0
- data/lib/doc/file_list.html +51 -0
- data/lib/doc/frames.html +17 -0
- data/lib/doc/index.html +195 -0
- data/lib/doc/js/app.js +314 -0
- data/lib/doc/js/full_list.js +216 -0
- data/lib/doc/js/jquery.js +4 -0
- data/lib/doc/method_list.html +987 -0
- data/lib/doc/top-level-namespace.html +483 -0
- data/lib/effects.rb +15 -1
- data/lib/keys.rb +3 -0
- data/lib/menu.rb +410 -17
- data/lib/navigation.rb +35 -0
- data/lib/output.rb +18 -4
- data/lib/rubytext_version.rb +1 -1
- data/lib/settings.rb +5 -4
- data/lib/widgets.rb +10 -2
- data/lib/window.rb +1 -0
- data/rubytext.gemspec +2 -1
- metadata +35 -14
data/lib/menu.rb
CHANGED
@@ -1,17 +1,331 @@
|
|
1
|
+
#### FIXME LATER
|
2
|
+
|
3
|
+
# The top-level module
|
4
|
+
|
1
5
|
module RubyText
|
2
6
|
|
7
|
+
# Wrapper for a curses window
|
8
|
+
|
3
9
|
class Window
|
4
|
-
def topmenu(items:, curr: 0, fg: Green, bg: Black)
|
5
|
-
r, c = 0, 0
|
6
|
-
high = 1
|
7
10
|
|
11
|
+
class Menu2D
|
12
|
+
|
13
|
+
class Vertical
|
14
|
+
attr_reader :widest, :height, :header, :hash
|
15
|
+
def initialize(vlist)
|
16
|
+
@header = vlist[0]
|
17
|
+
@hash = vlist[1]
|
18
|
+
@widest = @header.length
|
19
|
+
@hash.each_pair {|k,v| puts "k = #{k.inspect}"; getch; @widest = [@widest, k.length].max }
|
20
|
+
@height = @hash.size
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(win:, r: :center, c: :center, items:, colrow: [0, 0],
|
25
|
+
border: true, title: nil, fg: Green, bg: Black)
|
26
|
+
@win = win
|
27
|
+
@list = []
|
28
|
+
@header = @list.map {|x| x.header }
|
29
|
+
items.each {|vlist| @list << Vertical.new(vlist) }
|
30
|
+
@highest = @list.map {|x| x.height }.max
|
31
|
+
@full_width = @list.inject(0) {|sum, vlist| sum += vlist.widest + 2 }
|
32
|
+
@nlists = items.size
|
33
|
+
@grid = Array.new(@nlists) # column major order
|
34
|
+
@grid.map! {|x| [" "] * @highest }
|
35
|
+
@list.each.with_index do |vlist, i|
|
36
|
+
vlist.hash.each_pair.with_index do |kv, j|
|
37
|
+
k, v = kv
|
38
|
+
@grid[i][j] = [k, v]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
RubyText.hide_cursor
|
42
|
+
@high = @highest
|
43
|
+
@wide = @full_width
|
44
|
+
@high += 2 if border
|
45
|
+
@wide += 2 if border
|
46
|
+
|
47
|
+
tlen = title.length + 8 rescue 0
|
48
|
+
# wide = [wide, tlen].max
|
49
|
+
row, col = @win.coords(r, c)
|
50
|
+
row = row - @high/2 if r == :center
|
51
|
+
col = col - @wide/2 if c == :center
|
52
|
+
r, c = row, col
|
53
|
+
@win.saveback(@high+1, @wide, r, c)
|
54
|
+
mr, mc = r+@win.r0, c+@win.c0
|
55
|
+
title = nil unless border
|
56
|
+
|
57
|
+
@mwin = RubyText.window(@high+1, @wide, r: mr, c: mc, border: true,
|
58
|
+
fg: fg, bg: bg, title: title)
|
59
|
+
@header.each {|head| printf "%-#{maxw}s", head }
|
60
|
+
puts # after header
|
61
|
+
Curses.stdscr.keypad(true)
|
62
|
+
maxcol = items.size - 1
|
63
|
+
sizes = items.map {|x| x.size }
|
64
|
+
max = sizes.max
|
65
|
+
# mwin.go(r, c)
|
66
|
+
r += 1 # account for header
|
67
|
+
@selc, @selr = colrow
|
68
|
+
end
|
69
|
+
|
70
|
+
def show(r, c, colrow: [0, 0])
|
71
|
+
@selc, @selr = colrow
|
72
|
+
@grid.each.with_index do |column, cix|
|
73
|
+
column.each.with_index do |pairs, rix| # {Jan: ..., Feb: ..., Mar: ..., ...}
|
74
|
+
# STDSCR.puts "go: #{r}+#{rix}, #{c}+#{cix}*#{maxw}"
|
75
|
+
@mwin.go(rix, cix) # FIXME wrong?
|
76
|
+
style = ([@selc, @selr] == [cix, rix]) ? :reverse : :normal
|
77
|
+
key, val = pairs
|
78
|
+
label = key.to_s
|
79
|
+
@mwin.print label # fx(label, style)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def handle(r, c)
|
85
|
+
loop do
|
86
|
+
show(r, c)
|
87
|
+
ch = getch
|
88
|
+
case ch
|
89
|
+
when RubyText::Window::Up
|
90
|
+
@selr -= 1 if @selr > 0
|
91
|
+
when RubyText::Window::Down
|
92
|
+
# puts "PAUSE r,c = #@selr #@selc highest=#@highest"; getch
|
93
|
+
@selr += 1 if @selr < @highest - 1
|
94
|
+
when RubyText::Window::Left
|
95
|
+
@selc -= 1 if @selc > 0
|
96
|
+
when RubyText::Window::Right
|
97
|
+
@selc += 1 if @selc < @full_width
|
98
|
+
when RubyText::Window::Esc
|
99
|
+
@win.restback(@high+1, @wide, r-1, c)
|
100
|
+
RubyText.show_cursor
|
101
|
+
return [nil, nil, nil]
|
102
|
+
when RubyText::Window::Enter
|
103
|
+
@win.restback(@high+1, @wide, r-1, c)
|
104
|
+
RubyText.show_cursor
|
105
|
+
choice = @grid[@selc][@selr][1]
|
106
|
+
case choice
|
107
|
+
when String;
|
108
|
+
puts "Returning #{[@selc, @selr, choice].inspect}"; getch
|
109
|
+
return [@selc, @selr, choice]
|
110
|
+
when NilClass; return [nil, nil, nil]
|
111
|
+
end
|
112
|
+
result = choice.call # should be a Proc
|
113
|
+
return [nil, nil, nil] if result.nil? || result.empty?
|
114
|
+
return result
|
115
|
+
else Curses.beep
|
116
|
+
end
|
117
|
+
end
|
118
|
+
RubyText.show_cursor
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
def rectmenu(r: :center, c: :center, items:, colrow: [0, 0],
|
124
|
+
border: true,
|
125
|
+
title: nil, fg: Green, bg: Black)
|
8
126
|
RubyText.hide_cursor
|
127
|
+
maxh, maxw = _rectmenu_maxes(items)
|
128
|
+
header, stuff = _rect_hash2array(items, maxh, maxw)
|
129
|
+
wide = items.size * maxw
|
130
|
+
high = maxh
|
131
|
+
high += 2 if border
|
132
|
+
wide += 2 if border
|
133
|
+
|
134
|
+
tlen = title.length + 8 rescue 0
|
135
|
+
# wide = [wide, tlen].max
|
136
|
+
row, col = @win.coords(r, c)
|
137
|
+
row = row - high/2 if r == :center
|
138
|
+
col = col - wide/2 if c == :center
|
139
|
+
r, c = row, col
|
140
|
+
@win.saveback(high+1, wide, r, c)
|
141
|
+
mr, mc = r+@win.r0, c+@win.c0
|
142
|
+
title = nil unless border
|
143
|
+
|
144
|
+
mwin = RubyText.window(high+1, wide, r: mr, c: mc, border: true,
|
145
|
+
fg: fg, bg: bg, title: title)
|
146
|
+
header.each {|head| printf "%-#{maxw}s", head }
|
147
|
+
puts # after header
|
148
|
+
Curses.stdscr.keypad(true)
|
149
|
+
maxcol = items.size - 1
|
150
|
+
sizes = items.map {|x| x.size }
|
151
|
+
max = sizes.max
|
152
|
+
# mwin.go(r, c)
|
153
|
+
r += 1 # account for header
|
154
|
+
selc, selr = colrow
|
155
|
+
|
156
|
+
loop do
|
157
|
+
RubyText.hide_cursor # FIXME should be unnecessary
|
158
|
+
stuff.each.with_index do |column, cix|
|
159
|
+
column.each.with_index do |pairs, rix| # {Jan: ..., Feb: ..., Mar: ..., ...}
|
160
|
+
STDSCR.puts "go: #{r}+#{rix}, #{c}+#{cix}*#{maxw}"
|
161
|
+
mwin.go(rix+1, cix*maxw)
|
162
|
+
style = ([selc, selr] == [cix, rix]) ? :reverse : :normal
|
163
|
+
key, val = pairs
|
164
|
+
label = key.to_s
|
165
|
+
# mwin.print fx(label, style)
|
166
|
+
mwin.print label # fx(label, style)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
ch = getch
|
170
|
+
case ch
|
171
|
+
when Up
|
172
|
+
selr -= 1 if selr > 0
|
173
|
+
when Down
|
174
|
+
selr += 1 if selr < maxh - 1
|
175
|
+
when Left
|
176
|
+
selc -= 1 if selc > 0
|
177
|
+
when Right
|
178
|
+
selc += 1 if selc < maxcol
|
179
|
+
when Esc
|
180
|
+
self.restback(high+1, wide, r-1, c)
|
181
|
+
RubyText.show_cursor
|
182
|
+
return [nil, nil, nil]
|
183
|
+
when Enter
|
184
|
+
self.restback(high+1, wide, r-1, c)
|
185
|
+
RubyText.show_cursor
|
186
|
+
choice = stuff[selc][selr][1]
|
187
|
+
case choice
|
188
|
+
when String; return [selc, selr, choice]
|
189
|
+
when NilClass; return [nil, nil, nil]
|
190
|
+
end
|
191
|
+
result = choice.call # should be a Proc
|
192
|
+
return [nil, nil, nil] if result.nil? || result.empty?
|
193
|
+
return result
|
194
|
+
else Curses.beep
|
195
|
+
end
|
196
|
+
RubyText.show_cursor
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
module RubyText
|
203
|
+
|
204
|
+
# Two-paned widget with menu on left, informtional area on right
|
205
|
+
|
206
|
+
def self.selector(win: STDSCR, r: 0, c: 0, rows: 10, cols: 20,
|
207
|
+
items:, fg: White, bg: Blue,
|
208
|
+
win2:, callback:, enter: nil, quit: "q")
|
209
|
+
high = rows
|
210
|
+
wide = cols
|
211
|
+
mwin = RubyText.window(high, wide, r: r, c: c, fg: fg, bg: bg)
|
212
|
+
handler = callback
|
213
|
+
Curses.stdscr.keypad(true)
|
214
|
+
RubyText.hide_cursor
|
215
|
+
sel = 0
|
216
|
+
max = items.size - 1
|
217
|
+
handler.call(sel, items[sel], win2)
|
218
|
+
loop do
|
219
|
+
mwin.home
|
220
|
+
items.each.with_index do |item, row|
|
221
|
+
mwin.crlf
|
222
|
+
style = (sel == row) ? :reverse : :normal
|
223
|
+
mwin.print fx(" #{item}", style)
|
224
|
+
end
|
225
|
+
ch = getch
|
226
|
+
case ch
|
227
|
+
when Up
|
228
|
+
if sel > 0
|
229
|
+
sel -= 1
|
230
|
+
handler.call(sel, items[sel], win2)
|
231
|
+
end
|
232
|
+
when Down
|
233
|
+
if sel < max
|
234
|
+
sel += 1
|
235
|
+
handler.call(sel, items[sel], win2)
|
236
|
+
end
|
237
|
+
when Enter
|
238
|
+
if enter
|
239
|
+
del = enter.call(sel, items[sel], win2)
|
240
|
+
if del
|
241
|
+
items -= [items[sel]]
|
242
|
+
raise
|
243
|
+
end
|
244
|
+
end
|
245
|
+
when Tab
|
246
|
+
Curses.flash
|
247
|
+
when quit # parameter
|
248
|
+
exit
|
249
|
+
else Curses.beep # all else is trash
|
250
|
+
end
|
251
|
+
end
|
252
|
+
rescue
|
253
|
+
retry
|
254
|
+
end
|
255
|
+
|
256
|
+
# "Menu" for checklists
|
257
|
+
|
258
|
+
def checklist(r: :center, c: :center,
|
259
|
+
items:, curr: 0, selected: [],
|
260
|
+
title: nil, sel_fg: Yellow, fg: White, bg: Blue)
|
261
|
+
RubyText.hide_cursor
|
262
|
+
high = items.size + 2
|
263
|
+
wide = items.map(&:length).max + 8
|
264
|
+
tlen = title.length + 8 rescue 0
|
265
|
+
wide = [wide, tlen].max
|
266
|
+
row, col = self.coords(r, c)
|
267
|
+
row = row - high/2 if r == :center
|
268
|
+
col = col - wide/2 if c == :center
|
269
|
+
r, c = row, col
|
270
|
+
self.saveback(high, wide, r, c)
|
271
|
+
mr, mc = r+self.r0, c+self.c0
|
272
|
+
mwin = RubyText.window(high, wide, r: mr, c: mc,
|
273
|
+
fg: fg, bg: bg, title: title)
|
274
|
+
Curses.stdscr.keypad(true)
|
275
|
+
sel = curr
|
276
|
+
max = items.size - 1
|
277
|
+
loop do
|
278
|
+
RubyText.hide_cursor # FIXME should be unnecessary
|
279
|
+
items.each.with_index do |item, row|
|
280
|
+
mwin.go row, 0
|
281
|
+
style = (sel == row) ? :reverse : :normal
|
282
|
+
color = selected.find {|x| x[0] == row } ? sel_fg : fg
|
283
|
+
label = "[ ]" + item
|
284
|
+
mwin.print fx(label, color, style)
|
285
|
+
end
|
286
|
+
ch = getch
|
287
|
+
case ch
|
288
|
+
when Up
|
289
|
+
sel -= 1 if sel > 0
|
290
|
+
when Down
|
291
|
+
sel += 1 if sel < max
|
292
|
+
when Esc
|
293
|
+
self.restback(high, wide, r, c)
|
294
|
+
RubyText.show_cursor
|
295
|
+
return []
|
296
|
+
when Enter
|
297
|
+
self.restback(high, wide, r, c)
|
298
|
+
RubyText.show_cursor
|
299
|
+
return selected.map {|i| items[i] }
|
300
|
+
when " "
|
301
|
+
selected << [sel, items[sel]]
|
302
|
+
sel += 1 if sel < max
|
303
|
+
else Curses.beep
|
304
|
+
end
|
305
|
+
RubyText.show_cursor
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
end
|
310
|
+
|
311
|
+
# The top-level module
|
312
|
+
|
313
|
+
module RubyText
|
314
|
+
|
315
|
+
# Wrapper for a curses window
|
316
|
+
|
317
|
+
class Window
|
318
|
+
|
319
|
+
# One-line menu at top of window
|
320
|
+
|
321
|
+
def topmenu(items:, curr: 0, fg: Green, bg: Black)
|
322
|
+
r, c, high = 0, 0, 1
|
323
|
+
RubyText.hide_cursor
|
324
|
+
hash_flag = false
|
325
|
+
results = items
|
9
326
|
if items.is_a?(Hash)
|
10
|
-
results = items.values
|
11
|
-
items = items.keys
|
327
|
+
results, items = items.values, items.keys
|
12
328
|
hash_flag = true
|
13
|
-
else
|
14
|
-
results = items
|
15
329
|
end
|
16
330
|
|
17
331
|
width = 0 # total width
|
@@ -45,25 +359,30 @@ module RubyText
|
|
45
359
|
when Esc, " " # spacebar also quits
|
46
360
|
self.restback(high, width, r, c)
|
47
361
|
RubyText.show_cursor
|
362
|
+
STDSCR.go r, c
|
48
363
|
return [nil, nil]
|
49
364
|
when Down, Enter
|
50
365
|
self.restback(high, width, r, c)
|
51
366
|
RubyText.show_cursor
|
367
|
+
STDSCR.go r, c
|
52
368
|
choice = results[sel]
|
53
369
|
return [sel, choice] if choice.is_a? String
|
54
370
|
result = choice.call
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
371
|
+
return [nil, nil, nil] if result.nil? || result.empty?
|
372
|
+
# next if result.nil?
|
373
|
+
# next if result.empty?
|
374
|
+
# return result
|
375
|
+
else Curses.beep
|
59
376
|
end
|
60
377
|
RubyText.show_cursor
|
61
378
|
end
|
62
379
|
end
|
63
380
|
|
381
|
+
# Simple menu with rows of strings (or Procs)
|
382
|
+
|
64
383
|
def menu(r: :center, c: :center, items:, curr: 0,
|
65
|
-
border: true,
|
66
|
-
title: nil, fg: Green, bg: Black)
|
384
|
+
border: true, sticky: false,
|
385
|
+
title: nil, fg: Green, bg: Black, wrap: false)
|
67
386
|
RubyText.hide_cursor
|
68
387
|
if items.is_a?(Hash)
|
69
388
|
results = items.values
|
@@ -103,15 +422,23 @@ module RubyText
|
|
103
422
|
ch = getch
|
104
423
|
case ch
|
105
424
|
when Up
|
106
|
-
|
107
|
-
|
108
|
-
|
425
|
+
if sel > 0
|
426
|
+
sel -= 1
|
427
|
+
else
|
428
|
+
sel = max if wrap # asteroids mode :)
|
429
|
+
end
|
430
|
+
when Down, " " # let space mean down?
|
431
|
+
if sel < max
|
432
|
+
sel += 1
|
433
|
+
else
|
434
|
+
sel = 0 if wrap # asteroids mode :)
|
435
|
+
end
|
109
436
|
when Esc
|
110
437
|
self.restback(high, wide, r, c)
|
111
438
|
RubyText.show_cursor
|
112
439
|
return [nil, nil]
|
113
440
|
when Enter
|
114
|
-
self.restback(high, wide, r, c)
|
441
|
+
self.restback(high, wide, r, c) unless sticky
|
115
442
|
RubyText.show_cursor
|
116
443
|
choice = results[sel]
|
117
444
|
return [sel, choice] if choice.is_a? String
|
@@ -124,6 +451,8 @@ module RubyText
|
|
124
451
|
end
|
125
452
|
end
|
126
453
|
|
454
|
+
# Menu for multiple selections (buggy/unused?)
|
455
|
+
|
127
456
|
def multimenu(r: :center, c: :center,
|
128
457
|
items:, curr: 0, selected: [],
|
129
458
|
title: nil, sel_fg: Yellow, fg: White, bg: Blue)
|
@@ -175,6 +504,8 @@ module RubyText
|
|
175
504
|
end
|
176
505
|
end
|
177
506
|
|
507
|
+
# Simple yes/no decision
|
508
|
+
|
178
509
|
def yesno
|
179
510
|
# TODO: Accept YyNn
|
180
511
|
r, c = STDSCR.rc
|
@@ -182,6 +513,8 @@ module RubyText
|
|
182
513
|
num == 0
|
183
514
|
end
|
184
515
|
|
516
|
+
# Menu to choose a single setting and retain it
|
517
|
+
|
185
518
|
def radio_menu(r: :center, c: :center, items:, curr: 0,
|
186
519
|
# Handle current value better?
|
187
520
|
border: true,
|
@@ -251,6 +584,11 @@ module RubyText
|
|
251
584
|
end
|
252
585
|
end
|
253
586
|
end
|
587
|
+
end
|
588
|
+
|
589
|
+
module RubyText
|
590
|
+
|
591
|
+
# Two-paned widget with menu on left, informtional area on right
|
254
592
|
|
255
593
|
def self.selector(win: STDSCR, r: 0, c: 0, rows: 10, cols: 20,
|
256
594
|
items:, fg: White, bg: Blue,
|
@@ -301,5 +639,60 @@ module RubyText
|
|
301
639
|
rescue
|
302
640
|
retry
|
303
641
|
end
|
642
|
+
|
643
|
+
# "Menu" for checklists
|
644
|
+
|
645
|
+
def checklist(r: :center, c: :center,
|
646
|
+
items:, curr: 0, selected: [],
|
647
|
+
title: nil, sel_fg: Yellow, fg: White, bg: Blue)
|
648
|
+
RubyText.hide_cursor
|
649
|
+
high = items.size + 2
|
650
|
+
wide = items.map(&:length).max + 8
|
651
|
+
tlen = title.length + 8 rescue 0
|
652
|
+
wide = [wide, tlen].max
|
653
|
+
row, col = self.coords(r, c)
|
654
|
+
row = row - high/2 if r == :center
|
655
|
+
col = col - wide/2 if c == :center
|
656
|
+
r, c = row, col
|
657
|
+
self.saveback(high, wide, r, c)
|
658
|
+
mr, mc = r+self.r0, c+self.c0
|
659
|
+
mwin = RubyText.window(high, wide, r: mr, c: mc,
|
660
|
+
fg: fg, bg: bg, title: title)
|
661
|
+
Curses.stdscr.keypad(true)
|
662
|
+
sel = curr
|
663
|
+
max = items.size - 1
|
664
|
+
loop do
|
665
|
+
RubyText.hide_cursor # FIXME should be unnecessary
|
666
|
+
items.each.with_index do |item, row|
|
667
|
+
mwin.go row, 0
|
668
|
+
style = (sel == row) ? :reverse : :normal
|
669
|
+
color = selected.find {|x| x[0] == row } ? sel_fg : fg
|
670
|
+
label = "[ ]" + item
|
671
|
+
mwin.print fx(label, color, style)
|
672
|
+
end
|
673
|
+
ch = getch
|
674
|
+
case ch
|
675
|
+
when Up
|
676
|
+
sel -= 1 if sel > 0
|
677
|
+
when Down
|
678
|
+
sel += 1 if sel < max
|
679
|
+
when Esc
|
680
|
+
self.restback(high, wide, r, c)
|
681
|
+
RubyText.show_cursor
|
682
|
+
return []
|
683
|
+
when Enter
|
684
|
+
self.restback(high, wide, r, c)
|
685
|
+
RubyText.show_cursor
|
686
|
+
return selected.map {|i| items[i] }
|
687
|
+
when " "
|
688
|
+
selected << [sel, items[sel]]
|
689
|
+
sel += 1 if sel < max
|
690
|
+
else Curses.beep
|
691
|
+
end
|
692
|
+
RubyText.show_cursor
|
693
|
+
end
|
694
|
+
end
|
695
|
+
|
304
696
|
end
|
305
697
|
|
698
|
+
|
data/lib/navigation.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
|
+
# Reopening: Coordinate handling (1-based!)
|
2
|
+
|
1
3
|
class RubyText::Window
|
2
4
|
|
5
|
+
# Handle special coordinate names (symbols)
|
6
|
+
|
3
7
|
def coords(r, c)
|
4
8
|
r = case
|
5
9
|
when r == :center
|
@@ -24,10 +28,17 @@ class RubyText::Window
|
|
24
28
|
[r, c]
|
25
29
|
end
|
26
30
|
|
31
|
+
# Go to specified row/column in current window
|
32
|
+
|
27
33
|
def goto(r, c) # only accepts numbers!
|
28
34
|
@cwin.setpos(r, c)
|
35
|
+
@cwin.refresh
|
29
36
|
end
|
30
37
|
|
38
|
+
|
39
|
+
# Go to specified row/column in current window,
|
40
|
+
# execute block, and return cursor
|
41
|
+
|
31
42
|
def go(r0, c0)
|
32
43
|
r, c = coords(r0, c0)
|
33
44
|
save = self.rc
|
@@ -38,60 +49,84 @@ class RubyText::Window
|
|
38
49
|
end
|
39
50
|
end
|
40
51
|
|
52
|
+
# Move cursor up
|
53
|
+
|
41
54
|
def up(n=1)
|
42
55
|
r, c = rc
|
43
56
|
go r-n, c
|
44
57
|
end
|
45
58
|
|
59
|
+
# Move cursor down
|
60
|
+
|
46
61
|
def down(n=1)
|
47
62
|
r, c = rc
|
48
63
|
go r+n, c
|
49
64
|
end
|
50
65
|
|
66
|
+
# Move cursor left
|
67
|
+
|
51
68
|
def left(n=1)
|
52
69
|
r, c = rc
|
53
70
|
go r, c-n
|
54
71
|
end
|
55
72
|
|
73
|
+
# Move cursor right
|
74
|
+
|
56
75
|
def right(n=1)
|
57
76
|
r, c = rc
|
58
77
|
go r, c+n
|
59
78
|
end
|
60
79
|
|
80
|
+
# Move cursor to top of window
|
81
|
+
|
61
82
|
def top
|
62
83
|
r, c = rc
|
63
84
|
go 0, c
|
64
85
|
end
|
65
86
|
|
87
|
+
# Move cursor to bottom of window
|
88
|
+
|
66
89
|
def bottom
|
67
90
|
r, c = rc
|
68
91
|
rmax = self.rows - 1
|
69
92
|
go rmax, c
|
70
93
|
end
|
71
94
|
|
95
|
+
# Move cursor to top of window
|
96
|
+
|
72
97
|
def up!
|
73
98
|
top
|
74
99
|
end
|
75
100
|
|
101
|
+
# Move cursor to bottom of window
|
102
|
+
|
76
103
|
def down!
|
77
104
|
bottom
|
78
105
|
end
|
79
106
|
|
107
|
+
# Move cursor to far left of window
|
108
|
+
|
80
109
|
def left!
|
81
110
|
r, c = rc
|
82
111
|
go r, 0
|
83
112
|
end
|
84
113
|
|
114
|
+
# Move cursor to far left of window
|
115
|
+
|
85
116
|
def right!
|
86
117
|
r, c = rc
|
87
118
|
cmax = self.cols - 1
|
88
119
|
go r, cmax
|
89
120
|
end
|
90
121
|
|
122
|
+
# Move cursor to home (upper left)
|
123
|
+
|
91
124
|
def home
|
92
125
|
go 0, 0
|
93
126
|
end
|
94
127
|
|
128
|
+
# Return current row/column
|
129
|
+
|
95
130
|
def rc
|
96
131
|
[@cwin.cury, @cwin.curx]
|
97
132
|
end
|
data/lib/output.rb
CHANGED
@@ -123,17 +123,31 @@ class RubyText::Window
|
|
123
123
|
$stdscr = STDSCR
|
124
124
|
end
|
125
125
|
|
126
|
+
=begin
|
127
|
+
def go(r0, c0)
|
128
|
+
r, c = coords(r0, c0)
|
129
|
+
save = self.rc
|
130
|
+
goto r, c
|
131
|
+
if block_given?
|
132
|
+
yield
|
133
|
+
goto *save
|
134
|
+
end
|
135
|
+
end
|
136
|
+
=end
|
137
|
+
|
126
138
|
def [](r, c)
|
127
|
-
|
128
|
-
|
129
|
-
|
139
|
+
r0, c0 = self.rc
|
140
|
+
@cwin.setpos(r, c)
|
141
|
+
ch = @cwin.inch
|
142
|
+
@cwin.setpos(r0, c0)
|
130
143
|
ch.chr
|
131
144
|
end
|
132
145
|
|
133
146
|
def []=(r, c, char)
|
147
|
+
r0, c0 = self.rc
|
134
148
|
@cwin.setpos(r, c)
|
135
149
|
@cwin.addch(char[0].ord|Curses::A_NORMAL)
|
136
|
-
@cwin.setpos(
|
150
|
+
@cwin.setpos(r0, c0)
|
137
151
|
@cwin.refresh
|
138
152
|
end
|
139
153
|
|
data/lib/rubytext_version.rb
CHANGED
data/lib/settings.rb
CHANGED
@@ -9,7 +9,7 @@ module RubyText
|
|
9
9
|
@current = @defaults.dup
|
10
10
|
@stack = []
|
11
11
|
@stack.push @current # Note: Never let stack be empty
|
12
|
-
set_curses(
|
12
|
+
set_curses(**@current) # Set them for real
|
13
13
|
# FIXME To be continued...
|
14
14
|
end
|
15
15
|
|
@@ -39,7 +39,7 @@ module RubyText
|
|
39
39
|
cursor ||= @current[:cursor]
|
40
40
|
@stack.push @current
|
41
41
|
@current = {raw: raw, echo: echo, cbreak: cbreak, keypad: keypad, cursor: cursor}
|
42
|
-
set_curses(
|
42
|
+
set_curses(**@current)
|
43
43
|
end
|
44
44
|
|
45
45
|
def reset_boolean
|
@@ -57,7 +57,7 @@ module RubyText
|
|
57
57
|
sym0 = val ? sym : str[1..-1].to_sym
|
58
58
|
list[sym0] = val
|
59
59
|
end
|
60
|
-
set_boolean(list)
|
60
|
+
set_boolean(**list)
|
61
61
|
# allow a block here?
|
62
62
|
end
|
63
63
|
|
@@ -101,6 +101,7 @@ module RubyText
|
|
101
101
|
Object.const_set(:STDSCR, main) unless defined? STDSCR
|
102
102
|
$stdscr = STDSCR # FIXME global needed?
|
103
103
|
Object.include(WindowIO)
|
104
|
+
Curses.ESCDELAY = 10
|
104
105
|
@started = true
|
105
106
|
# rescue => err
|
106
107
|
# puts(err.inspect)
|
@@ -129,7 +130,7 @@ module RubyText
|
|
129
130
|
if name[0] == '_'
|
130
131
|
Curses.send(name[1..-1], *args)
|
131
132
|
else
|
132
|
-
raise "#{name} #{args.inspect}" # NoMethodError
|
133
|
+
raise "Missing: #{name} #{args.inspect}" # NoMethodError
|
133
134
|
end
|
134
135
|
end
|
135
136
|
|