curses-extension 1.3 → 2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a03325b4dbf6aa5c2cd506e50e642f62588a07cc543314d98eafce40cb7d2e3
4
- data.tar.gz: 2862dc209031c64df476ca07c3bd7fcba8f2929620966492f53f858903f30207
3
+ metadata.gz: 0a272233095a365552a978ea26953df75a91f985ca30a9765f7191338ffc5468
4
+ data.tar.gz: 6b807771cb90a3bc5bdbec098f01ec31414f55bfdb982cdf88cf3b0b62f33ca2
5
5
  SHA512:
6
- metadata.gz: be4ab27081169af7f9219df23272012e287e3f838f78407bc495d7470f522d1c1fd9c945c7b3ce99ea9dd48a81930ab2a7411e76efbe0b11d75da18a86af425d
7
- data.tar.gz: 3eaa3fba2972af226cffa6380d55a3a3e034bc0ba8984c2893d6cec6cee7801eafdbbae023c711195217f5def9e48e34450dbf97229762d9a20d1f7b8ad4a6bd
6
+ metadata.gz: 5fa593f92f9cdbb0774350fb4fa2c956f9be7435021c52559770fe2c3c35bb7753d25f35b69e7b192818f3ae795be7705374c3c02e1714f14573d75c1b079ae9
7
+ data.tar.gz: 445fcf7a916887d489d16835044513c8ad76664bfa9ed7163663a9edb12ca307806b671b7e76f4d847da53613f27e1563fdda69ff62e25d772ea2cde5436463f
data/lib/README.md CHANGED
@@ -1,31 +1,43 @@
1
1
  # Ruby-Curses-Class-Extension
2
- Extending the Ruby Curses module with some obvious functionality
2
+ Extending the Ruby Curses module with some obvious needed functionality.
3
+
4
+ With this extension, you don't need to initiate any color pairs or add text to
5
+ windows with odd syntax. Use any foreground and backround color you see fit
6
+ and let this extension take care of the weird need to pair colors and initiate
7
+ the color pairs. You also get a bunch of extra methods to manipulate curses
8
+ windows.
9
+
10
+ With this extension writing text to windows becomes a breeze. You can set
11
+ default foreground, background and attribute for a window (e.g. `win.fg =
12
+ 124`, `win.bg = 234` and `win.attr = Curses::A_BOLD`) - and you can write text
13
+ to a window with `win.p("Hello World")` where the defaults will be applied.
14
+ You can override the defaults with e.g. `win.p(124, "Hello World")` to write
15
+ the text in red or `win.p(76, 240, Curses::A_BOLD, "Hello World")` to write
16
+ the text in bold green on a gray background.
17
+
3
18
 
4
19
  ## Attributes
5
20
  Attribute | Description
6
21
  --------------------|--------------------------------------------------------
7
- color | Set the window's color to an already initiated color pair (with `init_pair(index, forground, backround`)
8
22
  fg | Foreground color for window (0-255)
9
23
  bg | Background color for window (0-255)
10
24
  attr | Attributes for window (such as Curses::A_BOLD) - string with "\|" (such as Curses::A_BOLD \| Curses::A_UNDERLINE)
11
25
  update | Whether to update the window on the next refresh
26
+ index | Used to track an index for each window (used to display lists such as the content of a directory, etc.)
12
27
 
13
28
  ## Functions
14
29
  Function | Description
15
30
  ------------------------------------|--------------------------------------------------------
16
31
  clr | Clears window without flicker (win.clear flickers)
17
- clr_to_cur_pos | Clears the window up to the current line
18
- clr_from_cur_pos | Clears the rest of the window after the current line
32
+ clr_to_cur_line | Clears the window up to the current line
33
+ clr_from_cur_line | Clears the rest of the window after the current line
19
34
  fill | Fill window with color as set by :color ( or :bg if not :color is set)
20
35
  fill_to_cur_pos | Fill the window up to the current line
21
36
  fill_from_cur_pos | Fill the rest of the window after the current line
