curses_menu 0.0.6 → 0.2.0

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: 74becd64c41df7dc7628e8c2b2c416c56f430c53d9be7e3e68698bb6bc1633aa
4
- data.tar.gz: 02bf486f61ae412243d536912202a36eb03d72d6c3c0e4ff034808221193d3f5
3
+ metadata.gz: '093b7bafe2adec885ebb1cd49607556b54a1925f416597d1ab220519ec6009f8'
4
+ data.tar.gz: f0a6110f5e1ae34026c3d6982a5f2e8c8f402849bd0a7805ed43f90a8b398cad
5
5
  SHA512:
6
- metadata.gz: d7014fece6ecf47e9f0dba36ee8b835841b8176809a09f52bf16e87892719075da8847427a62b2558068bb15abd6cb12cab0f49b4456693c417740c0d306f77d
7
- data.tar.gz: c407a1d42c57f39fa7c32488191097186c574fca00bd043e664b7cce45f0fba946d227712f9754025b0c9c72fac342cd721e3429cd2d4427b3d2bc4bfdc6dac6
6
+ metadata.gz: 6b8d1c93130d98de349183ffd888f21de3ea0023e0cd7372817dc7efa0606974c442b0c1bd1d10f946395deb62cac089a332a0fc7f35c13a662c6452147b736e
7
+ data.tar.gz: 15f764995f0baa99dca4da1e73a67c2079c4956f237f3975c3086f6f9678c212f10e6c40e8ae0d3d90ab4375463114c917708fd44ed1a058fe71239a61390254
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ # [v0.2.0](https://github.com/Muriel-Salvan/curses_menu/compare/v0.1.0...v0.2.0) (2022-11-01 21:07:07)
2
+
3
+ ### Features
4
+
5
+ * [[feature] [#6] Add lazy evaluation for actions](https://github.com/Muriel-Salvan/curses_menu/commit/0a5a96ae84fecdf982f763b833e8e863231dde73)
6
+
7
+ # [v0.1.0](https://github.com/Muriel-Salvan/curses_menu/compare/v0.0.6...v0.1.0) (2022-10-12 15:58:25)
8
+
9
+ ### Features
10
+
11
+ * [[#5] [feature] Add possibility to render menu item titles in a lazy way](https://github.com/Muriel-Salvan/curses_menu/commit/6997c846f800d37441ea40bce109345e725ff12c)
12
+
1
13
  # [v0.0.6](https://github.com/Muriel-Salvan/curses_menu/compare/v0.0.5...v0.0.6) (2022-10-12 15:48:18)
2
14
 
3
15
  ### Patches
@@ -0,0 +1,25 @@
1
+ require 'curses_menu'
2
+
3
+ nbr_visible_items = Curses.stdscr.maxy - 5
4
+ CursesMenu.new 'Menu items using lazy rendering' do |menu|
5
+ (nbr_visible_items * 2).times do
6
+ menu.item "[Rendered at #{Time.now}] - I am a normal item"
7
+ menu.item(proc do
8
+ "[Rendered at #{Time.now}] - I am a lazy item"
9
+ end)
10
+ menu.item(
11
+ "[Rendered at #{Time.now}] - I am a normal item with lazy rendered action",
12
+ actions: proc do
13
+ {
14
+ 'a' => {
15
+ name: "Action rendered at #{Time.now}",
16
+ execute: proc {}
17
+ }
18
+ }
19
+ end
20
+ )
21
+ end
22
+ menu.item 'Refresh menu' do
23
+ :menu_refresh
24
+ end
25
+ end
@@ -1,5 +1,5 @@
1
1
  class CursesMenu
2
2
 
3
- VERSION = '0.0.6'
3
+ VERSION = '0.2.0'
4
4
 
5
5
  end
data/lib/curses_menu.rb CHANGED
@@ -55,9 +55,11 @@ class CursesMenu
55
55
  # Display the menu
56
56
  current_items[display_first_idx..display_first_idx + max_displayed_items - 1].each.with_index do |item_info, idx|
57
57
  selected = display_first_idx + idx == selected_idx
58
+ # Keep a cache of titles as they can be loaded in a lazy way for performance
59
+ item_info[:title_cached] = item_info[:title].is_a?(Proc) ? item_info[:title].call : item_info[:title] unless item_info.key?(:title_cached)
58
60
  print(
59
61
  window,
60
- item_info[:title],
62
+ item_info[:title_cached],
61
63
  from: display_first_char_idx,
62
64
  default_color_pair: item_info.key?(:actions) ? COLORS_MENU_ITEM : COLORS_LINE,
63
65
  force_color_pair: selected ? COLORS_MENU_ITEM_SELECTED : nil,
@@ -72,9 +74,11 @@ class CursesMenu
72
74
  'Arrows/Home/End' => 'Navigate',
73
75
  'Esc' => 'Exit'
74
76
  }
75
- if current_items[selected_idx][:actions]
77
+ # Keep a cache of actions as they can be loaded in a lazy way for performance
78
+ current_items[selected_idx][:actions_cached] = current_items[selected_idx][:actions].is_a?(Proc) ? current_items[selected_idx][:actions].call : current_items[selected_idx][:actions] unless current_items[selected_idx].key?(:actions_cached)
79
+ if current_items[selected_idx][:actions_cached]
76
80
  display_actions.merge!(
77
- current_items[selected_idx][:actions].to_h do |action_shortcut, action_info|
81
+ current_items[selected_idx][:actions_cached].to_h do |action_shortcut, action_info|
78
82
  [
79
83
  case action_shortcut
80
84
  when KEY_ENTER
@@ -125,9 +129,11 @@ class CursesMenu
125
129
  break
126
130
  else
127
131
  # Check actions
128
- if current_items[selected_idx][:actions]&.key?(user_choice)
132
+ # Keep a cache of actions as they can be loaded in a lazy way for performance
133
+ current_items[selected_idx][:actions_cached] = current_items[selected_idx][:actions].is_a?(Proc) ? current_items[selected_idx][:actions].call : current_items[selected_idx][:actions] unless current_items[selected_idx].key?(:actions_cached)
134
+ if current_items[selected_idx][:actions_cached]&.key?(user_choice)
129
135
  curses_menu_finalize
130
- result = current_items[selected_idx][:actions][user_choice][:execute].call
136
+ result = current_items[selected_idx][:actions_cached][user_choice][:execute].call
131
137
  if result.is_a?(Symbol)
132
138
  case result
133
139
  when :menu_exit
@@ -159,10 +165,11 @@ class CursesMenu
159
165
  # This method is meant to be called from a choose_from call.
160
166
  #
161
167
  # 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: {}]
168
+ # * *title* (String, CursesRow or Proc): Text to be displayed for this item, or Proc returning this text when needed (lazy loading)
169
+ # * *actions* (Hash<Object, Hash<Symbol,Object> > or Proc): Associated actions to this item, per shortcut, or Proc returning those actions when needed (lazy loading) [default: {}]
164
170
  # * *name* (String): Name of this action (displayed at the bottom of the menu)
165
171
  # * *execute* (Proc): Code called when this action is selected
172
+ # In case of lazy loading (with a Proc), the title Proc will always be called first.
166
173
  # * *&action* (Proc): Code called if the item is selected (action for the enter key) [optional].
167
174
  # * Result::
168
175
  # * Symbol or Object: If the code returns a symbol, the menu will behave in a specific way:
@@ -170,8 +177,21 @@ class CursesMenu
170
177
  # * *menu_refresh*: The menu will compute again its items.
171
178
  def item(title, actions: {}, &action)
172
179
  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?
180
+ all_actions =
181
+ if action.nil?
182
+ actions
183
+ else
184
+ mapped_default_action = { KEY_ENTER => { name: 'Select', execute: action } }
185
+ if actions.is_a?(Proc)
186
+ # Make sure we keep the lazyness
187
+ proc do
188
+ actions.call.merge(mapped_default_action)
189
+ end
190
+ else
191
+ actions.merge(mapped_default_action)
192
+ end
193
+ end
194
+ menu_item_def[:actions] = all_actions if all_actions.is_a?(Proc) || !all_actions.empty?
175
195
  @current_menu_items << menu_item_def
176
196
  end
177
197
 
@@ -0,0 +1,383 @@
1
+ describe CursesMenu do
2
+
3
+ it 'displays a menu with 1 item with lazy rendering' do
4
+ render_called = false
5
+ test_menu do |menu|
6
+ menu.item(proc do
7
+ render_called = true
8
+ 'Menu item lazy'
9
+ end)
10
+ end
11
+ expect(render_called).to be true
12
+ assert_line 3, 'Menu item lazy'
13
+ end
14
+
15
+ it 'displays a menu with 1 item in a CursesRow with lazy rendering' do
16
+ render_called = false
17
+ test_menu do |menu|
18
+ menu.item(proc do
19
+ render_called = true
20
+ CursesMenu::CursesRow.new({ cell: { text: 'Menu item lazy' } })
21
+ end)
22
+ end
23
+ expect(render_called).to be true
24
+ assert_line 3, 'Menu item lazy'
25
+ end
26
+
27
+ it 'displays menu actions with lazy evaluation' do
28
+ render_called = false
29
+ action_executed = false
30
+ test_menu(keys: ['a']) do |menu|
31
+ menu.item('Menu item lazy', actions: proc do
32
+ render_called = true
33
+ {
34
+ 'a' => {
35
+ name: 'Lazy action',
36
+ execute: proc do
37
+ action_executed = true
38
+ end
39
+ }
40
+ }
41
+ end)
42
+ end
43
+ assert_line 3, 'Menu item lazy'
44
+ assert_line(-1, '= Arrows/Home/End: Navigate | Esc: Exit | a: Lazy action')
45
+ expect(render_called).to be true
46
+ expect(action_executed).to be true
47
+ end
48
+
49
+ it 'displays menu actions with lazy evaluation and a default action' do
50
+ render_called = false
51
+ action_executed = false
52
+ default_executed = false
53
+ test_menu(keys: ['a', CursesMenu::KEY_ENTER]) do |menu|
54
+ menu.item(
55
+ 'Menu item lazy',
56
+ actions: proc do
57
+ render_called = true
58
+ {
59
+ 'a' => {
60
+ name: 'Lazy action',
61
+ execute: proc do
62
+ action_executed = true
63
+ end
64
+ }
65
+ }
66
+ end
67
+ ) do
68
+ default_executed = true
69
+ end
70
+ end
71
+ assert_line 3, 'Menu item lazy'
72
+ assert_line(-1, '= Arrows/Home/End: Navigate | Enter: Select | Esc: Exit | a: Lazy action')
73
+ expect(render_called).to be true
74
+ expect(action_executed).to be true
75
+ expect(default_executed).to be true
76
+ end
77
+
78
+ it 'doesn\'t lazy render when the item is not displayed' do
79
+ nbr_visible_items = Curses.stdscr.maxy - 5
80
+ render_called = false
81
+ test_menu do |menu|
82
+ (nbr_visible_items * 2).times do |idx|
83
+ menu.item "Menu item #{idx}"
84
+ end
85
+ menu.item(proc do
86
+ render_called = true
87
+ 'Menu item lazy'
88
+ end)
89
+ end
90
+ expect(render_called).to be false
91
+ end
92
+
93
+ it 'doesn\'t lazy evaluate actions when the item is not displayed' do
94
+ nbr_visible_items = Curses.stdscr.maxy - 5
95
+ render_called = false
96
+ test_menu do |menu|
97
+ (nbr_visible_items * 2).times do |idx|
98
+ menu.item "Menu item #{idx}"
99
+ end
100
+ menu.item('Menu item lazy', actions: proc do
101
+ render_called = true
102
+ {
103
+ 'a' => {
104
+ name: 'Lazy action',
105
+ execute: proc {}
106
+ }
107
+ }
108
+ end)
109
+ end
110
+ expect(render_called).to be false
111
+ end
112
+
113
+ it 'doesn\'t lazy evaluate actions when the item is not selected' do
114
+ render_called = false
115
+ test_menu do |menu|
116
+ menu.item 'Menu item'
117
+ menu.item('Menu item lazy', actions: proc do
118
+ render_called = true
119
+ {
120
+ 'a' => {
121
+ name: 'Lazy action',
122
+ execute: proc {}
123
+ }
124
+ }
125
+ end)
126
+ end
127
+ expect(render_called).to be false
128
+ end
129
+
130
+ it 'lazy evaluates actions as soon as the item is selected' do
131
+ render_called = false
132
+ test_menu(keys: [Curses::KEY_DOWN]) do |menu|
133
+ menu.item 'Menu item'
134
+ menu.item('Menu item lazy', actions: proc do
135
+ render_called = true
136
+ {
137
+ 'a' => {
138
+ name: 'Lazy action',
139
+ execute: proc {}
140
+ }
141
+ }
142
+ end)
143
+ end
144
+ expect(render_called).to be true
145
+ end
146
+
147
+ it 'keeps lazy rendered titles in a cache while navigating' do
148
+ nbr_renders = 0
149
+ test_menu(keys: [Curses::KEY_DOWN, Curses::KEY_DOWN, Curses::KEY_DOWN]) do |menu|
150
+ menu.item 'Menu item 1'
151
+ menu.item(proc do
152
+ nbr_renders += 1
153
+ 'Menu item 2 Lazy'
154
+ end)
155
+ menu.item 'Menu item 3'
156
+ menu.item 'Menu item 4', actions: { 'a' => { name: 'Special action', execute: proc {} } }
157
+ end
158
+ expect(nbr_renders).to eq 1
159
+ assert_line(-1, '= Arrows/Home/End: Navigate | Esc: Exit | a: Special action')
160
+ end
161
+
162
+ it 'keeps lazy evaluated actions in a cache while navigating' do
163
+ nbr_renders = 0
164
+ test_menu(keys: [Curses::KEY_DOWN, Curses::KEY_DOWN, Curses::KEY_DOWN]) do |menu|
165
+ menu.item 'Menu item 1'
166
+ menu.item('Menu item 2 lazy', actions: proc do
167
+ nbr_renders += 1
168
+ {
169
+ 'a' => {
170
+ name: 'Lazy action',
171
+ execute: proc {}
172
+ }
173
+ }
174
+ end)
175
+ menu.item 'Menu item 3'
176
+ menu.item 'Menu item 4', actions: { 'a' => { name: 'Special action', execute: proc {} } }
177
+ end
178
+ expect(nbr_renders).to eq 1
179
+ assert_line(-1, '= Arrows/Home/End: Navigate | Esc: Exit | a: Special action')
180
+ end
181
+
182
+ it 'keeps lazy rendered titles in a cache while navigating across pages' do
183
+ nbr_renders = 0
184
+ nbr_visible_items = Curses.stdscr.maxy - 5
185
+ test_menu(keys: [Curses::KEY_DOWN, Curses::KEY_DOWN, Curses::KEY_END, Curses::KEY_HOME, Curses::KEY_END, Curses::KEY_HOME, Curses::KEY_END]) do |menu|
186
+ (nbr_visible_items * 2).times do |idx|
187
+ menu.item "Menu item #{idx}"
188
+ end
189
+ menu.item(proc do
190
+ nbr_renders += 1
191
+ 'Menu item Lazy'
192
+ end)
193
+ end
194
+ expect(nbr_renders).to eq 1
195
+ assert_line(-3, 'Menu item Lazy')
196
+ end
197
+
198
+ it 'keeps lazy evaluated actions in a cache while navigating across pages' do
199
+ nbr_renders = 0
200
+ nbr_visible_items = Curses.stdscr.maxy - 5
201
+ test_menu(keys: [Curses::KEY_DOWN, Curses::KEY_DOWN, Curses::KEY_END, Curses::KEY_HOME, Curses::KEY_END, Curses::KEY_HOME, Curses::KEY_END]) do |menu|
202
+ (nbr_visible_items * 2).times do |idx|
203
+ menu.item "Menu item #{idx}"
204
+ end
205
+ menu.item('Menu item lazy', actions: proc do
206
+ nbr_renders += 1
207
+ {
208
+ 'a' => {
209
+ name: 'Lazy action',
210
+ execute: proc {}
211
+ }
212
+ }
213
+ end)
214
+ end
215
+ expect(nbr_renders).to eq 1
216
+ assert_line(-1, '= Arrows/Home/End: Navigate | Esc: Exit | a: Lazy action')
217
+ end
218
+
219
+ it 'refreshes lazy rendered titles between menu refreshes' do
220
+ nbr_renders = 0
221
+ test_menu(keys: [Curses::KEY_DOWN, Curses::KEY_UP, CursesMenu::KEY_ENTER, Curses::KEY_DOWN, Curses::KEY_UP]) do |menu|
222
+ menu.item 'Menu item Refresh' do
223
+ :menu_refresh
224
+ end
225
+ menu.item(proc do
226
+ nbr_renders += 1
227
+ 'Menu item Lazy'
228
+ end)
229
+ end
230
+ expect(nbr_renders).to eq 2
231
+ end
232
+
233
+ it 'refreshes lazy evaluated actions between menu refreshes' do
234
+ nbr_renders = 0
235
+ test_menu(keys: [Curses::KEY_DOWN, Curses::KEY_UP, CursesMenu::KEY_ENTER, Curses::KEY_DOWN, Curses::KEY_UP]) do |menu|
236
+ menu.item 'Menu item Refresh' do
237
+ :menu_refresh
238
+ end
239
+ menu.item('Menu item lazy', actions: proc do
240
+ nbr_renders += 1
241
+ {
242
+ 'a' => {
243
+ name: 'Lazy action',
244
+ execute: proc {}
245
+ }
246
+ }
247
+ end)
248
+ end
249
+ expect(nbr_renders).to eq 2
250
+ end
251
+
252
+ it 'does not refresh lazy rendered titles when executing actions' do
253
+ nbr_renders = 0
254
+ test_menu(keys: [Curses::KEY_DOWN, Curses::KEY_UP, CursesMenu::KEY_ENTER, Curses::KEY_DOWN, Curses::KEY_UP]) do |menu|
255
+ menu.item 'Menu item' do
256
+ # Do nothing
257
+ end
258
+ menu.item(proc do
259
+ nbr_renders += 1
260
+ 'Menu item Lazy'
261
+ end)
262
+ end
263
+ expect(nbr_renders).to eq 1
264
+ end
265
+
266
+ it 'does not refresh lazy evaluated actions when executing actions' do
267
+ nbr_renders = 0
268
+ test_menu(keys: [Curses::KEY_DOWN, Curses::KEY_UP, CursesMenu::KEY_ENTER, Curses::KEY_DOWN, Curses::KEY_UP]) do |menu|
269
+ menu.item 'Menu item' do
270
+ # Do nothing
271
+ end
272
+ menu.item('Menu item lazy', actions: proc do
273
+ nbr_renders += 1
274
+ {
275
+ 'a' => {
276
+ name: 'Lazy action',
277
+ execute: proc {}
278
+ }
279
+ }
280
+ end)
281
+ end
282
+ expect(nbr_renders).to eq 1
283
+ end
284
+
285
+ it 'does not refresh lazy rendered titles when getting into sub-menus' do
286
+ nbr_renders = 0
287
+ test_menu(
288
+ keys: [
289
+ # Enter sub-menu
290
+ CursesMenu::KEY_ENTER,
291
+ Curses::KEY_DOWN,
292
+ # Back to first menu
293
+ CursesMenu::KEY_ESCAPE,
294
+ Curses::KEY_DOWN
295
+ ]
296
+ ) do |menu, key_presses|
297
+ menu.item 'Sub-menu' do
298
+ described_class.new('Sub-menu title', key_presses: key_presses) do |sub_menu|
299
+ sub_menu.item 'Sub-menu item 1'
300
+ sub_menu.item 'Sub-menu item 2'
301
+ end
302
+ end
303
+ menu.item(proc do
304
+ nbr_renders += 1
305
+ 'Menu item Lazy'
306
+ end)
307
+ end
308
+ expect(nbr_renders).to eq 1
309
+ end
310
+
311
+ it 'does not refresh lazy evaluated actions when getting into sub-menus' do
312
+ nbr_renders = 0
313
+ test_menu(
314
+ keys: [
315
+ # Enter sub-menu
316
+ CursesMenu::KEY_ENTER,
317
+ Curses::KEY_DOWN,
318
+ # Back to first menu
319
+ CursesMenu::KEY_ESCAPE,
320
+ Curses::KEY_DOWN
321
+ ]
322
+ ) do |menu, key_presses|
323
+ menu.item 'Sub-menu' do
324
+ described_class.new('Sub-menu title', key_presses: key_presses) do |sub_menu|
325
+ sub_menu.item 'Sub-menu item 1'
326
+ sub_menu.item 'Sub-menu item 2'
327
+ end
328
+ end
329
+ menu.item('Menu item lazy', actions: proc do
330
+ nbr_renders += 1
331
+ {
332
+ 'a' => {
333
+ name: 'Lazy action',
334
+ execute: proc {}
335
+ }
336
+ }
337
+ end)
338
+ end
339
+ expect(nbr_renders).to eq 1
340
+ end
341
+
342
+ it 'always lazy renders titles before lazy evaluating actions' do
343
+ lazy_renders = []
344
+ nbr_visible_items = Curses.stdscr.maxy - 5
345
+ test_menu(keys: [Curses::KEY_END, Curses::KEY_HOME, Curses::KEY_DOWN]) do |menu|
346
+ menu.item(
347
+ proc do
348
+ lazy_renders << :item_1_title
349
+ 'Menu item 1 lazy'
350
+ end,
351
+ actions: proc do
352
+ lazy_renders << :item_1_action
353
+ { 'a' => { name: 'Lazy action 1', execute: proc {} } }
354
+ end
355
+ )
356
+ menu.item(
357
+ proc do
358
+ lazy_renders << :item_2_title
359
+ 'Menu item 2 lazy'
360
+ end,
361
+ actions: proc do
362
+ lazy_renders << :item_2_action
363
+ { 'a' => { name: 'Lazy action 2', execute: proc {} } }
364
+ end
365
+ )
366
+ (nbr_visible_items * 2).times do |idx|
367
+ menu.item "Menu item #{idx}"
368
+ end
369
+ menu.item(
370
+ proc do
371
+ lazy_renders << :item_3_title
372
+ 'Menu item 3 lazy'
373
+ end,
374
+ actions: proc do
375
+ lazy_renders << :item_3_action
376
+ { 'a' => { name: 'Lazy action 3', execute: proc {} } }
377
+ end
378
+ )
379
+ end
380
+ expect(lazy_renders).to eq %i[item_1_title item_2_title item_1_action item_3_title item_3_action item_2_action]
381
+ end
382
+
383
+ end
@@ -9,6 +9,16 @@ describe CursesMenu do
9
9
  assert_line(-1, '= Arrows/Home/End: Navigate | Esc: Exit')
10
10
  end
11
11
 
12
+ it 'displays a menu with 1 item having a default action' do
13
+ test_menu(title: 'Menu title') do |menu|
14
+ menu.item 'Menu item' do
15
+ # Do nothing
16
+ end
17
+ end
18
+ assert_line 3, 'Menu item'
19
+ assert_line(-1, '= Arrows/Home/End: Navigate | Enter: Select | Esc: Exit')
20
+ end
21
+
12
22
  it 'displays a menu with several items' do
13
23
  test_menu do |menu|
14
24
  menu.item 'Menu item 1'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: curses_menu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Muriel Salvan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-12 00:00:00.000000000 Z
11
+ date: 2022-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curses
@@ -93,6 +93,7 @@ extra_rdoc_files:
93
93
  - examples/automatic_key_presses.rb
94
94
  - examples/formatting.rb
95
95
  - examples/hello.rb
96
+ - examples/lazy_menu_items.rb
96
97
  - examples/refresh.rb
97
98
  - examples/scrolling.rb
98
99
  - examples/several_items.rb
@@ -106,6 +107,7 @@ files:
106
107
  - examples/automatic_key_presses.rb
107
108
  - examples/formatting.rb
108
109
  - examples/hello.rb
110
+ - examples/lazy_menu_items.rb
109
111
  - examples/refresh.rb
110
112
  - examples/scrolling.rb
111
113
  - examples/several_items.rb
@@ -117,6 +119,7 @@ files:
117
119
  - spec/curses_menu_test.rb
118
120
  - spec/curses_menu_test/actions_spec.rb
119
121
  - spec/curses_menu_test/formatting_spec.rb
122
+ - spec/curses_menu_test/lazy_spec.rb
120
123
  - spec/curses_menu_test/rubocop_spec.rb
121
124
  - spec/curses_menu_test/scrolling_spec.rb
122
125
  - spec/curses_menu_test/simple_navigation_spec.rb