rbcurse 1.5.0 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
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,309 @@
1
+ require 'rbcurse/core/system/ncurses'
2
+ module RubyCurses
3
+ #
4
+ # an attempt to make a window based on stdscr for bottom line printing so the entire
5
+ # application can have one pointer, regardless of whether through App
6
+ # or otherwise. This still provides the full getchar operation, copied from
7
+ # Window class which is the main purpose of this. So as to provide ask, agree and say.
8
+ #
9
+ # We should be able to pass this window to bottomline and have one global bottomline
10
+ # created once (by window class ?)
11
+ #
12
+ # FFI: 2011-09-9 The change to FFI has affected this a lot since I do not get window
13
+ # methods in rbcurse for stdscr whereas suprisingly if i run the samples, i get them
14
+ # all.
15
+ #
16
+ # NOTE:
17
+ # WARNING: Pls do not use this class. This was just experimentation. Using stdscr
18
+ # mucks up the display and overwrites objects on the screen. I will remove this class
19
+ # at some time.
20
+ #
21
+ class StdscrWindow
22
+ attr_reader :width, :height, :top, :left
23
+
24
+ def initialize
25
+
26
+ #@window_pointer = FFI::NCurses.initscr
27
+ @window_pointer = Ncurses.initscr # FFIWINDOW
28
+ $log.debug "STDSCR window pointer is #{@window_pointer.class}"
29
+ #$log.debug "STDSCR window pointer mehtods #{@window_pointer.public_methods}"
30
+ $error_message_row ||= Ncurses.LINES-1
31
+ $error_message_col ||= 1
32
+ init_vars
33
+
34
+
35
+ end
36
+ def init_vars
37
+ #Ncurses::keypad(@window_pointer, true)
38
+ Ncurses.keypad(@window_pointer.pointer, true)
39
+ @stack = []
40
+ end
41
+ ##
42
+
43
+ # Ncurses
44
+
45
+
46
+ # taken from Window
47
+ def method_missing(name, *args)
48
+ name = name.to_s
49
+ if (name[0,2] == "mv")
50
+ test_name = name.dup
51
+ test_name[2,0] = "w" # insert "w" after"mv"
52
+ if (@window_pointer.respond_to?(test_name)) # FFIPOINTER
53
+ return @window_pointer.send(test_name,*args)
54
+ end
55
+
56
+ if (FFI::NCurses.respond_to?(test_name))
57
+ return FFI::NCurses.send(test_name, @window_pointer, *args)
58
+ end
59
+ end
60
+ test_name = "w" + name
61
+ # FFI responds but the pointer does not !!! bottomline 1045
62
+ if (@window_pointer.respond_to?(test_name)) # FFIPOINTER
63
+ return @window_pointer.send(test_name,*args)
64
+ end
65
+ if (FFI::NCurses.respond_to?(test_name))
66
+ return FFI::NCurses.send(test_name, @window_pointer, *args)
67
+ end
68
+ # what if it does not respond, can go into loop and give stack overflow
69
+ FFI::NCurses.send(name, @window_pointer, *args)
70
+ end
71
+ def respond_to?(name)
72
+ name = name.to_s
73
+ if (name[0,2] == "mv" && FFI::NCurses.respond_to?("mvw" + name[2..-1]))
74
+ return true
75
+ end
76
+ FFI::NCurses.respond_to?("w" + name) || FFI::NCurses.respond_to?(name)
77
+ end
78
+ #@window.send(meth, *args)
79
+
80
+ # FFI WARNING XXX I think these methods one window_pointer will fail
81
+ # since somehow stdscr is not getting these methods here.
82
+ def print(string, width = width)
83
+ return unless visible?
84
+ @window_pointer.waddnstr(string.to_s, width)
85
+ end
86
+
87
+ def print_yx(string, y = 0, x = 0)
88
+ @window_pointer.mvwaddnstr(y, x, string, width)
89
+ end
90
+
91
+ def print_empty_line
92
+ return unless visible?
93
+ @window_pointer.printw(' ' * width)
94
+ end
95
+
96
+ def print_line(string)
97
+ print(string.ljust(width))
98
+ end
99
+
100
+ def puts(*strings)
101
+ print(strings.join("\n") << "\n")
102
+ end
103
+
104
+ # FFI 2011-09-9 commented off so it goes to method missing
105
+ def XXXrefresh
106
+ @window_pointer.refresh
107
+ end
108
+
109
+
110
+ def color=(color)
111
+ @color = color
112
+ @window_pointer.color_set(color, nil)
113
+ end
114
+
115
+ def highlight_line(color, y, x, max)
116
+ @window_pointer.mvchgat(y, x, max, FFI::NCurses::A_NORMAL, color, nil)
117
+ end
118
+
119
+ def ungetch(ch)
120
+ FFI::NCurses.ungetch(ch)
121
+ end
122
+
123
+ # this used to work fine in ncursesruby
124
+ # but somehow in ffi, stdscr does not have most methods, i am unable to figure
125
+ # this out. C-c will crash this.
126
+ def getch
127
+ c = @window_pointer.getch # FFI NW stdscr must get key not some window
128
+ #raise "Ncurses.stdscr does not have getch" if !Ncurses.stdscr.respond_to? :getch
129
+ #$log.debug " XXXX before calling getch"
130
+ #c = Ncurses.stdscr.getch # FFIW if you use the FFIWINDOW
131
+ #c = FFI::NCurses.getch # FFI 2011-09-9 # without FFIWINDOW
132
+ #$log.debug " XXXX after calling getch #{c}"
133
+ #if c == FFI::NCurses::KEY_RESIZE
134
+ return c
135
+ rescue Interrupt => ex
136
+ 3 # is C-c
137
+ end
138
+
139
+ # returns control, alt, alt+ctrl, alt+control+shift, F1 .. etc
140
+ # ALT combinations also send a 27 before the actual key
141
+ # Please test with above combinations before using on your terminal
142
+ # added by rkumar 2008-12-12 23:07
143
+ def getchar
144
+ FFI::NCurses.raw # FFI required so that getch does not crash on C-c
145
+ while 1
146
+ ch = getch
147
+ #$log.debug "window getchar() GOT: #{ch}" if ch != -1
148
+ if ch == -1
149
+ # the returns escape 27 if no key followed it, so its SLOW if you want only esc
150
+ if @stack.first == 27
151
+ #$log.debug " -1 stack sizze #{@stack.size}: #{@stack.inspect}, ch #{ch}"
152
+ case @stack.size
153
+ when 1
154
+ @stack.clear
155
+ return 27
156
+ when 2 # basically a ALT-O, this will be really slow since it waits for -1
157
+ ch = 128 + @stack.last
158
+ @stack.clear
159
+ return ch
160
+ when 3
161
+ $log.debug " SHOULD NOT COME HERE getchar()"
162
+ end
163
+ end
164
+ @stack.clear
165
+ next
166
+ end
167
+ # this is the ALT combination
168
+ if @stack.first == 27
169
+ # experimental. 2 escapes in quick succession to make exit faster
170
+ if ch == 27
171
+ @stack.clear
172
+ return ch
173
+ end
174
+ # possible F1..F3 on xterm-color
175
+ if ch == 79 or ch == 91
176
+ #$log.debug " got 27, #{ch}, waiting for one more"
177
+ @stack << ch
178
+ next
179
+ end
180
+ #$log.debug "stack SIZE #{@stack.size}, #{@stack.inspect}, ch: #{ch}"
181
+ if @stack == [27,79]
182
+ # xterm-color
183
+ case ch
184
+ when 80
185
+ ch = KEY_F1
186
+ when 81
187
+ ch = KEY_F2
188
+ when 82
189
+ ch = KEY_F3
190
+ when 83
191
+ ch = KEY_F4
192
+ end
193
+ @stack.clear
194
+ return ch
195
+ elsif @stack == [27, 91]
196
+ if ch == 90
197
+ @stack.clear
198
+ return KEY_BTAB # backtab
199
+ end
200
+ end
201
+ # the usual Meta combos. (alt)
202
+ ch = 128 + ch
203
+ @stack.clear
204
+ return ch
205
+ end
206
+ # append a 27 to stack, actually one can use a flag too
207
+ if ch == 27
208
+ @stack << 27
209
+ next
210
+ end
211
+ return ch
212
+ end
213
+ end
214
+
215
+ def clear
216
+ # return unless visible?
217
+ move 0, 0
218
+ puts *Array.new(height){ ' ' * (width - 1) }
219
+ end
220
+
221
+
222
+ def visible?
223
+ @visible
224
+ end
225
+ ##
226
+ # added by rk 2008-11-29 19:01
227
+ # I usually use this, not the others ones here
228
+ # @param r - row
229
+ # @param c - col
230
+ # @param string - text to print
231
+ # @param color - color pair
232
+ # @ param att - ncurses attribute: normal, bold, reverse, blink,
233
+ # underline
234
+ def printstring(r,c,string, color, att = FFI::NCurses::A_NORMAL)
235
+ prv_printstring(r,c,string, color, att )
236
+ end
237
+
238
+ ## name changed from printstring to prv_prinstring
239
+ def prv_printstring(r,c,string, color, att = FFI::NCurses::A_NORMAL)
240
+
241
+ #$log.debug " #{@name} inside window printstring r #{r} c #{c} #{string} "
242
+ att = FFI::NCurses::A_NORMAL if att.nil?
243
+ case att.to_s.downcase
244
+ when 'normal'
245
+ att = FFI::NCurses::A_NORMAL
246
+ when 'underline'
247
+ att = FFI::NCurses::A_UNDERLINE
248
+ when 'bold'
249
+ att = FFI::NCurses::A_BOLD
250
+ when 'blink'
251
+ att = FFI::NCurses::A_BLINK # unlikely to work
252
+ when 'reverse'
253
+ att = FFI::NCurses::A_REVERSE
254
+ end
255
+
256
+ attron(Ncurses.COLOR_PAIR(color) | att)
257
+ # we should not print beyond window coordinates
258
+ # trying out on 2009-01-03 19:29
259
+ width = Ncurses.COLS
260
+ # the next line won't ensure we don't write outside some bounds like table
261
+ #string = string[0..(width-c)] if c + string.length > width
262
+ #$log.debug "PRINT len:#{string.length}, #{Ncurses.COLS}, #{r}, #{c} w: #{@window} "
263
+ mvprintw(r, c, "%s", string);
264
+ attroff(Ncurses.COLOR_PAIR(color) | att)
265
+ end
266
+ # added by rk 2008-11-29 19:01
267
+ # Since these methods write directly to window they are not advised
268
+ # since clearing previous message we don't know how much to clear.
269
+ # Best to map error_message to a label.
270
+ # 2010-09-13 00:22 WE should not use these any longer.
271
+ # Application should create a label and map a Variable named
272
+ # $errormessage to it. We should only update the Variable
273
+ # CLEANUP DEPRECATED
274
+ def print_error_message text=$error_message
275
+ raise "DEPRECATED CLEANUP use global method of same name"
276
+ r = $error_message_row || Ncurses.LINES-1
277
+ c = $error_message_col || (Ncurses.COLS-text.length)/2
278
+
279
+ $log.debug "got ERROR MESSAGE #{text} row #{r} "
280
+ clear_error r, $datacolor
281
+ printstring r, c, text, color = $promptcolor
282
+ $error_message_clear_pending = true
283
+ end
284
+ # added by rk 2008-11-29 19:01
285
+ # CLEANUP DEPRECATED
286
+ def print_status_message text=$status_message
287
+ raise "DEPRECATED CLEANUP use global method of same name"
288
+ r = $status_message_row || Ncurses.LINES-1
289
+ clear_error r, $datacolor
290
+ # print it in centre
291
+ printstring r, (Ncurses.COLS-text.length)/2, text, color = $promptcolor
292
+ end
293
+ # Clear error message printed
294
+ # I am not only clearing if something was printed. This is since
295
+ # certain small forms like TabbedForm top form throw an error on printstring.
296
+ #
297
+ #raise "DEPRECATED CLEANUP use global method of same name"
298
+ def clear_error r = $error_message_row, color = $datacolor
299
+ return unless $error_message_clear_pending
300
+ c = $error_message_col || (Ncurses.COLS-text.length)/2
301
+ sz = $error_message_size || Ncurses.COLS
302
+ printstring(r, c, "%-*s" % [sz, " "], color)
303
+ $error_message_clear_pending = false
304
+ end
305
+ ##
306
+ def get_window; @window_pointer; end
307
+ def to_s; @name || self; end
308
+ end
309
+ end
@@ -0,0 +1,170 @@
1
+ # Usage:
2
+ # VER::Keyboard2.focus = self
3
+ # or whatever class you have created.
4
+ # DEPENDENCIES:
5
+ # press(key) - a method that takes an int key and processes it
6
+ # stopping? returns true of false. if false, this prgram returns control
7
+ # window - gives window of caller, responding to getch
8
+ # 2008-11-24 12:41
9
+ # this differs from original in that i try to return an int so it can just replace
10
+ # existing loops without any modification
11
+ # I thus return an int not a string
12
+ module VER
13
+ module Keyboard2 # avoid initialize
14
+ ESC = 27 # keycode
15
+ @polling = false
16
+
17
+ module_function
18
+
19
+ def focus=(receiver)
20
+ @stack = []
21
+ @focus = receiver
22
+ poll unless @polling
23
+ end
24
+
25
+ def poll
26
+ @polling = true
27
+
28
+ while char = @focus.window.getch
29
+ break if @focus.stopping? # XXX
30
+ #break if VER.stopping?
31
+ $log.debug("char: #{char} stakc: #{@stack.inspect}") if char != Ncurses::ERR
32
+ if char == Ncurses::ERR # timeout or signal
33
+ #@focus.press('esc') if @stack == [ESC]
34
+ @focus.press(ESC) if @stack == [ESC]
35
+ @stack.clear
36
+ elsif ready = resolve(char)
37
+ $log.debug("char: #{char} ready: #{ready}")
38
+ @stack.clear
39
+ @focus.press(ready)
40
+ end
41
+ end
42
+
43
+ ensure
44
+ @polling = false
45
+ end
46
+
47
+ def resolve(char)
48
+ $log.debug("char: #{char} resolve") if char == ESC
49
+ @stack << char
50
+
51
+ if @stack.first == ESC
52
+ MOD_KEYS[@stack] || SPECIAL_KEYS[@stack]
53
+ elsif (char >= 0 and char < 27) or char == 32 or char == 127
54
+ char
55
+ else
56
+ #NCURSES_KEYS[char] || CONTROL_KEYS[char] || PRINTABLE_KEYS[char]
57
+ NCURSES_KEYS[char] || PRINTABLE_KEYS[char]
58
+ end
59
+ end
60
+
61
+ # TODO: make this section sane
62
+
63
+ ASCII = (0..255).map{|c| c.chr }
64
+ CONTROL = ASCII.grep(/[[:cntrl:]]/)
65
+ PRINTABLE = ASCII.grep(/[[:print:]]/)
66
+
67
+ SPECIAL_KEYS = {
68
+ [27, 79, 50, 81] => 'F14',
69
+ [27, 79, 50, 82] => 'F15',
70
+ [27, 79, 70] => 'end',
71
+ [27, 79, 70] => 'end',
72
+ [27, 79, 72] => 'home',
73
+ # [27, 79, 80] => 'F1',
74
+ [27, 79, 80] => Ncurses::KEY_F1,
75
+ [27, 79, 81] => 'F2',
76
+ [27, 79, 82] => 'F3',
77
+ [27, 79, 83] => 'F4',
78
+ [27, 91, 49, 126] => 'end',
79
+ [27, 91, 49, 126] => 'home',
80
+ [27, 91, 49, 49, 126] => Ncurses::KEY_F1,
81
+ [27, 91, 49, 50, 126] => 'F2',
82
+ [27, 91, 49, 51, 126] => 'F3',
83
+ [27, 91, 49, 52, 126] => 'F4',
84
+ [27, 91, 49, 52, 126] => 'F4',
85
+ [27, 91, 49, 53, 126] => 'F5',
86
+ [27, 91, 49, 55, 126] => 'F6',
87
+ [27, 91, 49, 56, 59, 50, 126] => 'F19',
88
+ [27, 91, 49, 56, 59, 51, 126] => 'F7',
89
+ [27, 91, 49, 59, 51, 65] => 'ppage',
90
+ [27, 91, 49, 59, 51, 66] => 'npage',
91
+ [27, 91, 49, 59, 53, 65] => 'ppage',
92
+ [27, 91, 49, 59, 53, 66] => 'npage',
93
+ [27, 91, 49, 59, 53, 70] => 'M-<',
94
+ [27, 91, 49, 59, 53, 72] => 'M->',
95
+ [27, 91, 50, 54, 126] => 'F14',
96
+ [27, 91, 50, 56, 126] => 'F15',
97
+ [27, 91, 51, 59, 51, 126] => 'del',
98
+ [27, 91, 52, 126] => 'end',
99
+ [27, 91, 55, 126] => 'home',
100
+ [27, 91, 55, 126] => 'home',
101
+ [27, 91, 56, 126] => 'end',
102
+ [27, 91, 56, 126] => 'end',
103
+ [27, 91, 65] => 'up',
104
+ [27, 91, 66] => 'down',
105
+ [27, 91, 67] => 'right',
106
+ [27, 91, 68] => 'left',
107
+ [27, 91, 70] => 'end',
108
+ [27, 91, 72] => 'end',
109
+ [27, 91, 72] => 'home',
110
+ [27, 91, 91, 65] => Ncurses::KEY_F1,
111
+ [27, 91, 91, 66] => 'F2',
112
+ [27, 91, 91, 67] => 'F3',
113
+ [27, 91, 91, 68] => 'F4',
114
+ [27, 91, 91, 69] => 'F5',
115
+ }
116
+
117
+ CONTROL_KEYS = {
118
+ 0 => 'C-space',
119
+ 1 => 'C-a',
120
+ 2 => 'C-b',
121
+ 3 => 'C-c',
122
+ 4 => 'C-d',
123
+ 5 => 'C-e',
124
+ 6 => 'C-f',
125
+ 7 => 'C-g',
126
+ 8 => 'C-h',
127
+ 9 => 'tab',
128
+ 10 => 'return', # C-j
129
+ 11 => 'C-k',
130
+ 12 => 'C-l',
131
+ 13 => 'return', # C-m
132
+ 14 => 'C-n',
133
+ 15 => 'C-o',
134
+ 16 => 'C-p',
135
+ 17 => 'C-q',
136
+ 18 => 'C-r',
137
+ 19 => 'C-s',
138
+ 20 => 'C-t',
139
+ 21 => 'C-u',
140
+ 22 => 'C-v',
141
+ 23 => 'C-w',
142
+ 24 => 'C-x',
143
+ 25 => 'C-y',
144
+ 26 => 'C-z', # FIXME: is usually suspend in shell job control
145
+ # 27 => 'esc',
146
+ 32 => 'space',
147
+ 127 => 'backspace',
148
+ }
149
+
150
+ PRINTABLE_KEYS = {}
151
+ MOD_KEYS = {}
152
+
153
+ PRINTABLE.each do |key|
154
+ code = key.unpack('c')[0] # using unpack to be compatible with 1.9
155
+ # PRINTABLE_KEYS[code] = key
156
+ # MOD_KEYS[[ESC, code]] = "M-#{key}" unless key == '[' # don't map esc
157
+ PRINTABLE_KEYS[code] = code
158
+ MOD_KEYS[[ESC, code]] = 128 + code unless key == '[' # don't map esc
159
+ end
160
+
161
+ NCURSES_KEYS = {}
162
+ Ncurses.constants.grep(/^KEY_/).each do |const|
163
+ value = Ncurses.const_get(const)
164
+ key = const[/^KEY_(.*)/, 1]
165
+ key = key =~ /^F/ ? key : key.downcase # function keys
166
+ #NCURSES_KEYS[value] = key
167
+ NCURSES_KEYS[value] = value
168
+ end
169
+ end
170
+ end