curses_menu 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/examples/lazy_menu_items.rb +13 -2
- data/lib/curses_menu/version.rb +1 -1
- data/lib/curses_menu.rb +25 -7
- data/spec/curses_menu_test/lazy_spec.rb +259 -3
- data/spec/curses_menu_test/simple_navigation_spec.rb +10 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '093b7bafe2adec885ebb1cd49607556b54a1925f416597d1ab220519ec6009f8'
|
4
|
+
data.tar.gz: f0a6110f5e1ae34026c3d6982a5f2e8c8f402849bd0a7805ed43f90a8b398cad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b8d1c93130d98de349183ffd888f21de3ea0023e0cd7372817dc7efa0606974c442b0c1bd1d10f946395deb62cac089a332a0fc7f35c13a662c6452147b736e
|
7
|
+
data.tar.gz: 15f764995f0baa99dca4da1e73a67c2079c4956f237f3975c3086f6f9678c212f10e6c40e8ae0d3d90ab4375463114c917708fd44ed1a058fe71239a61390254
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
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
|
+
|
1
7
|
# [v0.1.0](https://github.com/Muriel-Salvan/curses_menu/compare/v0.0.6...v0.1.0) (2022-10-12 15:58:25)
|
2
8
|
|
3
9
|
### Features
|
data/examples/lazy_menu_items.rb
CHANGED
@@ -3,10 +3,21 @@ require 'curses_menu'
|
|
3
3
|
nbr_visible_items = Curses.stdscr.maxy - 5
|
4
4
|
CursesMenu.new 'Menu items using lazy rendering' do |menu|
|
5
5
|
(nbr_visible_items * 2).times do
|
6
|
-
menu.item "I am a normal item
|
6
|
+
menu.item "[Rendered at #{Time.now}] - I am a normal item"
|
7
7
|
menu.item(proc do
|
8
|
-
"I am a lazy item
|
8
|
+
"[Rendered at #{Time.now}] - I am a lazy item"
|
9
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
|
+
)
|
10
21
|
end
|
11
22
|
menu.item 'Refresh menu' do
|
12
23
|
:menu_refresh
|
data/lib/curses_menu/version.rb
CHANGED
data/lib/curses_menu.rb
CHANGED
@@ -74,9 +74,11 @@ class CursesMenu
|
|
74
74
|
'Arrows/Home/End' => 'Navigate',
|
75
75
|
'Esc' => 'Exit'
|
76
76
|
}
|
77
|
-
|
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]
|
78
80
|
display_actions.merge!(
|
79
|
-
current_items[selected_idx][:
|
81
|
+
current_items[selected_idx][:actions_cached].to_h do |action_shortcut, action_info|
|
80
82
|
[
|
81
83
|
case action_shortcut
|
82
84
|
when KEY_ENTER
|
@@ -127,9 +129,11 @@ class CursesMenu
|
|
127
129
|
break
|
128
130
|
else
|
129
131
|
# Check actions
|
130
|
-
|
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)
|
131
135
|
curses_menu_finalize
|
132
|
-
result = current_items[selected_idx][:
|
136
|
+
result = current_items[selected_idx][:actions_cached][user_choice][:execute].call
|
133
137
|
if result.is_a?(Symbol)
|
134
138
|
case result
|
135
139
|
when :menu_exit
|
@@ -162,9 +166,10 @@ class CursesMenu
|
|
162
166
|
#
|
163
167
|
# Parameters::
|
164
168
|
# * *title* (String, CursesRow or Proc): Text to be displayed for this item, or Proc returning this text when needed (lazy loading)
|
165
|
-
# * *actions* (Hash<Object, Hash<Symbol,Object> >): Associated actions to this item, per shortcut [default: {}]
|
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: {}]
|
166
170
|
# * *name* (String): Name of this action (displayed at the bottom of the menu)
|
167
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.
|
168
173
|
# * *&action* (Proc): Code called if the item is selected (action for the enter key) [optional].
|
169
174
|
# * Result::
|
170
175
|
# * Symbol or Object: If the code returns a symbol, the menu will behave in a specific way:
|
@@ -172,8 +177,21 @@ class CursesMenu
|
|
172
177
|
# * *menu_refresh*: The menu will compute again its items.
|
173
178
|
def item(title, actions: {}, &action)
|
174
179
|
menu_item_def = { title: title }
|
175
|
-
all_actions =
|
176
|
-
|
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?
|
177
195
|
@current_menu_items << menu_item_def
|
178
196
|
end
|
179
197
|
|
@@ -2,7 +2,7 @@ describe CursesMenu do
|
|
2
2
|
|
3
3
|
it 'displays a menu with 1 item with lazy rendering' do
|
4
4
|
render_called = false
|
5
|
-
test_menu
|
5
|
+
test_menu do |menu|
|
6
6
|
menu.item(proc do
|
7
7
|
render_called = true
|
8
8
|
'Menu item lazy'
|
@@ -14,7 +14,7 @@ describe CursesMenu do
|
|
14
14
|
|
15
15
|
it 'displays a menu with 1 item in a CursesRow with lazy rendering' do
|
16
16
|
render_called = false
|
17
|
-
test_menu
|
17
|
+
test_menu do |menu|
|
18
18
|
menu.item(proc do
|
19
19
|
render_called = true
|
20
20
|
CursesMenu::CursesRow.new({ cell: { text: 'Menu item lazy' } })
|
@@ -24,10 +24,61 @@ describe CursesMenu do
|
|
24
24
|
assert_line 3, 'Menu item lazy'
|
25
25
|
end
|
26
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
|
+
|
27
78
|
it 'doesn\'t lazy render when the item is not displayed' do
|
28
79
|
nbr_visible_items = Curses.stdscr.maxy - 5
|
29
80
|
render_called = false
|
30
|
-
test_menu
|
81
|
+
test_menu do |menu|
|
31
82
|
(nbr_visible_items * 2).times do |idx|
|
32
83
|
menu.item "Menu item #{idx}"
|
33
84
|
end
|
@@ -39,6 +90,60 @@ describe CursesMenu do
|
|
39
90
|
expect(render_called).to be false
|
40
91
|
end
|
41
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
|
+
|
42
147
|
it 'keeps lazy rendered titles in a cache while navigating' do
|
43
148
|
nbr_renders = 0
|
44
149
|
test_menu(keys: [Curses::KEY_DOWN, Curses::KEY_DOWN, Curses::KEY_DOWN]) do |menu|
|
@@ -54,6 +159,26 @@ describe CursesMenu do
|
|
54
159
|
assert_line(-1, '= Arrows/Home/End: Navigate | Esc: Exit | a: Special action')
|
55
160
|
end
|
56
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
|
+
|
57
182
|
it 'keeps lazy rendered titles in a cache while navigating across pages' do
|
58
183
|
nbr_renders = 0
|
59
184
|
nbr_visible_items = Curses.stdscr.maxy - 5
|
@@ -70,6 +195,27 @@ describe CursesMenu do
|
|
70
195
|
assert_line(-3, 'Menu item Lazy')
|
71
196
|
end
|
72
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
|
+
|
73
219
|
it 'refreshes lazy rendered titles between menu refreshes' do
|
74
220
|
nbr_renders = 0
|
75
221
|
test_menu(keys: [Curses::KEY_DOWN, Curses::KEY_UP, CursesMenu::KEY_ENTER, Curses::KEY_DOWN, Curses::KEY_UP]) do |menu|
|
@@ -84,6 +230,25 @@ describe CursesMenu do
|
|
84
230
|
expect(nbr_renders).to eq 2
|
85
231
|
end
|
86
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
|
+
|
87
252
|
it 'does not refresh lazy rendered titles when executing actions' do
|
88
253
|
nbr_renders = 0
|
89
254
|
test_menu(keys: [Curses::KEY_DOWN, Curses::KEY_UP, CursesMenu::KEY_ENTER, Curses::KEY_DOWN, Curses::KEY_UP]) do |menu|
|
@@ -98,6 +263,25 @@ describe CursesMenu do
|
|
98
263
|
expect(nbr_renders).to eq 1
|
99
264
|
end
|
100
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
|
+
|
101
285
|
it 'does not refresh lazy rendered titles when getting into sub-menus' do
|
102
286
|
nbr_renders = 0
|
103
287
|
test_menu(
|
@@ -124,4 +308,76 @@ describe CursesMenu do
|
|
124
308
|
expect(nbr_renders).to eq 1
|
125
309
|
end
|
126
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
|
+
|
127
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.
|
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-
|
11
|
+
date: 2022-11-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: curses
|