rubytext 0.1.23 → 0.1.25

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64b02560a60dde6b8be61c328c5ef17783f04f4d1f0d0fcdc3d01be2d1e77407
4
- data.tar.gz: 2901d7e3edd0b8df5eae3c0fe010d5b609feb125e00f79bf659e34b8cd8ce377
3
+ metadata.gz: 404061798371be530a55ad03d0c679b8d187aeee89dd40450e38d73591cacda5
4
+ data.tar.gz: 3a9587a311670022ff32037159c71e1c260f23f4bffca9365c77ecc90e3aa960
5
5
  SHA512:
6
- metadata.gz: a240d93d49063fb3428353080f30d7eecec11b2140c11cfd4552495fd663ebc987c6155f98cf72008795328779c1c09eb372c25c495ecfa3bc149c2bb502c89b
7
- data.tar.gz: 3aee37214e7afb38b29b5cfabb5d5f67b8217e777b42ca95db55bc85299ccf4bd8b51aecfab1bada8fa99aa2489420b4ff92f1a6c52fae5b16673093980e7944
6
+ metadata.gz: a086383fbc7a3b82b816f5f03b585ae86cecb15ebf123975d4d0f47c804e44bbec80f733a213526b93cb554a50d059e29f8a521b1dfd748b4755df038b465c9f
7
+ data.tar.gz: 0a1582a8bbdd7047a909611e6afa2b9cc38c6036053e82f45c20c3c388d7749488ee479e28e9efd436102a3a09156130eceace11159fc3fd9116eed8aa42ba3d
@@ -0,0 +1,56 @@
1
+ if ARGV.size != 2
2
+ STDERR.puts "Usage: ruby ide.rb libname.rb progname.rb"
3
+ exit
4
+ end
5
+
6
+ require 'rubytext'
7
+
8
+ RubyText.start
9
+
10
+ @lib, @code = ARGV
11
+
12
+ def shell(str)
13
+ STDSCR.clear
14
+ RubyText.show_cursor
15
+ system("stty sane") # FIXME - dumb hack
16
+ STDSCR.puts "\n\n When you exit, you will\n return to the IDE.\n "
17
+ system(str)
18
+ Curses.noecho # FIXME Shouldn't have to do this stuff
19
+ Curses.stdscr.keypad(true)
20
+ Curses.cbreak # by default
21
+ end
22
+
23
+ items = ["Edit lib", # 0
24
+ "Edit code", # 1
25
+ "Run code", # 2
26
+ "pry", # 3
27
+ "Shell", # 4
28
+ "irb", # 5
29
+ "RubyDocs", # 6
30
+ "Quit"] # 7
31
+
32
+ def show
33
+ STDSCR.clear
34
+ puts
35
+ puts " World's Simplest Ruby IDE\n "
36
+ puts " Lib = #{@lib}"
37
+ puts " Code = #{@code}"
38
+ puts
39
+ end
40
+
41
+ loop do
42
+ show
43
+ n, str = STDSCR.menu(r: 10, c: 5, items: items)
44
+ puts n.inspect
45
+ case n
46
+ when 0; system("vi #{@lib}")
47
+ when 1; system("vi #{@code}")
48
+ when 2; system("tput clear; ruby #{@code}; sleep 5")
49
+ when 3; shell("pry")
50
+ when 4; shell("bash")
51
+ when 5; shell("irb")
52
+ when 6; system("open -a Safari http://ruby-doc.org")
53
+ when 7; exit
54
+ end
55
+ end
56
+
data/lib/menu.rb CHANGED
@@ -1,3 +1,313 @@
1
+ #### FIXME LATER
2
+
3
+ # The top-level module
4
+
5
+ module RubyText
6
+
7
+ # Wrapper for a curses window
8
+
9
+ class Window
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)
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
+
1
311
  # The top-level module
2
312
 
3
313
  module RubyText
@@ -9,16 +319,13 @@ module RubyText
9
319
  # One-line menu at top of window
10
320
 
11
321
  def topmenu(items:, curr: 0, fg: Green, bg: Black)
12
- r, c = 0, 0
13
- high = 1
14
-
322
+ r, c, high = 0, 0, 1
15
323
  RubyText.hide_cursor
324
+ hash_flag = false
325
+ results = items
16
326
  if items.is_a?(Hash)
17
- results = items.values
18
- items = items.keys
327
+ results, items = items.values, items.keys
19
328
  hash_flag = true
20
- else
21
- results = items
22
329
  end
23
330
 
24
331
  width = 0 # total width
@@ -52,16 +359,19 @@ module RubyText
52
359
  when Esc, " " # spacebar also quits
53
360
  self.restback(high, width, r, c)
