eft 0.4.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 801797fc4df36523e6baaad909c55c6cb0221d60
4
+ data.tar.gz: f3496e92b58c74b9d1cfa9b3624e06c0f79b34b5
5
+ SHA512:
6
+ metadata.gz: 208b327f0aa6d1ead392ca2682113dfea63807361abdc942f5e64417f9da5bf89763652926c8aaf2165524254aaa3c8b1d1dc1094f43321c5ab53bba3808a508
7
+ data.tar.gz: 8ea0d807d62731ffaca846db012209d848cd05f4f97a94131e3c47fcc184cb694bd9bff84603938d00c6e44c276704daa862cddc0bd6bd5eddf3d540c2d18784
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup markdown
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ []: {{{1
2
+
3
+ File : README.md
4
+ Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ Date : 2014-02-20
6
+
7
+ Copyright : Copyright (C) 2014 Felix C. Stegerman
8
+ Version : v0.4.0
9
+
10
+ []: }}}1
11
+
12
+ [![Gem Version](https://badge.fury.io/rb/eft.png)](http://badge.fury.io/rb/eft)
13
+
14
+ ## Description
15
+ []: {{{1
16
+
17
+ eft - ruby + whiptail
18
+
19
+ Eft is a ruby dsl that wraps `whiptail` [1] to display dialog boxes;
20
+ see `example.rb` for examples.
21
+
22
+ ```ruby
23
+ Eft.ask('What is your name?') do |q|
24
+ q.on_ok { |name| puts "Hello, #{name}!" }
25
+ end
26
+ ```
27
+
28
+ []: }}}1
29
+
30
+ ## Specs & Docs
31
+
32
+ ```bash
33
+ $ rake spec # TODO
34
+ $ rake docs
35
+ ```
36
+
37
+ ## TODO
38
+
39
+ * specs! (how to automate tests of whiptail? - I don't know!)
40
+ * --noitem?
41
+ * choose between whiptail and dialog?
42
+ * extend w/ dialog's other dialogs?
43
+ * remove dependency on obfusk-util?
44
+
45
+ ## License
46
+
47
+ LGPLv3+ [2].
48
+
49
+ ## References
50
+
51
+ [1] Newt (and whiptail)
52
+ --- http://en.wikipedia.org/wiki/Newt_(programming_library)
53
+
54
+ [2] GNU Lesser General Public License, version 3
55
+ --- http://www.gnu.org/licenses/lgpl-3.0.html
56
+
57
+ []: ! ( vim: set tw=70 sw=2 sts=2 et fdm=marker : )
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ desc 'Run specs'
2
+ task :spec do
3
+ puts 'No automated tests yet - please manually test the example'
4
+ # sh 'rspec -c'
5
+ end
6
+
7
+ desc 'Run specs verbosely'
8
+ task 'spec:verbose' do
9
+ puts 'No automated tests yet - please manually test the example'
10
+ # sh 'rspec -cfd'
11
+ end
12
+
13
+ desc 'Run specs verbosely, view w/ less'
14
+ task 'spec:less' do
15
+ puts 'No automated tests yet - please manually test the example'
16
+ # sh 'rspec -cfd --tty | less -R'
17
+ end
18
+
19
+ desc 'Check for warnings'
20
+ task :warn do
21
+ sh 'ruby -w -I lib -I ../rb-obfusk-util/lib -r eft -e ""'
22
+ end
23
+
24
+ desc 'Run example'
25
+ task :example do
26
+ sh 'ruby -w -I lib -I ../rb-obfusk-util/lib example.rb'
27
+ end
28
+
29
+ desc 'Generate docs'
30
+ task :docs do
31
+ sh 'yardoc | cat'
32
+ end
33
+
34
+ desc 'List undocumented objects'
35
+ task 'docs:undoc' do
36
+ sh 'yard stats --list-undoc'
37
+ end
38
+
39
+ desc 'Cleanup'
40
+ task :clean do
41
+ sh 'rm -rf .yardoc/ doc/ *.gem'
42
+ end
43
+
44
+ desc 'Build SNAPSHOT gem'
45
+ task :snapshot do
46
+ v = Time.new.strftime '%Y%m%d%H%M%S'
47
+ f = 'lib/eft/version.rb'
48
+ sh "sed -ri~ 's!(SNAPSHOT)!\\1.#{v}!' #{f}"
49
+ sh 'gem build eft.gemspec'
50
+ end
51
+
52
+ desc 'Undo SNAPSHOT gem'
53
+ task 'snapshot:undo' do
54
+ sh 'git checkout -- lib/eft/version.rb'
55
+ end
data/eft.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ require File.expand_path('../lib/eft/version', __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'eft'
5
+ s.homepage = 'https://github.com/obfusk/eft'
6
+ s.summary = 'ruby + whiptail'
7
+
8
+ s.description = <<-END.gsub(/^ {4}/, '')
9
+ ruby + whiptail
10
+
11
+ Eft is a ruby dsl that wraps whiptail to display dialog boxes.
12
+ END
13
+
14
+ s.version = Eft::VERSION
15
+ s.date = Eft::DATE
16
+
17
+ s.authors = [ 'Felix C. Stegerman' ]
18
+ s.email = %w{ flx@obfusk.net }
19
+
20
+ s.licenses = %w{ LGPLv3+ }
21
+
22
+ s.files = %w{ .yardopts README.md Rakefile } \
23
+ + %w{ eft.gemspec example.rb } \
24
+ + Dir['lib/**/*.rb']
25
+
26
+ s.add_runtime_dependency 'obfusk-util'
27
+
28
+ s.add_development_dependency 'rake'
29
+ # s.add_development_dependency 'rspec'
30
+
31
+ s.required_ruby_version = '>= 1.9.1'
32
+ end
data/example.rb ADDED
@@ -0,0 +1,64 @@
1
+ require 'eft'
2
+
3
+ Eft.menu('Choices:', selected: 'bar', title: 'Menu',
4
+ backtitle: 'Choose!') do |m|
5
+ m.on('foo', 'Do The Foo') do |x|
6
+ Eft.ask('What is your name?', ok_button: 'Next',
7
+ default: 'Anonymous') do |q1|
8
+ q1.on_ok do |name|
9
+ Eft.ask_pass('Secret?', ok_button: 'Go!') do |q2|
10
+ q2.on_ok do |sec|
11
+ Eft.show_msg "Welcome #{name}, your secret is #{sec}"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ m.on('bar', 'Do Bar!') do |x|
18
+ Eft.ask_yesno 'Is everything going well?' do |q|
19
+ q.on_yes { puts 'Nice!' }
20
+ q.on_no { puts 'Too bad!' }
21
+ end
22
+ end
23
+ m.on('baz', 'Baz!?') do |x|
24
+ Eft.gauge '...', 0, title: 'Progress' do |mv|
25
+ 0.upto(100) do |i|
26
+ i % 5 == 0 ? mv[i, "We're at ##{i} ..."] : mv[i]
27
+ sleep 0.05
28
+ end
29
+ end
30
+ end
31
+ m.on('qux', 'Quixotic?') do |x|
32
+ Eft.show_info 'Hi!'
33
+ end
34
+ m.on('quux', 'Quixotic!') do |x|
35
+ Eft.show_text file: '/etc/services', scroll: true
36
+ end
37
+ m.on('quuux', 'There\'s more ...') do |x|
38
+ Eft.check 'Which ones?' do |c|
39
+ c.choice('1', 'One')
40
+ c.choice('2', 'Two', true)
41
+ c.choice('3', 'Three')
42
+ c.on_ok do |choices|
43
+ Eft.show_text text: choices*10*"\n", title: 'Multiplied!'
44
+ end
45
+ end
46
+ end
47
+ m.on('almost there', 'Just one more') do |x|
48
+ Eft.radio 'One or none' do |c|
49
+ c.choice('1', 'One')
50
+ c.choice('2', 'Two')
51
+ c.on_ok { |choice| puts "You chose: #{choice || 'none!?'}" }
52
+ end
53
+ end
54
+ m.on('last one', 'Really! I promise.') do |x|
55
+ Eft.radio 'Which one?', selected: '2' do |c|
56
+ c.choice('1', 'One')
57
+ c.choice('2', 'Two')
58
+ c.choice('3', 'Three')
59
+ c.on_ok { |choice| puts "You chose: #{choice}" }
60
+ end
61
+ end
62
+ m.on_cancel { puts 'Not interested.' }
63
+ m.on_esc { puts 'Escaped!' }
64
+ end
@@ -0,0 +1,4 @@
1
+ module Eft
2
+ VERSION = '0.4.0'
3
+ DATE = '2014-02-20'
4
+ end
data/lib/eft.rb ADDED
@@ -0,0 +1,322 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : eft.rb
4
+ # Maintainer : Felix C. Stegerman <flx@obfusk.net>
5
+ # Date : 2014-02-20
6
+ #
7
+ # Copyright : Copyright (C) 2014 Felix C. Stegerman
8
+ # Licence : LGPLv3+
9
+ #
10
+ # -- ; }}}1
11
+
12
+ require 'tempfile'
13
+
14
+ require 'obfusk/util/run'
15
+ require 'obfusk/util/term'
16
+
17
+ module Eft
18
+
19
+ OU = Obfusk::Util
20
+
21
+ # --
22
+
23
+ # NB: dialog works as well as whiptail, but these options will be
24
+ # incompatible: --*-button (is: --*-label), --scrolltext
25
+
26
+ WHIPTAIL = 'whiptail'
27
+ EXIT = { ok_yes: 0, cancel_no: 1, esc: 255 }
28
+ CHECK_OPTS = ['--separate-output']
29
+
30
+ OPT = ->(o,x) { o.select { |k,v| OPTS[x][k] }
31
+ .map { |k,v| OPTS[x][k][v] } }
32
+ ON_OFF = ->(x) { x ? 'on' : 'off' }
33
+
34
+ # --
35
+
36
+ # translate method to option
37
+ WHAT = { # {{{1
38
+ show_info: '--infobox' , show_msg: '--msgbox' ,
39
+ show_text: '--textbox' , ask: '--inputbox' ,
40
+ ask_pass: '--passwordbox' , ask_yesno: '--yesno' ,
41
+ menu: '--menu' , check: '--checklist' ,
42
+ radio: '--radiolist' , gauge: '--gauge' ,
43
+ } # }}}1
44
+
45
+ # options per category
46
+ OPTS = { # {{{1
47
+ all: {
48
+ title: ->(t) { ['--title', t] },
49
+ backtitle: ->(t) { ['--backtitle', t] },
50
+ scroll: ->(b) { b ? ['--scrolltext'] : [] }, # ????
51
+ },
52
+ ok: {
53
+ ok_button: ->(t) { ['--ok-button', t] },
54
+ },
55
+ cancel: {
56
+ cancel_button: ->(t) { ['--cancel-button', t] },
57
+ no_cancel: ->(b) { b ? ['--nocancel'] : [] },
58
+ },
59
+ yes: {
60
+ yes_button: ->(t) { ['--yes-button', t] },
61
+ },
62
+ no: {
63
+ no_button: ->(t) { ['--no-button', t] },
64
+ default_no: ->(b) { b ? ['--default-no'] : [] },
65
+ },
66
+ menu: {
67
+ selected: ->(i) { ['--default-item', i] },
68
+ },
69
+ } # }}}1
70
+
71
+ # --
72
+
73
+ class Error < RuntimeError; end
74
+
75
+ # configuration class
76
+ class Cfg # {{{1
77
+ # set from hash, pass to block, freeze
78
+ def initialize(cfg = {}, &b)
79
+ @cfg = cfg; b[self] if b; @cfg.freeze
80
+ end
81
+
82
+ # call if set
83
+ def call(k, *a)
84
+ @cfg[k][*a] if @cfg[k]
85
+ end
86
+
87
+ # nothing by default
88
+ def _opts; [] end
89
+ end # }}}1
90
+
91
+ #
92
+
93
+ module CfgEsc ; def on_esc(&b) @cfg[:on_esc] = b end; end
94
+ module CfgOK ; def on_ok(&b) @cfg[:on_ok] = b end; end
95
+ module CfgCancel; def on_cancel(&b) @cfg[:on_cancel] = b end; end
96
+ module CfgYes ; def on_yes(&b) @cfg[:on_yes] = b end; end
97
+ module CfgNo ; def on_no(&b) @cfg[:on_no] = b end; end
98
+
99
+ #
100
+
101
+ class CfgShowInfo < Cfg ; end
102
+ class CfgShowMsg < Cfg; include CfgEsc, CfgOK ; end
103
+ class CfgShowText < Cfg; include CfgEsc, CfgOK ; end
104
+ class CfgAsk < Cfg; include CfgEsc, CfgOK, CfgCancel ; end
105
+ class CfgAskPass < Cfg; include CfgEsc, CfgOK, CfgCancel ; end
106
+ class CfgAskYesNo < Cfg; include CfgEsc, CfgYes, CfgNo ; end
107
+ class CfgGauge < Cfg ; end
108
+
109
+ #
110
+
111
+ # menu config
112
+ class CfgMenu < Cfg # {{{1
113
+ include CfgEsc, CfgOK, CfgCancel
114
+
115
+ def initialize(*a, &b)
116
+ @menu = []; super; @menu.freeze
117
+ end
118
+
119
+ # add menu item
120
+ def on(tag, item, &b)
121
+ @menu << { tag: tag, item: item, block: b }
122
+ end
123
+
124
+ def _menu; @menu end
125
+ end # }}}1
126
+
127
+ # checkboxes config
128
+ class CfgCheck < Cfg # {{{1
129
+ include CfgEsc, CfgOK, CfgCancel
130
+
131
+ def initialize(*a, &b)
132
+ @check = []; super; @check.freeze
133
+ end
134
+
135
+ # add a choice
136
+ def choice(tag, item, selected = false)
137
+ @check << { tag: tag, item: item, selected: selected }
138
+ end
139
+
140
+ def _check; @check end
141
+ def _opts; CHECK_OPTS; end
142
+ end # }}}1
143
+
144
+ # radiolist config
145
+ class CfgRadio < Cfg # {{{1
146
+ include CfgEsc, CfgOK, CfgCancel
147
+
148
+ def initialize(*a, &b)
149
+ @radio = []; super; @radio.freeze
150
+ end
151
+
152
+ # add a choice
153
+ def choice(tag, item)
154
+ @radio << { tag: tag, item: item }
155
+ end
156
+
157
+ def _radio; @radio end
158
+ end # }}}1
159
+
160
+ # --
161
+
162
+ # show message w/o buttons, don't clear screen
163
+ def self.show_info(text, opts = {})
164
+ _whip :show_info, text, CfgShowInfo.new, opts
165
+ end
166
+
167
+ # show message w/ OK button
168
+ def self.show_msg(text, opts = {}, &b)
169
+ c = CfgShowMsg.new(&b)
170
+ _whip(:show_msg, text, c, opts) { c.call :on_ok }
171
+ end
172
+
173
+ # show file contents or text w/ OK button
174
+ def self.show_text(opts = {}, &b)
175
+ _file_or_temp opts do |f|
176
+ c = CfgShowText.new(&b)
177
+ _whip(:show_text, f, c, opts) { c.call :on_ok }
178
+ end
179
+ end
180
+
181
+ # --
182
+
183
+ # ask for input w/ OK/Cancel buttons (and default)
184
+ def self.ask(text, opts = {}, &b)
185
+ c = CfgAsk.new(&b); a = opts[:default] ? [opts[:default]] : []
186
+ _whip(:ask, text, c, opts, a) do |lines|
187
+ c.call :on_ok, lines.first
188
+ end
189
+ end
190
+
191
+ # ask for password w/ OK/Cancel buttons
192
+ def self.ask_pass(text, opts = {}, &b)
193
+ c = CfgAskPass.new(&b)
194
+ _whip(:ask_pass, text, c, opts) do |lines|
195
+ c.call :on_ok, lines.first
196
+ end
197
+ end
198
+
199
+ # ask w/ Yes/No buttons
200
+ def self.ask_yesno(text, opts = {}, &b)
201
+ c = CfgAskYesNo.new(&b)
202
+ _whip(:ask_yesno, text, c, opts) { c.call :on_yes }
203
+ end
204
+
205
+ # --
206
+
207
+ # choose from menu w/ OK/Cancel buttons
208
+ def self.menu(text, opts = {}, &b) # {{{1
209
+ c = CfgMenu.new(&b); m = c._menu
210
+ o = opts.merge(subheight: opts[:menu_height]).freeze
211
+ a = m.map { |x| [x[:tag],x[:item]] } .flatten
212
+ t = Hash[m.map { |x| [x[:tag],x] }]
213
+ _whip(:menu, text, c, o, a) do |lines|
214
+ tag = lines.first; t[tag][:block][tag]
215
+ end
216
+ end # }}}1
217
+
218
+ # --
219
+
220
+ # choose checkboxes w/ OK/Cancel buttons
221
+ def self.check(text, opts = {}, &b) # {{{1
222
+ c = CfgCheck.new(&b); i = c._check
223
+ o = opts.merge(subheight: opts[:list_height]).freeze
224
+ a = i.map { |x| [x[:tag],x[:item],ON_OFF[x[:selected]]] } .flatten
225
+ _whip(:check, text, c, o, a) do |lines|
226
+ c.call :on_ok, lines
227
+ end
228
+ end # }}}1
229
+
230
+ # choose radiobutton w/ OK/Cancel buttons
231
+ def self.radio(text, opts = {}, &b) # {{{1
232
+ s = opts[:selected] ; f = ->(x) { ON_OFF[x == s] }
233
+ c = CfgRadio.new(&b); i = c._radio
234
+ o = opts.merge(subheight: opts[:list_height]).freeze
235
+ a = i.map { |x| [x[:tag],x[:item],f[x[:tag]]] } .flatten
236
+ _whip(:radio, text, c, o, a) do |lines|
237
+ c.call :on_ok, lines.first
238
+ end # }}}1
239
+ end
240
+
241
+ # --
242
+
243
+ # show gauge; use lambda passed to block to move it forward by
244
+ # passing it `percent[, message]`
245
+ def self.gauge(text, percent, opts = {}, &b) # {{{1
246
+ IO.pipe do |r, w|
247
+ mv = ->(pct, msg = nil) {
248
+ msg ? w.puts('XXX', pct, msg, 'XXX', pct) : w.puts(pct) # WTF!
249
+ }
250
+ c = CfgGauge.new
251
+ o = _whip_opts :gauge, c, opts
252
+ c = _whip_cmd text, opts, o, [percent]
253
+ pid = OU.spawn(*c, in: r)
254
+ r.close; b[mv]; w.close; Process.wait pid
255
+ raise Error, 'exitstatus != 0' if $?.exitstatus != 0
256
+ end # }}}1
257
+ end
258
+
259
+ # --
260
+
261
+ # process options, run whiptail, call `b[lines]` or
262
+ # `on_{cancel,no,esc}[]`
263
+ # @raise Error if unknown exitstatus
264
+ def self._whip(what, text, cfg, opts, args = [], &b) # {{{1
265
+ o = _whip_opts what, cfg, opts; c = _whip_cmd text, opts, o, args
266
+ r = _run_whip c
267
+ case r[:exit]
268
+ when EXIT[:ok_yes] ; b[r[:lines]] if b
269
+ when EXIT[:cancel_no] ; cfg.call :on_cancel; cfg.call :on_no
270
+ when EXIT[:esc] ; cfg.call :on_esc
271
+ else raise Error, 'unknown exitstatus'
272
+ end
273
+ nil
274
+ end # }}}1
275
+
276
+ # process whiptail options
277
+ def self._whip_opts(what, cfg, opts) # {{{1
278
+ cfg._opts + [ OPT[opts,:all],
279
+ cfg.respond_to?(:on_ok) ? OPT[opts,:ok] : [],
280
+ cfg.respond_to?(:on_cancel) ? OPT[opts,:cancel] : [],
281
+ cfg.respond_to?(:on_yes) ? OPT[opts,:yes] : [],
282
+ cfg.respond_to?(:on_no) ? OPT[opts,:no] : [],
283
+ what == :menu ? OPT[opts,:menu] : [],
284
+ ] .flatten + [WHAT[what]]
285
+ end # }}}1
286
+
287
+ # whiptail command
288
+ def self._whip_cmd(text, opts, opt_args, args) # {{{1
289
+ h = opts[:height] || OU::Term.lines - 4
290
+ w = opts[:width] || OU::Term.columns - 4
291
+ s = opts.has_key?(:subheight) ? [opts[:subheight] || h - 8] : []
292
+ a = [WHIPTAIL] + opt_args + ['--', text, h, w] + s + args
293
+ a.map(&:to_s)
294
+ end # }}}1
295
+
296
+ # run whiptail
297
+ # @return [Hash] `{ exit: exitstatus, lines: chomped_lines }`
298
+ def self._run_whip(args)
299
+ IO.pipe do |r, w|
300
+ s = OU.spawn_w(*args, err: w); w.close
301
+ { exit: s.exitstatus, lines: r.readlines.map(&:chomp) }
302
+ end
303
+ end
304
+
305
+ # --
306
+
307
+ # call block w/ either `opts[:file]` or a tempfile w/ contents
308
+ # `opts[:text]`
309
+ def self._file_or_temp(opts, &b) # {{{1
310
+ file = opts[:file]; text = opts[:text]
311
+ raise Error, 'can\'t have file and text' if file && text
312
+ raise Error, 'must have file or text' if !file && !text
313
+ if file
314
+ b[file]
315
+ else
316
+ Tempfile.open('eft') { |f| f.write text; f.close; b[f.path] }
317
+ end
318
+ end # }}}1
319
+
320
+ end
321
+
322
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: eft
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Felix C. Stegerman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: obfusk-util
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: |
42
+ ruby + whiptail
43
+
44
+ Eft is a ruby dsl that wraps whiptail to display dialog boxes.
45
+ email:
46
+ - flx@obfusk.net
47
+ executables: []
48
+ extensions: []
49
+ extra_rdoc_files: []
50
+ files:
51
+ - .yardopts
52
+ - README.md
53
+ - Rakefile
54
+ - eft.gemspec
55
+ - example.rb
56
+ - lib/eft/version.rb
57
+ - lib/eft.rb
58
+ homepage: https://github.com/obfusk/eft
59
+ licenses:
60
+ - LGPLv3+
61
+ metadata: {}
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - '>='
69
+ - !ruby/object:Gem::Version
70
+ version: 1.9.1
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubyforge_project:
78
+ rubygems_version: 2.0.14
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: ruby + whiptail
82
+ test_files: []