22
- p(text) | Write text to window with color or fg/bg and attributes (will handle the exceptions if no colors are set)
37
+ p(fg, bg, attr, text) | Write text to window with fg/bg and attributes (will handle the exceptions if no colors are set).
38
+ You can use `puts` instead of `p` (it's an alias)
23
39
  pclr(text) | As `p(text)` but also clears the rest of the window
24
- pa(fg, bg, attr, text) | Write text to window with specified fg, bg and attribute(s)
25
- paclr(text) | As `pa(text)` but also clears the rest of the window
26
- print(text, fg=255, bg=0, attr=0) | Print text (from current position) with optional attributes
27
- puts(text, fg=255, bg=0, attr=0) | Clears window and puts text with optional attributes
28
- format_text(text) | Format text so that it linebreaks neatly inside window
40
+ format(text) | Format text so that it linebreaks neatly inside window
29
41
 
30
42
  ## Curses template
31
- The `curses_template.rb` includes the class extension and serves as the basis for my curses applications.
43
+ The `curses_template.rb` includes the class extension and serves as the basis for my curses applications. It is a runnable curses application that does nothing.
@@ -1,11 +1,26 @@
1
1
  class Curses::Window # CLASS EXTENSION
2
2
  # General extensions (see https://github.com/isene/Ruby-Curses-Class-Extension)
3
- attr_accessor :color, :fg, :bg, :attr, :update, :index
4
- # Set self.color for an already defined color pair such as: init_pair(1, 255, 3)
5
- # The color pair is defined like this: init_pair(index, foreground, background)
6
- # self.fg is set for the foreground color (and is used if self.color is not set)
7
- # self.bg is set for the background color (and is used if self.color is not set)
3
+ # This is a class extension to Ruby Curses - a class in dire need of such.
4
+ # self.pair keeps a registry of colors as they are encountered - defined with:
5
+ # init_pair(index, foreground, background)
6
+ # self.fg is set for the foreground color
7
+ # self.bg is set for the background color
8
8
  # self.attr is set for text attributes like Curses::A_BOLD
9
+ # self.update can be used to indicate if a window should be updated (true/false)
10
+ # self.index can be used to keep track of the current list item in a window
11
+ attr_accessor :fg, :bg, :attr, :update, :index
12
+ def self.pair(fg, bg)
13
+ @p = [[]] if @p == nil
14
+ fg = fg.to_i; bg = bg.to_i
15
+ if @p.include?([fg,bg])
16
+ @p.index([fg,bg])
17
+ else
18
+ @p.push([fg,bg])
19
+ cp = @p.index([fg,bg])
20
+ init_pair(cp, fg, bg)
21
+ @p.index([fg,bg])
22
+ end
23
+ end
9
24
  def clr # Clears the whole window
10
25
  self.setpos(0, 0)
11
26
  self.maxy.times {self.deleteln()}
@@ -32,15 +47,11 @@ class Curses::Window # CLASS EXTENSION
32
47
  x = self.curx
33
48
  y = self.cury
34
49
  self.setpos(0, 0)
50
+ self.bg = 0 if self.bg == nil
51
+ self.fg = 255 if self.fg == nil
35
52
  blank = " " * self.maxx
36
- if self.color == nil
37
- self.bg = 0 if self.bg == nil
38
- self.fg = 255 if self.fg == nil
39
- init_pair(self.fg, self.fg, self.bg)
40
- y.times {self.attron(color_pair(self.fg)) {self << blank}}
41
- else
42
- y.times {self.attron(color_pair(self.color)) {self << blank}}
43
- end
53
+ cp = Curses::Window.pair(self.fg, self.bg)
54
+ y.times {self.attron(color_pair(cp)) {self << blank}}
44
55
  self.refresh
45
56
  self.setpos(y, x)
46
57
  end
@@ -48,60 +59,30 @@ class Curses::Window # CLASS EXTENSION
48
59
  x = self.curx
49
60
  y = self.cury
50
61
  self.setpos(y, 0)
62
+ self.bg = 0 if self.bg == nil
63
+ self.fg = 255 if self.fg == nil
51
64
  blank = " " * self.maxx
52
- if self.color == nil
53
- self.bg = 0 if self.bg == nil
54
- self.fg = 255 if self.fg == nil
55
- init_pair(self.fg, self.fg, self.bg)
56
- self.maxy.times {self.attron(color_pair(self.fg)) {self << blank}}
57
- else
58
- self.maxy.times {self.attron(color_pair(self.color)) {self << blank}}
59
- end
65
+ cp = Curses::Window.pair(self.fg, self.bg)
66
+ self.maxy.times {self.attron(color_pair(cp)) {self << blank}}
60
67
  self.refresh
61
68
  self.setpos(y, x)
62
69
  end
63
- def p(text) # Puts text to window
64
- self.attr = 0 if self.attr == nil
65
- if self.color == nil
66
- self.bg = 0 if self.bg == nil
67
- self.fg = 255 if self.fg == nil
68
- init_pair(self.fg, self.fg, self.bg)
69
- self.attron(color_pair(self.fg) | self.attr) { self << text }
70
- else
71
- self.attron(color_pair(self.color) | self.attr) { self << text }
72
- end
70
+ def p(fg = self.fg, bg = self.bg, attr = self.attr, text) # Puts text to window with full set of attributes
71
+ fg = 255 if fg == nil
72
+ bg = 0 if bg == nil
73
+ attr = 0 if attr == nil
74
+ cp = Curses::Window.pair(fg, bg)
75
+ self.attron(color_pair(cp) | attr) { self << text }
73
76
  self.refresh
74
77
  end
75
- def pclr(text) # Puts text to window and clears the rest of the window
76
- self.p(text)
78
+ def pclr(fg = self.fg, bg = self.bg, attr = self.attr, text) # Puts text to window with full set of attributes and clears rest of window
79
+ self.p(fg, bg, attr, text)
77
80
  self.clr_from_cur_line
78
81
  end
79
- def paclr(fg, bg, attr, text) # Puts text to window with full set of attributes and clears rest of window
80
- self.paclr(fg, bg, attr, text)
81
- self.clr_from_cur_line
82
- end
83
- def pa(fg, bg, attr, text) # Puts text to window with full set of attributes
84
- self.fg = fg
85
- self.bg = bg
86
- self.attr = attr
87
- init_pair(self.fg, self.fg, self.bg)
88
- self.attron(color_pair(self.fg) | self.attr) { self << text }
89
- self.refresh
90
- end
91
- def puts(text, fg=255, bg=0, attr=0) # Clears window and puts text with optional attributes
92
- self.clr
93
- self.refresh
94
- self.setpos(0, 0)
95
- self.print(text, fg, bg, attr)
96
- end
97
- def print(text, fg=255, bg=0, attr=0) # Print text (from current position) with optional attributes
98
- init_pair(fg, fg, bg)
99
- self.attron(color_pair(fg) | attr) { self << text }
100
- self.refresh
101
- end
102
- def format_text(text) # Format text so that it linebreaks neatly inside window
82
+ def format(text) # Format text so that it linebreaks neatly inside window
103
83
  return "\n" + text.gsub(/(.{1,#{self.maxx}})( +|$\n?)|(.{1,#{self.maxx}})/, "\\1\\3\n")
104
84
  end
85
+ alias :puts :p
105
86
  end
106
87
 
107
88
  # vim: set sw=2 sts=2 et fdm=syntax fdn=2 fcs=fold\:\ :
@@ -8,10 +8,10 @@
8
8
  # +-------------------------------+
9
9
  # | @w_t |
10
10
  # +---------------+---------------+
11
- # | | |
12
11
  # | @w_l | @w_r |
13
12
  # | | |
14
13
  # | | |
14
+ # | | |
15
15
  # +---------------+---------------+
16
16
  # | @w_b |
17
17
  # +-------------------------------+
@@ -32,12 +32,27 @@ end
32
32
 
33
33
  class Curses::Window # CLASS EXTENSION
34
34
  # General extensions (see https://github.com/isene/Ruby-Curses-Class-Extension)
35
- attr_accessor :color, :fg, :bg, :attr, :update, :index
36
- # Set self.color for an already defined color pair such as: init_pair(1, 255, 3)
37
- # The color pair is defined like this: init_pair(index, foreground, background)
38
- # self.fg is set for the foreground color (and is used if self.color is not set)
39
- # self.bg is set for the background color (and is used if self.color is not set)
35
+ # This is a class extension to Ruby Curses - a class in dire need of such.
36
+ # self.pair keeps a registry of colors as they are encountered - defined with:
37
+ # init_pair(index, foreground, background)
38
+ # self.fg is set for the foreground color
39
+ # self.bg is set for the background color
40
40
  # self.attr is set for text attributes like Curses::A_BOLD
41
+ # self.update can be used to indicate if a window should be updated (true/false)
42
+ # self.index can be used to keep track of the current list item in a window
43
+ attr_accessor :fg, :bg, :attr, :update, :index
44
+ def self.pair(fg, bg)
45
+ @p = [[]] if @p == nil
46
+ fg = fg.to_i; bg = bg.to_i
47
+ if @p.include?([fg,bg])
48
+ @p.index([fg,bg])
49
+ else
50
+ @p.push([fg,bg])
51
+ cp = @p.index([fg,bg])
52
+ init_pair(cp, fg, bg)
53
+ @p.index([fg,bg])
54
+ end
55
+ end
41
56
  def clr # Clears the whole window
42
57
  self.setpos(0, 0)
43
58
  self.maxy.times {self.deleteln()}
@@ -64,15 +79,11 @@ class Curses::Window # CLASS EXTENSION
64
79
  x = self.curx
65
80
  y = self.cury
66
81
  self.setpos(0, 0)
82
+ self.bg = 0 if self.bg == nil
83
+ self.fg = 255 if self.fg == nil
67
84
  blank = " " * self.maxx
68
- if self.color == nil
69
- self.bg = 0 if self.bg == nil
70
- self.fg = 255 if self.fg == nil
71
- init_pair(self.fg, self.fg, self.bg)
72
- y.times {self.attron(color_pair(self.fg)) {self << blank}}
73
- else
74
- y.times {self.attron(color_pair(self.color)) {self << blank}}
75
- end
85
+ cp = Curses::Window.pair(self.fg, self.bg)
86
+ y.times {self.attron(color_pair(cp)) {self << blank}}
76
87
  self.refresh
77
88
  self.setpos(y, x)
78
89
  end
@@ -80,60 +91,30 @@ class Curses::Window # CLASS EXTENSION
80
91
  x = self.curx
81
92
  y = self.cury
82
93
  self.setpos(y, 0)
94
+ self.bg = 0 if self.bg == nil
95
+ self.fg = 255 if self.fg == nil
83
96
  blank = " " * self.maxx
84
- if self.color == nil
85
- self.bg = 0 if self.bg == nil
86
- self.fg = 255 if self.fg == nil
87
- init_pair(self.fg, self.fg, self.bg)
88
- self.maxy.times {self.attron(color_pair(self.fg)) {self << blank}}
89
- else
90
- self.maxy.times {self.attron(color_pair(self.color)) {self << blank}}
91
- end
97
+ cp = Curses::Window.pair(self.fg, self.bg)
98
+ self.maxy.times {self.attron(color_pair(cp)) {self << blank}}
92
99
  self.refresh
93
100
  self.setpos(y, x)
94
101
  end
95
- def p(text) # Puts text to window
96
- self.attr = 0 if self.attr == nil
97
- if self.color == nil
98
- self.bg = 0 if self.bg == nil
99
- self.fg = 255 if self.fg == nil
100
- init_pair(self.fg, self.fg, self.bg)
101
- self.attron(color_pair(self.fg) | self.attr) { self << text }
102
- else
103
- self.attron(color_pair(self.color) | self.attr) { self << text }
104
- end
102
+ def p(fg = self.fg, bg = self.bg, attr = self.attr, text) # Puts text to window with full set of attributes
103
+ fg = 255 if fg == nil
104
+ bg = 0 if bg == nil
105
+ attr = 0 if attr == nil
106
+ cp = Curses::Window.pair(fg, bg)
107
+ self.attron(color_pair(cp) | attr) { self << text }
105
108
  self.refresh
106
109
  end
107
- def pclr(text) # Puts text to window and clears the rest of the window
108
- self.p(text)
109
- self.clr_from_cur_line
110
- end
111
- def paclr(fg, bg, attr, text) # Puts text to window with full set of attributes and clears rest of window
112
- self.paclr(fg, bg, attr, text)
110
+ def pclr(fg = self.fg, bg = self.bg, attr = self.attr, text) # Puts text to window with full set of attributes and clears rest of window
111
+ self.p(fg, bg, attr, text)
113
112
  self.clr_from_cur_line
114
113
  end
115
- def pa(fg, bg, attr, text) # Puts text to window with full set of attributes
116
- self.fg = fg
117
- self.bg = bg
118
- self.attr = attr
119
- init_pair(self.fg, self.fg, self.bg)
120
- self.attron(color_pair(self.fg) | self.attr) { self << text }
121
- self.refresh
122
- end
123
- def puts(text, fg=255, bg=0, attr=0) # Clears window and puts text with optional attributes
124
- self.clr
125
- self.refresh
126
- self.setpos(0, 0)
127
- self.print(text, fg, bg, attr)
128
- end
129
- def print(text, fg=255, bg=0, attr=0) # Print text (from current position) with optional attributes
130
- init_pair(fg, fg, bg)
131
- self.attron(color_pair(fg) | attr) { self << text }
132
- self.refresh
133
- end
134
- def format_text(text) # Format text so that it linebreaks neatly inside window
114
+ def format(text) # Format text so that it linebreaks neatly inside window
135
115
  return "\n" + text.gsub(/(.{1,#{self.maxx}})( +|$\n?)|(.{1,#{self.maxx}})/, "\\1\\3\n")
136
116
  end
117
+ alias :puts :p
137
118
  end
138
119
 
139
120
  def getchr # Process key presses
@@ -210,6 +191,28 @@ def main_getkey # GET KEY FROM USER
210
191
  @break = true
211
192
  when 'q' # Exit
212
193
  exit 0
194
+ when '@' # Enter "Ruby debug"
195
+ cmd = w_b_getstr("◆ ", "")
196
+ @w_b.clr
197
+ @w_b.refresh
198
+ @w_b.update = true
199
+ @w_r.clr
200
+ info = "Command: #{cmd}\n\n"
201
+ begin
202
+ info += eval(cmd).to_s
203
+ rescue Exception => err
204
+ info += "Error: #{err.inspect}"
205
+ end
206
+ w_r_info(info)
207
+ @w_r.update = false
208
+ cmd = w_b_getstr("◆ ", "")
209
+ begin
210
+ @w_r.fill
211
+ @w_r.p(eval(cmd))
212
+ rescue StandardError => e
213
+ w_b("Error: #{e.inspect}")
214
+ end
215
+ #@w_b.update = false
213
216
  end
214
217
  while STDIN.ready?
215
218
  chr = STDIN.getc
@@ -219,25 +222,98 @@ end
219
222
  # TOP WINDOW FUNCTIONS
220
223
 
221
224
  # BOTTOM WINDOW FUNCTIONS
225
+ def w_b(info) # SHOW INFO IN @W_B
226
+ @w_b.clr
227
+ info = "Choose window: i=IMDB list (+/- to add/remove from My list), g=Genres (+/- to add/remove), m=My list. " if info == nil
228
+ info = info[1..(@w_b.maxx - 3)] + "…" if info.length + 3 > @w_b.maxx
229
+ info += " " * (@w_b.maxx - info.length) if info.length < @w_b.maxx
230
+ @w_b.p(info)
231
+ @w_b.update = false
232
+ end
233
+ def w_b_getstr(pretext, text) # A SIMPLE READLINE-LIKE ROUTINE
234
+ Curses.curs_set(1)
235
+ Curses.echo
236
+ stk = 0
237
+ pos = text.length
238
+ chr = ""
239
+ while chr != "ENTER"
240
+ @w_b.setpos(0,0)
241
+ text = pretext + text
242
+ text += " " * (@w_b.maxx - text.length) if text.length < @w_b.maxx
243
+ @w_b.p(text)
244
+ @w_b.setpos(0,pretext.length + pos)
245
+ @w_b.refresh
246
+ chr = getchr
247
+ case chr
248
+ when 'C-C', 'C-G'
249
+ return ""
250
+ when 'RIGHT'
251
+ pos += 1 unless pos > text.length
252
+ when 'LEFT'
253
+ pos -= 1 unless pos == 0
254
+ when 'HOME'
255
+ pos = 0
256
+ when 'END'
257
+ pos = text.length
258
+ when 'DEL'
259
+ text[pos] = ""
260
+ when 'BACK'
261
+ unless pos == 0
262
+ pos -= 1
263
+ text[pos] = ""
264
+ end
265
+ when 'LDEL'
266
+ text = ""
267
+ pos = 0
268
+ when /^.$/
269
+ text.insert(pos,chr)
270
+ pos += 1
271
+ end
272
+ end
273
+ Curses.curs_set(0)
274
+ Curses.noecho
275
+ return text
276
+ end
222
277
 
223
278
  # LEFT WINDOW FUNCTIONS
224
279
 
225
280
  # RIGHT WINDOW FUNCTIONS
226
-
281
+ def w_r_info(info) # SHOW INFO IN THE RIGHT WINDOW
282
+ begin
283
+ @w_r.clr
284
+ @w_r.refresh
285
+ @w_r.p(info)
286
+ @w_r.update = false
287
+ rescue
288
+ end
289
+ end
227
290
 
228
291
  # MAIN PROGRAM
229
292
  loop do # OUTER LOOP - (catching refreshes via 'r')
230
293
  @break = false # Initialize @break variable (set if user hits 'r')
231
- begin # Create the four windows/panels
294
+ begin # Create the four windows/panes
232
295
  maxx = Curses.cols
233
- exit if maxx < @w_l_width
234
296
  maxy = Curses.lines
235
- # Curses::Window.new(h,w,y,x)
236
- @w_t = Curses::Window.new(1, maxx, 0, 0)
237
- @w_b = Curses::Window.new(1, maxx, maxy - 1, 0)
238
- @w_l = Curses::Window.new(maxy - 2, maxx / 2, 1, 0)
239
- @w_r = Curses::Window.new(maxy - 2, maxx / 2, 1, maxx / 2)
297
+ # Create windows/panes
298
+ # Curses::Window.new ( h, w, y, x)
299
+ @w_t = Curses::Window.new( 1, maxx, 0, 0)
300
+ @w_b = Curses::Window.new( 1, maxx, maxy-1, 0)
301
+ @w_l = Curses::Window.new(maxy-2, maxx/2, 1, 0)
302
+ @w_r = Curses::Window.new(maxy-2, maxx/2, 1, maxx/2)
303
+ # Set foreground and background colors and attributes
304
+ @w_t.fg, @w_t.bg, @w_t.attr = 255, 23, 0
305
+ @w_b.fg, @w_b.bg, @w_b.attr = 231, 238, 0
306
+ @w_l.fg, @w_l.bg, @w_l.attr = 46, 234, 0
307
+ @w_r.fg, @w_r.bg, @w_r.attr = 202, 235, 0
240
308
  loop do # INNER, CORE LOOP
309
+ @w_t.fill; @w_b.fill; @w_l.fill; @w_r.fill
310
+
311
+ # Example code to write to the panes in various ways
312
+ @w_t.p("Top window")
313
+ @w_b.p("Bottom window")
314
+ @w_l.p(196,182,Curses::A_BOLD,"Left window")
315
+ @w_r.p("Right window")
316
+
241
317
  # Top window (info line)
242
318
 
243
319
  # Bottom window (command line)
@@ -246,9 +322,10 @@ loop do # OUTER LOOP - (catching refreshes via 'r')
246
322
 
247
323
  # Right window
248
324
 
249
- main_getkey # Get key from user
325
+ # Get key from user
326
+ main_getkey
250
327
 
251
- break if @break # Break to outer loop, redrawing windows, if user hit 'r'
328
+ break if @break # Break to outer loop, redrawing windows, if user hits 'r'
252
329
  break if Curses.cols != maxx or Curses.lines != maxy # break on terminal resize
253
330
  end
254
331
  ensure # On exit: close curses, clear terminal
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: curses-extension
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.3'
4
+ version: '2.1'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geir Isene
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-02 00:00:00.000000000 Z
11
+ date: 2023-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curses
@@ -35,8 +35,7 @@ description: 'The Ruby curses library is sorely lacking some important features.
35
35
  terminal curses applications in Ruby. See the Github page for information on what
36
36
  properties and functions are included: https://github.com/isene/Ruby-Curses-Class-Extension.
37
37
  The curses_template.rb is also installed in the lib directory and serves as the
38
- basis for my own curses applications. New in 1.3: Included :index as Class accessor
39
- and other improvements'
38
+ basis for my own curses applications. New in 2.1: Simplified'
40
39
  email: g@isene.com
41
40
  executables: []
42
41
  extensions: []