curses_menu 0.0.1 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/examples/hello.rb CHANGED
@@ -1,8 +1,8 @@
1
- require 'curses_menu'
2
-
3
- CursesMenu.new 'My awesome new menu!' do |menu|
4
- menu.item 'How\'s life?' do
5
- puts 'Couldn\'t be easier'
6
- :menu_exit
7
- end
8
- end
1
+ require 'curses_menu'
2
+
3
+ CursesMenu.new 'My awesome new menu!' do |menu|
4
+ menu.item 'How\'s life?' do
5
+ puts 'Couldn\'t be easier'
6
+ :menu_exit
7
+ end
8
+ end
data/examples/refresh.rb CHANGED
@@ -1,22 +1,22 @@
1
- require 'curses_menu'
2
-
3
- nbr = 0
4
- switch = false
5
- CursesMenu.new 'Menu being refreshed when selecting things' do |menu|
6
- menu.item "Current number is #{nbr} - Select me for +1" do
7
- nbr += 1
8
- :menu_refresh
9
- end
10
- menu.item "Current number is #{nbr} - Select me for -1" do
11
- nbr -= 1
12
- :menu_refresh
13
- end
14
- menu.item "[#{switch ? '*' : ' '}] Switch me!" do
15
- switch = !switch
16
- :menu_refresh
17
- end
18
- menu.item 'Quit' do
19
- puts 'Quitting...'
20
- :menu_exit
21
- end
22
- end
1
+ require 'curses_menu'
2
+
3
+ nbr = 0
4
+ switch = false
5
+ CursesMenu.new 'Menu being refreshed when selecting things' do |menu|
6
+ menu.item "Current number is #{nbr} - Select me for +1" do
7
+ nbr += 1
8
+ :menu_refresh
9
+ end
10
+ menu.item "Current number is #{nbr} - Select me for -1" do
11
+ nbr -= 1
12
+ :menu_refresh
13
+ end
14
+ menu.item "[#{switch ? '*' : ' '}] Switch me!" do
15
+ switch = !switch
16
+ :menu_refresh
17
+ end
18
+ menu.item 'Quit' do
19
+ puts 'Quitting...'
20
+ :menu_exit
21
+ end
22
+ end
@@ -1,9 +1,9 @@
1
- require 'curses_menu'
2
-
3
- CursesMenu.new 'Use all arrows, Page up/down, Home and End keys!' do |menu|
4
- menu.item('Quit') { :menu_exit }
5
- menu.item 'That\'s a big menu item! ' * 20
6
- 1000.times do |idx|
7
- menu.item "Menu item #{idx}"
8
- end
9
- end
1
+ require 'curses_menu'
2
+
3
+ CursesMenu.new 'Use all arrows, Page up/down, Home and End keys!' do |menu|
4
+ menu.item('Quit') { :menu_exit }
5
+ menu.item 'That\'s a big menu item! ' * 20
6
+ 1000.times do |idx|
7
+ menu.item "Menu item #{idx}"
8
+ end
9
+ end
@@ -1,18 +1,18 @@
1
- require 'curses_menu'
2
-
3
- CursesMenu.new 'We have several items, some of them have no action' do |menu|
4
- menu.item 'Nothing to do with me'
5
- menu.item 'Select me - I\'m option A!' do
6
- puts 'You have selected A. Press enter to continue.'
7
- $stdin.gets
8
- end
9
- menu.item 'Or select me - Option B!' do
10
- puts 'You have selected B. Press enter to continue.'
11
- $stdin.gets
12
- end
13
- menu.item '---- Separator'
14
- menu.item 'Quit' do
15
- puts 'Quitting...'
16
- :menu_exit
17
- end
18
- end
1
+ require 'curses_menu'
2
+
3
+ CursesMenu.new 'We have several items, some of them have no action' do |menu|
4
+ menu.item 'Nothing to do with me'
5
+ menu.item 'Select me - I\'m option A!' do
6
+ puts 'You have selected A. Press enter to continue.'
7
+ $stdin.gets
8
+ end
9
+ menu.item 'Or select me - Option B!' do
10
+ puts 'You have selected B. Press enter to continue.'
11
+ $stdin.gets
12
+ end
13
+ menu.item '---- Separator'
14
+ menu.item 'Quit' do
15
+ puts 'Quitting...'
16
+ :menu_exit
17
+ end
18
+ end
@@ -1,20 +1,20 @@
1
- require 'curses_menu'
2
-
3
- CursesMenu.new 'Top menu' do |menu|
4
- menu.item 'Enter menu 1' do
5
- CursesMenu.new 'Sub-menu 1' do |sub_menu|
6
- sub_menu.item 'We are in sub-menu 1'
7
- sub_menu.item('Back') { :menu_exit }
8
- end
9
- end
10
- menu.item 'Enter menu 2' do
11
- CursesMenu.new 'Sub-menu 2' do |sub_menu|
12
- sub_menu.item 'We are in sub-menu 2'
13
- sub_menu.item('Back') { :menu_exit }
14
- end
15
- end
16
- menu.item 'Quit' do
17
- puts 'Quitting...'
18
- :menu_exit
19
- end
20
- end
1
+ require 'curses_menu'
2
+
3
+ CursesMenu.new 'Top menu' do |menu|
4
+ menu.item 'Enter menu 1' do
5
+ CursesMenu.new 'Sub-menu 1' do |sub_menu|
6
+ sub_menu.item 'We are in sub-menu 1'
7
+ sub_menu.item('Back') { :menu_exit }
8
+ end
9
+ end
10
+ menu.item 'Enter menu 2' do
11
+ CursesMenu.new 'Sub-menu 2' do |sub_menu|
12
+ sub_menu.item 'We are in sub-menu 2'
13
+ sub_menu.item('Back') { :menu_exit }
14
+ end
15
+ end
16
+ menu.item 'Quit' do
17
+ puts 'Quitting...'
18
+ :menu_exit
19
+ end
20
+ end
data/examples/utf_8.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'curses_menu'
2
+
3
+ CursesMenu.new 'My awesome new menu! - 私の素晴らしい新しいメニュー' do |menu|
4
+ menu.item 'How\'s life? - 人生はどうですか?' do
5
+ puts 'Couldn\'t be easier - 簡単なことはありません'
6
+ :menu_exit
7
+ end
8
+ end
data/lib/curses_menu.rb CHANGED
@@ -1,241 +1,248 @@
1
- require 'curses'
2
- require 'curses_menu/curses_row'
3
-
4
- class CursesMenu
5
-
6
- # Define some color pairs names.
7
- # The integer value is meaningless in itself but they all have to be different.
8
- COLORS_TITLE = 1
9
- COLORS_LINE = 2
10
- COLORS_MENU_ITEM = 3
11
- COLORS_MENU_ITEM_SELECTED = 4
12
- COLORS_INPUT = 5
13
- COLORS_GREEN = 6
14
- COLORS_RED = 7
15
- COLORS_YELLOW = 8
16
- COLORS_BLUE = 9
17
-
18
- # curses keys that are not defined by Curses, but that are returned by getch
19
- KEY_ENTER = 10
20
- KEY_ESCAPE = 27
21
-
22
- # Constructor.
23
- # Display a list of choices, ask for user input and execute the choice made.
24
- # Repeat the operation unless one of the code returns the :menu_exit symbol.
25
- #
26
- # Parameters::
27
- # * *title* (String): Title of those choices
28
- # * *key_presses* (Array<Object>): List of key presses to automatically apply [default: []]
29
- # Can be characters or ascii values, as returned by curses' getch.
30
- # The list is modified in place along with its consumption, so that it can be reused in sub-menus if needed.
31
- # * *&menu_items_def* (Proc): Code to be called to get the list of choices. This code can call the following methods to design the menu:
32
- # * Parameters::
33
- # * *menu* (CursesMenu): The CursesMenu instance
34
- def initialize(title, key_presses: [], &menu_items_def)
35
- @current_menu_items = nil
36
- @curses_initialized = false
37
- current_items = gather_menu_items(&menu_items_def)
38
- selected_idx = 0
39
- raise "Menu #{title} has no items to select" if selected_idx.nil?
40
- window = curses_menu_initialize
41
- begin
42
- max_displayed_items = window.maxy - 5
43
- display_first_idx = 0
44
- display_first_char_idx = 0
45
- loop do
46
- # TODO: Don't redraw fixed items for performance
47
- # Display the title
48
- window.setpos(0, 0)
49
- print(window, '', default_color_pair: COLORS_TITLE, pad: '=')
50
- print(window, "= #{title}", default_color_pair: COLORS_TITLE, pad: ' ', single_line: true)
51
- print(window, '', default_color_pair: COLORS_TITLE, pad: '-')
52
- # Display the menu
53
- current_items[display_first_idx..display_first_idx + max_displayed_items - 1].each.with_index do |item_info, idx|
54
- selected = display_first_idx + idx == selected_idx
55
- print(
56
- window,
57
- item_info[:title],
58
- from: display_first_char_idx,
59
- default_color_pair: item_info.key?(:actions) ? COLORS_MENU_ITEM : COLORS_LINE,
60
- force_color_pair: selected ? COLORS_MENU_ITEM_SELECTED : nil,
61
- pad: selected ? ' ' : nil,
62
- single_line: true
63
- )
64
- end
65
- # Display the footer
66
- window.setpos(window.maxy - 2, 0)
67
- print(window, '', default_color_pair: COLORS_TITLE, pad: '=')
68
- display_actions = {
69
- 'Arrows/Home/End' => 'Navigate',
70
- 'Esc' => 'Exit'
71
- }
72
- if current_items[selected_idx][:actions]
73
- display_actions.merge!(Hash[current_items[selected_idx][:actions].map do |action_shortcut, action_info|
74
- [
75
- case action_shortcut
76
- when KEY_ENTER
77
- 'Enter'
78
- else
79
- action_shortcut
80
- end,
81
- action_info[:name]
82
- ]
83
- end])
84
- end
85
- print(
86
- window,
87
- "= #{display_actions.sort.map { |(shortcut, name)| "#{shortcut}: #{name}" }.join(' | ')}",
88
- from: display_first_char_idx,
89
- default_color_pair: COLORS_TITLE,
90
- pad: ' ',
91
- add_nl: false,
92
- single_line: true
93
- )
94
- window.refresh
95
- user_choice = nil
96
- loop do
97
- user_choice = key_presses.empty? ? window.getch : key_presses.shift
98
- break unless user_choice.nil?
99
- sleep 0.01
100
- end
101
- case user_choice
102
- when Curses::KEY_RIGHT
103
- display_first_char_idx += 1
104
- when Curses::KEY_LEFT
105
- display_first_char_idx -= 1
106
- when Curses::KEY_UP
107
- selected_idx -= 1
108
- when Curses::KEY_PPAGE
109
- selected_idx -= max_displayed_items - 1
110
- when Curses::KEY_DOWN
111
- selected_idx += 1
112
- when Curses::KEY_NPAGE
113
- selected_idx += max_displayed_items - 1
114
- when Curses::KEY_HOME
115
- selected_idx = 0
116
- when Curses::KEY_END
117
- selected_idx = current_items.size - 1
118
- when KEY_ESCAPE
119
- break
120
- else
121
- # Check actions
122
- if current_items[selected_idx][:actions]&.key?(user_choice)
123
- curses_menu_finalize
124
- result = current_items[selected_idx][:actions][user_choice][:execute].call
125
- if result.is_a?(Symbol)
126
- case result
127
- when :menu_exit
128
- break
129
- when :menu_refresh
130
- current_items = gather_menu_items(&menu_items_def)
131
- end
132
- end
133
- window = curses_menu_initialize
134
- window.clear
135
- end
136
- end
137
- # Stay in bounds
138
- display_first_char_idx = 0 if display_first_char_idx < 0
139
- selected_idx = current_items.size - 1 if selected_idx >= current_items.size
140
- selected_idx = 0 if selected_idx < 0
141
- if selected_idx < display_first_idx
142
- display_first_idx = selected_idx
143
- elsif selected_idx >= display_first_idx + max_displayed_items
144
- display_first_idx = selected_idx - max_displayed_items + 1
145
- end
146
- end
147
- ensure
148
- curses_menu_finalize
149
- end
150
- end
151
-
152
- # Register a new menu item.
153
- # This method is meant to be called from a choose_from call.
154
- #
155
- # Parameters::
156
- # * *title* (String or CursesRow): Text to be displayed for this item
157
- # * *actions* (Hash<Object, Hash<Symbol,Object> >): Associated actions to this item, per shortcut [default: {}]
158
- # * *name* (String): Name of this action (displayed at the bottom of the menu)
159
- # * *execute* (Proc): Code called when this action is selected
160
- # * *&action* (Proc): Code called if the item is selected (action for the enter key) [optional].
161
- # * Result::
162
- # * Symbol or Object: If the code returns a symbol, the menu will behave in a specific way:
163
- # * *menu_exit*: the menu selection exits.
164
- # * *menu_refresh*: The menu will compute again its items.
165
- def item(title, actions: {}, &action)
166
- menu_item_def = { title: title }
167
- all_actions = action.nil? ? actions : actions.merge(KEY_ENTER => { name: 'Select', execute: action })
168
- menu_item_def[:actions] = all_actions unless all_actions.empty?
169
- @current_menu_items << menu_item_def
170
- end
171
-
172
- private
173
-
174
- # Display a given curses string information.
175
- #
176
- # Parameters::
177
- # * *window* (Window): The curses window in which we display.
178
- # * *string* (String or CursesRow): The curses row, or as a single String.
179
- # * See CursesRow#print_on for all the other parameters description
180
- def print(window, string, from: 0, to: nil, default_color_pair: COLORS_LINE, force_color_pair: nil, pad: nil, add_nl: true, single_line: false)
181
- string = CursesRow.new(default: { text: string }) if string.is_a?(String)
182
- string.print_on(
183
- window,
184
- from: from,
185
- to: to,
186
- default_color_pair: default_color_pair,
187
- force_color_pair: force_color_pair,
188
- pad: pad,
189
- add_nl: add_nl,
190
- single_line: single_line
191
- )
192
- end
193
-
194
- # Initialize and get the curses menu window
195
- #
196
- # Result::
197
- # * Window: The curses menu window
198
- def curses_menu_initialize
199
- Curses.init_screen
200
- # Use non-blocking key read, otherwise using Popen3 later blocks
201
- Curses.timeout = 0
202
- Curses.start_color
203
- Curses.init_pair(COLORS_TITLE, Curses::COLOR_BLACK, Curses::COLOR_CYAN)
204
- Curses.init_pair(COLORS_LINE, Curses::COLOR_WHITE, Curses::COLOR_BLACK)
205
- Curses.init_pair(COLORS_MENU_ITEM, Curses::COLOR_WHITE, Curses::COLOR_BLACK)
206
- Curses.init_pair(COLORS_MENU_ITEM_SELECTED, Curses::COLOR_BLACK, Curses::COLOR_WHITE)
207
- Curses.init_pair(COLORS_INPUT, Curses::COLOR_WHITE, Curses::COLOR_BLUE)
208
- Curses.init_pair(COLORS_GREEN, Curses::COLOR_GREEN, Curses::COLOR_BLACK)
209
- Curses.init_pair(COLORS_RED, Curses::COLOR_RED, Curses::COLOR_BLACK)
210
- Curses.init_pair(COLORS_YELLOW, Curses::COLOR_YELLOW, Curses::COLOR_BLACK)
211
- Curses.init_pair(COLORS_BLUE, Curses::COLOR_BLUE, Curses::COLOR_BLACK)
212
- window = Curses.stdscr
213
- window.keypad = true
214
- @curses_initialized = true
215
- window
216
- end
217
-
218
- # Finalize the curses menu window
219
- def curses_menu_finalize
220
- Curses.close_screen if @curses_initialized
221
- @curses_initialized = false
222
- end
223
-
224
- # Get menu items.
225
- #
226
- # Parameters::
227
- # * Proc: Code defining the menu items
228
- # * *menu* (CursesMenu): The menu for which we gather items.
229
- # Result::
230
- # * Array< Hash<Symbol,Object> >: List of items to be displayed
231
- # * *title* (String): Item title to display
232
- # * *actions* (Hash<Object, Hash<Symbol,Object> >): Associated actions to this item, per shortcut [optional]
233
- # * *name* (String): Name of this action (displayed at the bottom of the menu)
234
- # * *execute* (Proc): Code called when this action is selected
235
- def gather_menu_items
236
- @current_menu_items = []
237
- yield self
238
- @current_menu_items
239
- end
240
-
241
- end
1
+ require 'curses'
2
+ require 'curses_menu/curses_row'
3
+
4
+ # Provide a menu using curses with keys navigation and selection
5
+ class CursesMenu
6
+
7
+ # Define some color pairs names.
8
+ # The integer value is meaningless in itself but they all have to be different.
9
+ COLORS_TITLE = 1
10
+ COLORS_LINE = 2
11
+ COLORS_MENU_ITEM = 3
12
+ COLORS_MENU_ITEM_SELECTED = 4
13
+ COLORS_INPUT = 5
14
+ COLORS_GREEN = 6
15
+ COLORS_RED = 7
16
+ COLORS_YELLOW = 8
17
+ COLORS_BLUE = 9
18
+ COLORS_WHITE = 10
19
+
20
+ # curses keys that are not defined by Curses, but that are returned by getch
21
+ KEY_ENTER = 10
22
+ KEY_ESCAPE = 27
23
+
24
+ # Constructor.
25
+ # Display a list of choices, ask for user input and execute the choice made.
26
+ # Repeat the operation unless one of the code returns the :menu_exit symbol.
27
+ #
28
+ # Parameters::
29
+ # * *title* (String): Title of those choices
30
+ # * *key_presses* (Array<Object>): List of key presses to automatically apply [default: []]
31
+ # Can be characters or ascii values, as returned by curses' getch.
32
+ # The list is modified in place along with its consumption, so that it can be reused in sub-menus if needed.
33
+ # * *&menu_items_def* (Proc): Code to be called to get the list of choices. This code can call the following methods to design the menu:
34
+ # * Parameters::
35
+ # * *menu* (CursesMenu): The CursesMenu instance
36
+ def initialize(title, key_presses: [], &menu_items_def)
37
+ @current_menu_items = nil
38
+ @curses_initialized = false
39
+ current_items = gather_menu_items(&menu_items_def)
40
+ selected_idx = 0
41
+ raise "Menu #{title} has no items to select" if selected_idx.nil?
42
+
43
+ window = curses_menu_initialize
44
+ begin
45
+ max_displayed_items = window.maxy - 5
46
+ display_first_idx = 0
47
+ display_first_char_idx = 0
48
+ loop do
49
+ # TODO: Don't redraw fixed items for performance
50
+ # Display the title
51
+ window.setpos(0, 0)
52
+ print(window, '', default_color_pair: COLORS_TITLE, pad: '=')
53
+ print(window, "= #{title}", default_color_pair: COLORS_TITLE, pad: ' ', single_line: true)
54
+ print(window, '', default_color_pair: COLORS_TITLE, pad: '-')
55
+ # Display the menu
56
+ current_items[display_first_idx..display_first_idx + max_displayed_items - 1].each.with_index do |item_info, idx|
57
+ selected = display_first_idx + idx == selected_idx
58
+ print(
59
+ window,
60
+ item_info[:title],
61
+ from: display_first_char_idx,
62
+ default_color_pair: item_info.key?(:actions) ? COLORS_MENU_ITEM : COLORS_LINE,
63
+ force_color_pair: selected ? COLORS_MENU_ITEM_SELECTED : nil,
64
+ pad: selected ? ' ' : nil,
65
+ single_line: true
66
+ )
67
+ end
68
+ # Display the footer
69
+ window.setpos(window.maxy - 2, 0)
70
+ print(window, '', default_color_pair: COLORS_TITLE, pad: '=')
71
+ display_actions = {
72
+ 'Arrows/Home/End' => 'Navigate',
73
+ 'Esc' => 'Exit'
74
+ }
75
+ if current_items[selected_idx][:actions]
76
+ display_actions.merge!(
77
+ current_items[selected_idx][:actions].map do |action_shortcut, action_info|
78
+ [
79
+ case action_shortcut
80
+ when KEY_ENTER
81
+ 'Enter'
82
+ else
83
+ action_shortcut
84
+ end,
85
+ action_info[:name]
86
+ ]
87
+ end.to_h
88
+ )
89
+ end
90
+ print(
91
+ window,
92
+ "= #{display_actions.sort.map { |(shortcut, name)| "#{shortcut}: #{name}" }.join(' | ')}",
93
+ from: display_first_char_idx,
94
+ default_color_pair: COLORS_TITLE,
95
+ pad: ' ',
96
+ add_nl: false,
97
+ single_line: true
98
+ )
99
+ window.refresh
100
+ user_choice = nil
101
+ loop do
102
+ user_choice = key_presses.empty? ? window.getch : key_presses.shift
103
+ break unless user_choice.nil?
104
+
105
+ sleep 0.01
106
+ end
107
+ case user_choice
108
+ when Curses::KEY_RIGHT
109
+ display_first_char_idx += 1
110
+ when Curses::KEY_LEFT
111
+ display_first_char_idx -= 1
112
+ when Curses::KEY_UP
113
+ selected_idx -= 1
114
+ when Curses::KEY_PPAGE
115
+ selected_idx -= max_displayed_items - 1
116
+ when Curses::KEY_DOWN
117
+ selected_idx += 1
118
+ when Curses::KEY_NPAGE
119
+ selected_idx += max_displayed_items - 1
120
+ when Curses::KEY_HOME
121
+ selected_idx = 0
122
+ when Curses::KEY_END
123
+ selected_idx = current_items.size - 1
124
+ when KEY_ESCAPE
125
+ break
126
+ else
127
+ # Check actions
128
+ if current_items[selected_idx][:actions]&.key?(user_choice)
129
+ curses_menu_finalize
130
+ result = current_items[selected_idx][:actions][user_choice][:execute].call
131
+ if result.is_a?(Symbol)
132
+ case result
133
+ when :menu_exit
134
+ break
135
+ when :menu_refresh
136
+ current_items = gather_menu_items(&menu_items_def)
137
+ end
138
+ end
139
+ window = curses_menu_initialize
140
+ window.clear
141
+ end
142
+ end
143
+ # Stay in bounds
144
+ display_first_char_idx = 0 if display_first_char_idx.negative?
145
+ selected_idx = current_items.size - 1 if selected_idx >= current_items.size
146
+ selected_idx = 0 if selected_idx.negative?
147
+ if selected_idx < display_first_idx
148
+ display_first_idx = selected_idx
149
+ elsif selected_idx >= display_first_idx + max_displayed_items
150
+ display_first_idx = selected_idx - max_displayed_items + 1
151
+ end
152
+ end
153
+ ensure
154
+ curses_menu_finalize
155
+ end
156
+ end
157
+
158
+ # Register a new menu item.
159
+ # This method is meant to be called from a choose_from call.
160
+ #
161
+ # Parameters::
162
+ # * *title* (String or CursesRow): Text to be displayed for this item
163
+ # * *actions* (Hash<Object, Hash<Symbol,Object> >): Associated actions to this item, per shortcut [default: {}]
164
+ # * *name* (String): Name of this action (displayed at the bottom of the menu)
165
+ # * *execute* (Proc): Code called when this action is selected
166
+ # * *&action* (Proc): Code called if the item is selected (action for the enter key) [optional].
167
+ # * Result::
168
+ # * Symbol or Object: If the code returns a symbol, the menu will behave in a specific way:
169
+ # * *menu_exit*: the menu selection exits.
170
+ # * *menu_refresh*: The menu will compute again its items.
171
+ def item(title, actions: {}, &action)
172
+ menu_item_def = { title: title }
173
+ all_actions = action.nil? ? actions : actions.merge(KEY_ENTER => { name: 'Select', execute: action })
174
+ menu_item_def[:actions] = all_actions unless all_actions.empty?
175
+ @current_menu_items << menu_item_def
176
+ end
177
+
178
+ private
179
+
180
+ # Display a given curses string information.
181
+ #
182
+ # Parameters::
183
+ # * *window* (Window): The curses window in which we display.
184
+ # * *string* (String or CursesRow): The curses row, or as a single String.
185
+ # * See CursesRow#print_on for all the other parameters description
186
+ def print(window, string, from: 0, to: nil, default_color_pair: COLORS_LINE, force_color_pair: nil, pad: nil, add_nl: true, single_line: false)
187
+ string = CursesRow.new({ default: { text: string } }) if string.is_a?(String)
188
+ string.print_on(
189
+ window,
190
+ from: from,
191
+ to: to,
192
+ default_color_pair: default_color_pair,
193
+ force_color_pair: force_color_pair,
194
+ pad: pad,
195
+ add_nl: add_nl,
196
+ single_line: single_line
197
+ )
198
+ end
199
+
200
+ # Initialize and get the curses menu window
201
+ #
202
+ # Result::
203
+ # * Window: The curses menu window
204
+ def curses_menu_initialize
205
+ Curses.init_screen
206
+ # Use non-blocking key read, otherwise using Popen3 later blocks
207
+ Curses.timeout = 0
208
+ Curses.start_color
209
+ Curses.init_pair(COLORS_TITLE, Curses::COLOR_BLACK, Curses::COLOR_CYAN)
210
+ Curses.init_pair(COLORS_LINE, Curses::COLOR_WHITE, Curses::COLOR_BLACK)
211
+ Curses.init_pair(COLORS_MENU_ITEM, Curses::COLOR_WHITE, Curses::COLOR_BLACK)
212
+ Curses.init_pair(COLORS_MENU_ITEM_SELECTED, Curses::COLOR_BLACK, Curses::COLOR_WHITE)
213
+ Curses.init_pair(COLORS_INPUT, Curses::COLOR_WHITE, Curses::COLOR_BLUE)
214
+ Curses.init_pair(COLORS_GREEN, Curses::COLOR_GREEN, Curses::COLOR_BLACK)
215
+ Curses.init_pair(COLORS_RED, Curses::COLOR_RED, Curses::COLOR_BLACK)
216
+ Curses.init_pair(COLORS_YELLOW, Curses::COLOR_YELLOW, Curses::COLOR_BLACK)
217
+ Curses.init_pair(COLORS_BLUE, Curses::COLOR_BLUE, Curses::COLOR_BLACK)
218
+ Curses.init_pair(COLORS_WHITE, Curses::COLOR_WHITE, Curses::COLOR_BLACK)
219
+ window = Curses.stdscr
220
+ window.keypad = true
221
+ @curses_initialized = true
222
+ window
223
+ end
224
+
225
+ # Finalize the curses menu window
226
+ def curses_menu_finalize
227
+ Curses.close_screen if @curses_initialized
228
+ @curses_initialized = false
229
+ end
230
+
231
+ # Get menu items.
232
+ #
233
+ # Parameters::
234
+ # * Proc: Code defining the menu items
235
+ # * *menu* (CursesMenu): The menu for which we gather items.
236
+ # Result::
237
+ # * Array< Hash<Symbol,Object> >: List of items to be displayed
238
+ # * *title* (String): Item title to display
239
+ # * *actions* (Hash<Object, Hash<Symbol,Object> >): Associated actions to this item, per shortcut [optional]
240
+ # * *name* (String): Name of this action (displayed at the bottom of the menu)
241
+ # * *execute* (Proc): Code called when this action is selected
242
+ def gather_menu_items
243
+ @current_menu_items = []
244
+ yield self
245
+ @current_menu_items
246
+ end
247
+
248
+ end