54
361
  RubyText.show_cursor
362
+ STDSCR.go r, c
55
363
  return [nil, nil]
56
364
  when Down, Enter
57
365
  self.restback(high, width, r, c)
58
366
  RubyText.show_cursor
367
+ STDSCR.go r, c
59
368
  choice = results[sel]
60
369
  return [sel, choice] if choice.is_a? String
61
370
  result = choice.call
62
- next if result.nil?
63
- next if result.empty?
64
- return result
371
+ return [nil, nil, nil] if result.nil? || result.empty?
372
+ # next if result.nil?
373
+ # next if result.empty?
374
+ # return result
65
375
  else Curses.beep
66
376
  end
67
377
  RubyText.show_cursor
@@ -72,7 +382,7 @@ module RubyText
72
382
 
73
383
  def menu(r: :center, c: :center, items:, curr: 0,
74
384
  border: true, sticky: false,
75
- title: nil, fg: Green, bg: Black)
385
+ title: nil, fg: Green, bg: Black, wrap: false)
76
386
  RubyText.hide_cursor
77
387
  if items.is_a?(Hash)
78
388
  results = items.values
@@ -112,9 +422,17 @@ module RubyText
112
422
  ch = getch
113
423
  case ch
114
424
  when Up
115
- sel -= 1 if sel > 0
116
- when Down
117
- sel += 1 if sel < max
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
118
436
  when Esc
119
437
  self.restback(high, wide, r, c)
120
438
  RubyText.show_cursor
@@ -377,3 +695,4 @@ module RubyText
377
695
 
378
696
  end
379
697
 
698
+
@@ -1,6 +1,6 @@
1
1
 
2
2
  module RubyText
3
- VERSION = "0.1.23"
3
+ VERSION = "0.1.25"
4
4
 
5
5
  Path = File.expand_path(File.join(File.dirname(__FILE__)))
6
6
  end
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(@current) # Set them for real
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(@current)
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
 
@@ -130,7 +130,7 @@ module RubyText
130
130
  if name[0] == '_'
131
131
  Curses.send(name[1..-1], *args)
132
132
  else
133
- raise "#{name} #{args.inspect}" # NoMethodError
133
+ raise "Missing: #{name} #{args.inspect}" # NoMethodError
134
134
  end
135
135
  end
136
136
 
data/lib/widgets.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'stringio'
2
+
1
3
  module RubyText
2
4
  def self.ticker(row: STDSCR.rows-1, col: 0, width: STDSCR.cols,
3
5
  fg: White, bg: Blue, text:, delay: 0.1)
@@ -35,14 +37,20 @@ module RubyText
35
37
  ret
36
38
  end
37
39
 
38
- def self.splash(msg)
40
+ def self.splash(msg = nil)
41
+ io = StringIO.new("")
42
+ if msg.nil?
43
+ yield io
44
+ msg = io.string
45
+ end
46
+
39
47
  lines = msg.split("\n")
40
48
  high = lines.size + 4
41
49
  wide = lines.map {|x| x.length }.max + 4
42
50
  r0 = (STDSCR.rows - high)/2
43
51
  c0 = (STDSCR.cols - wide)/2
44
52
  STDSCR.saveback(high, wide, r0, c0)
45
- win = RubyText.window(high, wide, r: r0, c: c0,
53
+ win = RubyText.window(high, wide, r: r0, c: c0, scroll: true,
46
54
  fg: White, bg: Red, title: "[Press any key]")
47
55
  win.print "\n "
48
56
  win.puts msg
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubytext
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.23
4
+ version: 0.1.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hal Fulton
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-15 00:00:00.000000000 Z
11
+ date: 2022-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curses
@@ -72,6 +72,7 @@ files:
72
72
  - examples/sym_navigate.rb
73
73
  - examples/ticker_threads.rb
74
74
  - examples/topbottom.rb
75
+ - examples/topmenu.rb
75
76
  - examples/udlr_bang.rb
76
77
  - examples/updown_etc.rb
77
78
  - examples/win_centering.rb
@@ -145,7 +146,7 @@ homepage: https://github.com/Hal9000/rubytext
145
146
  licenses:
146
147
  - Ruby
147
148
  metadata: {}
148
- post_install_message:
149
+ post_install_message:
149
150
  rdoc_options: []
150
151
  require_paths:
151
152
  - lib
@@ -160,8 +161,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
161
  - !ruby/object:Gem::Version
161
162
  version: '0'
162
163
  requirements: []
163
- rubygems_version: 3.0.4
164
- signing_key:
164
+ rubygems_version: 3.1.2
165
+ signing_key:
165
166
  specification_version: 4
166
167
  summary: A thick wrapper for Curses
167
168
  test_files: []