rbcurse 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/CHANGELOG +1570 -0
  2. data/History.txt +6 -0
  3. data/Manifest.txt +54 -0
  4. data/README.txt +304 -0
  5. data/Rakefile +28 -0
  6. data/examples/qdfilechooser.rb +68 -0
  7. data/examples/rfe.rb +853 -0
  8. data/examples/rfe_renderer.rb +69 -0
  9. data/examples/test1.rb +242 -0
  10. data/examples/test2.rb +498 -0
  11. data/examples/testcombo.rb +95 -0
  12. data/examples/testkeypress.rb +61 -0
  13. data/examples/testmenu.rb +105 -0
  14. data/examples/testtable.rb +266 -0
  15. data/examples/testtabp.rb +106 -0
  16. data/examples/testtodo.rb +532 -0
  17. data/examples/viewtodo.rb +512 -0
  18. data/lib/rbcurse/action.rb +31 -0
  19. data/lib/rbcurse/applicationheader.rb +57 -0
  20. data/lib/rbcurse/celleditor.rb +120 -0
  21. data/lib/rbcurse/checkboxcellrenderer.rb +69 -0
  22. data/lib/rbcurse/colormap.rb +133 -0
  23. data/lib/rbcurse/comboboxcellrenderer.rb +45 -0
  24. data/lib/rbcurse/defaultlistselectionmodel.rb +49 -0
  25. data/lib/rbcurse/keylabelprinter.rb +143 -0
  26. data/lib/rbcurse/listcellrenderer.rb +99 -0
  27. data/lib/rbcurse/listkeys.rb +33 -0
  28. data/lib/rbcurse/listscrollable.rb +216 -0
  29. data/lib/rbcurse/listselectable.rb +67 -0
  30. data/lib/rbcurse/mapper.rb +108 -0
  31. data/lib/rbcurse/orderedhash.rb +77 -0
  32. data/lib/rbcurse/rcombo.rb +243 -0
  33. data/lib/rbcurse/rdialogs.rb +183 -0
  34. data/lib/rbcurse/rform.rb +845 -0
  35. data/lib/rbcurse/rinputdataevent.rb +36 -0
  36. data/lib/rbcurse/rlistbox.rb +804 -0
  37. data/lib/rbcurse/rmenu.rb +666 -0
  38. data/lib/rbcurse/rmessagebox.rb +325 -0
  39. data/lib/rbcurse/rpopupmenu.rb +754 -0
  40. data/lib/rbcurse/rtabbedpane.rb +259 -0
  41. data/lib/rbcurse/rtable.rb +1296 -0
  42. data/lib/rbcurse/rtextarea.rb +673 -0
  43. data/lib/rbcurse/rtextview.rb +335 -0
  44. data/lib/rbcurse/rwidget.rb +1731 -0
  45. data/lib/rbcurse/scrollable.rb +301 -0
  46. data/lib/rbcurse/selectable.rb +94 -0
  47. data/lib/rbcurse/table/tablecellrenderer.rb +85 -0
  48. data/lib/rbcurse/table/tabledatecellrenderer.rb +102 -0
  49. data/lib/rbcurse.rb +7 -0
  50. data/lib/ver/keyboard.rb +150 -0
  51. data/lib/ver/keyboard2.rb +170 -0
  52. data/lib/ver/ncurses.rb +102 -0
  53. data/lib/ver/window.rb +369 -0
  54. data/test/test_rbcurse.rb +0 -0
  55. metadata +118 -0
@@ -0,0 +1,150 @@
1
+ module VER
2
+ module Keyboard # avoid initialize
3
+ ESC = 27 # keycode
4
+ @polling = false
5
+
6
+ module_function
7
+
8
+ def focus=(receiver)
9
+ @stack = []
10
+ @focus = receiver
11
+ poll unless @polling
12
+ end
13
+
14
+ def poll
15
+ @polling = true
16
+
17
+ while char = @focus.window.getch
18
+ break if @focus.stopping? # XXX
19
+ #break if VER.stopping?
20
+ $log.debug("char: #{char} stakc: #{@stack.inspect}") if char != Ncurses::ERR
21
+ if char == Ncurses::ERR # timeout or signal
22
+ @focus.press('esc') if @stack == [ESC]
23
+ @stack.clear
24
+ elsif ready = resolve(char)
25
+ $log.debug("char: #{char} ready: #{ready}")
26
+ @stack.clear
27
+ @focus.press(ready)
28
+ end
29
+ end
30
+
31
+ ensure
32
+ @polling = false
33
+ end
34
+
35
+ def resolve(char)
36
+ @stack << char
37
+
38
+ if @stack.first == ESC
39
+ MOD_KEYS[@stack] || SPECIAL_KEYS[@stack]
40
+ else
41
+ NCURSES_KEYS[char] || CONTROL_KEYS[char] || PRINTABLE_KEYS[char]
42
+ end
43
+ end
44
+
45
+ # TODO: make this section sane
46
+
47
+ ASCII = (0..255).map{|c| c.chr }
48
+ CONTROL = ASCII.grep(/[[:cntrl:]]/)
49
+ PRINTABLE = ASCII.grep(/[[:print:]]/)
50
+
51
+ SPECIAL_KEYS = {
52
+ [27, 79, 50, 81] => 'F14',
53
+ [27, 79, 50, 82] => 'F15',
54
+ [27, 79, 70] => 'end',
55
+ [27, 79, 70] => 'end',
56
+ [27, 79, 72] => 'home',
57
+ [27, 79, 80] => 'F1',
58
+ [27, 79, 81] => 'F2',
59
+ [27, 79, 82] => 'F3',
60
+ [27, 79, 83] => 'F4',
61
+ [27, 91, 49, 126] => 'end',
62
+ [27, 91, 49, 126] => 'home',
63
+ [27, 91, 49, 49, 126] => 'F1',
64
+ [27, 91, 49, 50, 126] => 'F2',
65
+ [27, 91, 49, 51, 126] => 'F3',
66
+ [27, 91, 49, 52, 126] => 'F4',
67
+ [27, 91, 49, 52, 126] => 'F4',
68
+ [27, 91, 49, 53, 126] => 'F5',
69
+ [27, 91, 49, 55, 126] => 'F6',
70
+ [27, 91, 49, 56, 59, 50, 126] => 'F19',
71
+ [27, 91, 49, 56, 59, 51, 126] => 'F7',
72
+ [27, 91, 49, 59, 51, 65] => 'ppage',
73
+ [27, 91, 49, 59, 51, 66] => 'npage',
74
+ [27, 91, 49, 59, 53, 65] => 'ppage',
75
+ [27, 91, 49, 59, 53, 66] => 'npage',
76
+ [27, 91, 49, 59, 53, 70] => 'M-<',
77
+ [27, 91, 49, 59, 53, 72] => 'M->',
78
+ [27, 91, 50, 54, 126] => 'F14',
79
+ [27, 91, 50, 56, 126] => 'F15',
80
+ [27, 91, 51, 59, 51, 126] => 'del',
81
+ [27, 91, 52, 126] => 'end',
82
+ [27, 91, 55, 126] => 'home',
83
+ [27, 91, 55, 126] => 'home',
84
+ [27, 91, 56, 126] => 'end',
85
+ [27, 91, 56, 126] => 'end',
86
+ [27, 91, 65] => 'up',
87
+ [27, 91, 66] => 'down',
88
+ [27, 91, 67] => 'right',
89
+ [27, 91, 68] => 'left',
90
+ [27, 91, 70] => 'end',
91
+ [27, 91, 72] => 'end',
92
+ [27, 91, 72] => 'home',
93
+ [27, 91, 91, 65] => 'F1',
94
+ [27, 91, 91, 66] => 'F2',
95
+ [27, 91, 91, 67] => 'F3',
96
+ [27, 91, 91, 68] => 'F4',
97
+ [27, 91, 91, 69] => 'F5',
98
+ }
99
+
100
+ CONTROL_KEYS = {
101
+ 0 => 'C-space',
102
+ 1 => 'C-a',
103
+ 2 => 'C-b',
104
+ 3 => 'C-c',
105
+ 4 => 'C-d',
106
+ 5 => 'C-e',
107
+ 6 => 'C-f',
108
+ 7 => 'C-g',
109
+ 8 => 'C-h',
110
+ 9 => 'tab',
111
+ 10 => 'return', # C-j
112
+ 11 => 'C-k',
113
+ 12 => 'C-l',
114
+ 13 => 'return', # C-m
115
+ 14 => 'C-n',
116
+ 15 => 'C-o',
117
+ 16 => 'C-p',
118
+ 17 => 'C-q',
119
+ 18 => 'C-r',
120
+ 19 => 'C-s',
121
+ 20 => 'C-t',
122
+ 21 => 'C-u',
123
+ 22 => 'C-v',
124
+ 23 => 'C-w',
125
+ 24 => 'C-x',
126
+ 25 => 'C-y',
127
+ 26 => 'C-z', # FIXME: is usually suspend in shell job control
128
+ # 27 => 'esc',
129
+ 32 => 'space',
130
+ 127 => 'backspace',
131
+ }
132
+
133
+ PRINTABLE_KEYS = {}
134
+ MOD_KEYS = {}
135
+
136
+ PRINTABLE.each do |key|
137
+ code = key.unpack('c')[0] # using unpack to be compatible with 1.9
138
+ PRINTABLE_KEYS[code] = key
139
+ MOD_KEYS[[ESC, code]] = "M-#{key}" unless key == '[' # don't map esc
140
+ end
141
+
142
+ NCURSES_KEYS = {}
143
+ Ncurses.constants.grep(/^KEY_/).each do |const|
144
+ value = Ncurses.const_get(const)
145
+ key = const[/^KEY_(.*)/, 1]
146
+ key = key =~ /^F/ ? key : key.downcase # function keys
147
+ NCURSES_KEYS[value] = key
148
+ end
149
+ end
150
+ 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
@@ -0,0 +1,102 @@
1
+ require 'rbcurse/colormap'
2
+ module VER
3
+ include ColorMap
4
+ module_function
5
+
6
+ # Setup ncurses, nicely documented by the curses manpages
7
+ def start_ncurses
8
+ # The initscr code determines the terminal type and initializes all curses
9
+ # data structures.
10
+ # initscr also causes the first call to refresh to clear the screen.
11
+ # If errors occur, initscr writes an appropriate error message to standard
12
+ # error and exits; otherwise, a pointer is returned to stdscr.
13
+ stdscr = Ncurses.initscr
14
+
15
+ # Color.start if Ncurses.has_colors?
16
+ Ncurses.start_color();
17
+ ColorMap.setup # added by RK 2008-11-30 00:48
18
+ # The keypad option enables the keypad of the user's terminal.
19
+ # If enabled (bf is TRUE), the user can press a function key (such as an
20
+ # arrow key) and wgetch returns a single value representing the function
21
+ # key, as in KEY_LEFT.
22
+ # If disabled (bf is FALSE), curses does not treat function keys specially
23
+ # and the program has to interpret the escape sequences itself.
24
+ # If the keypad in the terminal can be turned on (made to transmit) and off
25
+ # (made to work locally), turning on this option causes the terminal keypad
26
+ # to be turned on when wgetch is called.
27
+ # The default value for keypad is false.
28
+ Ncurses.keypad(stdscr, bf = true)
29
+
30
+ # The nl and nonl routines control whether the underlying display device
31
+ # translates the return key into newline on input, and whether it
32
+ # translates newline into return and line-feed on output (in either case,
33
+ # the call addch('\n') does the equivalent of return and line feed on the
34
+ # virtual screen).
35
+ # Initially, these translations do occur.
36
+ # If you disable them using nonl, curses will be able to make better use of
37
+ # the line-feed capability, resulting in faster cursor motion.
38
+ # Also, curses will then be able to detect the return key.
39
+ Ncurses.nonl
40
+
41
+ # The raw and noraw routines place the terminal into or out of raw mode.
42
+ # Raw mode is similar to cbreak mode, in that characters typed are
43
+ # immediately passed through to the user program.
44
+ # The differences are that in raw mode, the interrupt, quit, suspend, and
45
+ # flow control characters are all passed through uninterpreted, instead of
46
+ # generating a signal.
47
+ # The behavior of the BREAK key depends on other bits in the tty driver
48
+ # that are not set by curses.
49
+ Ncurses.raw
50
+
51
+ # Normally, the tty driver buffers typed characters until a newline or
52
+ # carriage return is typed.
53
+ # The cbreak routine disables line buffering and
54
+ # erase/kill character-processing (interrupt and flow control characters
55
+ # are unaffected), making characters typed by the user immediately
56
+ # available to the program.
57
+ Ncurses.cbreak
58
+
59
+ # The echo and noecho routines control whether characters typed by the user
60
+ # are echoed by getch as they are typed.
61
+ # Echoing by the tty driver is always disabled, but initially getch is in
62
+ # echo mode, so characters typed are echoed.
63
+ Ncurses.noecho
64
+
65
+ # The curs_set routine sets the cursor state is set to invisible, normal,
66
+ # or very visible for visibility equal to 0, 1, or 2 respectively.
67
+ # If the terminal supports the visibility requested, the previous cursor
68
+ # state is returned; otherwise, ERR is returned.
69
+ Ncurses.curs_set(1)
70
+
71
+ # The halfdelay routine is used for half-delay mode, which is similar to
72
+ # cbreak mode in that characters typed by the user are immediately
73
+ # available to the program.
74
+ # However, after blocking for tenths tenths of seconds, ERR is returned if
75
+ # nothing has been typed.
76
+ # The value of tenths must be a number between 1 and 255.
77
+ # Use nocbreak to leave half-delay mode.
78
+ Ncurses::halfdelay(tenths = 10)
79
+
80
+ # The nodelay option causes getch to be a non-blocking call. If no input is
81
+ # ready, getch returns ERR. If disabled (bf is FALSE), getch waits until a
82
+ # key is pressed.
83
+ # Ncurses::nodelay(Ncurses::stdscr, bf = true)
84
+ end
85
+
86
+ def stop_ncurses
87
+ Ncurses.echo
88
+ Ncurses.nocbreak
89
+ Ncurses.nl
90
+ Ncurses.endwin
91
+ ensure
92
+ return unless error = @last_error
93
+ log = Config[:logfile].value
94
+
95
+ Kernel.warn "There may have been fatal errors logged to: #{log}."
96
+ Kernel.warn "The most recent was:"
97
+
98
+ $stderr.puts ''
99
+ $stderr.puts @last_error_message if @last_error_message
100
+ $stderr.puts @last_error, *@last_error.backtrace
101
+ end
102
+ end