eftcmdr 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: c026792651e7d592cd7e95b0cdbeba4b48a72a34
4
+ data.tar.gz: 90f7c70c580bfa46dcd83a809dc241a9115f77fc
5
+ SHA512:
6
+ metadata.gz: 12f6227308d8c61cca91fd372776dc89f628dc3bc3ce06e63dac725ba0217b67d7b2d8fcff56f5840e22c82162ea4bd805237df4a16c61295c6175121f452226
7
+ data.tar.gz: 7519af3448265a958f276452a7e9fd4d117ecf986bc61b2cc03f6552e37551b955f528e1656ee87b6ac8c36c20b26bc72b53316d5d540d760b6e5fa08f8aaf28
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup markdown
data/README.md ADDED
@@ -0,0 +1,77 @@
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/eftcmdr.png)](http://badge.fury.io/rb/eftcmdr)
13
+
14
+ ## Description
15
+ []: {{{1
16
+
17
+ eftcmdr - yaml + ruby + whiptail
18
+
19
+ EftCmdr is a yaml dsl that wraps `whiptail` [1] to display dialog
20
+ boxes. It provides a yaml dsl on top of `eft` [2]. See `examples/`
21
+ for examples.
22
+
23
+ ```yaml
24
+ ask: ask_name
25
+ text: What is your name?
26
+ then:
27
+ eval: eval_hello
28
+ code: |
29
+ puts "Hello, #{ctx[:ask_name]}!"
30
+ ```
31
+
32
+ ```bash
33
+ $ eftcmdr examples/hello.yml
34
+ ```
35
+
36
+ ### SSH
37
+
38
+ You can use `eftcmdr-ssh-setup` to generate a
39
+ `~/.ssh/authorized_keys` from `~/.eftcmdr.d/*.{pub,yml}` (see
40
+ `examples/`). This allows you to use `eftcmdr` to provide a menu
41
+ over `ssh -t` that allows selected users to perform selected
42
+ actions.
43
+
44
+ **NB**: be careful what you allow -- access to e.g. a rails console
45
+ makes it trivial to get complete shell access.
46
+
47
+ []: }}}1
48
+
49
+ ## Specs & Docs
50
+
51
+ ```bash
52
+ $ rake spec # TODO
53
+ $ rake docs
54
+ ```
55
+
56
+ ## TODO
57
+
58
+ * gauge?
59
+ * options?
60
+ * specs! (how to automate tests of whiptail? - I don't know!)
61
+
62
+ ## License
63
+
64
+ LGPLv3+ [3].
65
+
66
+ ## References
67
+
68
+ [1] Newt (and whiptail)
69
+ --- http://en.wikipedia.org/wiki/Newt_(programming_library)
70
+
71
+ [2] eft
72
+ --- https://github.com/obfusk/eft
73
+
74
+ [3] GNU Lesser General Public License, version 3
75
+ --- http://www.gnu.org/licenses/lgpl-3.0.html
76
+
77
+ []: ! ( vim: set tw=70 sw=2 sts=2 et fdm=marker : )
data/Rakefile ADDED
@@ -0,0 +1,70 @@
1
+ desc 'Run specs'
2
+ task :spec do
3
+ puts 'No automated tests yet - please manually test the examples'
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 examples'
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 examples'
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 -r eftcmdr -e ""'
22
+ end
23
+
24
+ desc 'Run example foo'
25
+ task 'example:foo' do
26
+ sh 'ruby -w -I lib bin/eftcmdr examples/foo.yml'
27
+ end
28
+
29
+ desc 'Run example bar'
30
+ task 'example:bar' do
31
+ sh 'ruby -w -I lib bin/eftcmdr examples/bar.yml'
32
+ end
33
+
34
+ desc 'Run example qux'
35
+ task 'example:qux' do
36
+ sh 'ruby -w -I lib bin/eftcmdr examples/qux.yml'
37
+ end
38
+
39
+ desc 'Run example hello'
40
+ task 'example:hello' do
41
+ sh 'ruby -w -I lib bin/eftcmdr examples/hello.yml'
42
+ end
43
+
44
+ desc 'Generate docs'
45
+ task :docs do
46
+ sh 'yardoc | cat'
47
+ end
48
+
49
+ desc 'List undocumented objects'
50
+ task 'docs:undoc' do
51
+ sh 'yard stats --list-undoc'
52
+ end
53
+
54
+ desc 'Cleanup'
55
+ task :clean do
56
+ sh 'rm -rf .yardoc/ doc/ *.gem'
57
+ end
58
+
59
+ desc 'Build SNAPSHOT gem'
60
+ task :snapshot do
61
+ v = Time.new.strftime '%Y%m%d%H%M%S'
62
+ f = 'lib/eftcmdr/version.rb'
63
+ sh "sed -ri~ 's!(SNAPSHOT)!\\1.#{v}!' #{f}"
64
+ sh 'gem build eftcmdr.gemspec'
65
+ end
66
+
67
+ desc 'Undo SNAPSHOT gem'
68
+ task 'snapshot:undo' do
69
+ sh 'git checkout -- lib/eftcmdr/version.rb'
70
+ end
data/bin/eftcmdr ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'eftcmdr'
4
+
5
+ EftCmdr.run(*EftCmdr.load_yaml(*ARGV))
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'eftcmdr'
4
+
5
+ file = ARGV[0] || "#{Dir.home}/.ssh/authorized_keys"
6
+ dir = ARGV[1] || "#{Dir.home}/.eftcmdr.d"
7
+
8
+ EftCmdr.build_authorized_keys file, dir
data/eftcmdr.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ require File.expand_path('../lib/eftcmdr/version', __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'eftcmdr'
5
+ s.homepage = 'https://github.com/obfusk/eftcmdr'
6
+ s.summary = 'yaml + ruby + whiptail'
7
+
8
+ s.description = <<-END.gsub(/^ {4}/, '')
9
+ EftCmdr is a yaml dsl that wraps whiptail to display dialog boxes.
10
+ It provides a yaml dsl on top of eft. See examples/ for examples.
11
+ END
12
+
13
+ s.version = EftCmdr::VERSION
14
+ s.date = EftCmdr::DATE
15
+
16
+ s.authors = [ 'Felix C. Stegerman' ]
17
+ s.email = %w{ flx@obfusk.net }
18
+
19
+ s.licenses = %w{ LGPLv3+ }
20
+
21
+ s.executables = %w{ eftcmdr eftcmdr-ssh-setup }
22
+ s.files = %w{ .yardopts README.md Rakefile eftcmdr.gemspec } \
23
+ + Dir['examples/**/*.{yml,apps}'] \
24
+ + Dir['lib/**/*.rb']
25
+
26
+ s.add_runtime_dependency 'eft'
27
+ s.add_runtime_dependency 'obfusk-util', '>= 0.5.0'
28
+
29
+ s.add_development_dependency 'rake'
30
+ # s.add_development_dependency 'rspec'
31
+
32
+ s.required_ruby_version = '>= 1.9.1'
33
+ end
data/examples/bar.apps ADDED
@@ -0,0 +1 @@
1
+ qux quux
data/examples/bar.yml ADDED
@@ -0,0 +1,70 @@
1
+ _apps: &_apps
2
+ <% apps = file.sub(/\.yml\z/, '.apps') %>
3
+ <% if File.exists? apps %>
4
+ <% File.read(apps).split.each do |x| %>
5
+ - tag: <%= x %>
6
+ text: The <%= x %> app
7
+ <% end %>
8
+ <% end %>
9
+
10
+ _menu_commands: &_menu_commands
11
+ menu: menu_commands
12
+ title: commands
13
+ text: Choose a command to run
14
+ choices:
15
+
16
+ - tag: log
17
+ text: view log
18
+ then:
19
+ ask: ask_lines
20
+ text: How many lines?
21
+ default: 100
22
+ validate: \A\d+\z
23
+ then:
24
+ eval: eval_view_log
25
+ code: |
26
+ sh! 'echo cd "$1" && echo tail -n "$2" logfile', app, ctx[:ask_lines]
27
+
28
+ - tag: console
29
+ text: rails console
30
+ then:
31
+ eval: eval_rails_console
32
+ code: |
33
+ sh! 'echo cd "$1" && echo rails console', app
34
+
35
+ - tag: psql
36
+ text: postgresql console
37
+ then:
38
+ eval: eval_psql
39
+ code: |
40
+ sh! 'echo psql "$1"', app
41
+
42
+ - tag: reset
43
+ text: git reset
44
+ then:
45
+ show_text: show_text_git_status
46
+ code: |
47
+ shc!('echo cd "$1" && echo git fetch --all && echo git status',
48
+ app, merge: true).stdout
49
+ then:
50
+ ask_yesno: ask_yesno_git_reset
51
+ text: Are you sure?
52
+ then:
53
+ eval: eval_git_reset
54
+ code: |
55
+ sh! 'echo cd "$1" && echo git reset --hard', app
56
+ else:
57
+ eval: eval_git_reset_cancelled
58
+ code: |
59
+ puts 'git reset cancelled'
60
+
61
+ menu: menu_apps
62
+ title: apps
63
+ text: Choose an app
64
+ choices: *_apps
65
+ then:
66
+ eval: eval_menu_apps
67
+ code: |
68
+ app = ctx[:menu_apps][:tag]
69
+ then: *_menu_commands
70
+
data/examples/foo.apps ADDED
@@ -0,0 +1,2 @@
1
+ foo bar
2
+ baz
data/examples/foo.yml ADDED
@@ -0,0 +1,70 @@
1
+ _apps: &_apps
2
+ <% apps = file.sub(/\.yml\z/, '.apps') %>
3
+ <% if File.exists? apps %>
4
+ <% File.read(apps).split.each do |x| %>
5
+ - tag: <%= x %>
6
+ text: The <%= x %> app
7
+ <% end %>
8
+ <% end %>
9
+
10
+ _menu_commands: &_menu_commands
11
+ menu: menu_commands
12
+ title: commands
13
+ text: Choose a command to run
14
+ choices:
15
+
16
+ - tag: log
17
+ text: view log
18
+ then:
19
+ ask: ask_lines
20
+ text: How many lines?
21
+ default: 100
22
+ validate: \A\d+\z
23
+ then:
24
+ eval: eval_view_log
25
+ code: |
26
+ sh! 'echo cd "$1" && echo tail -n "$2" logfile', app, ctx[:ask_lines]
27
+
28
+ - tag: console
29
+ text: rails console
30
+ then:
31
+ eval: eval_rails_console
32
+ code: |
33
+ sh! 'echo cd "$1" && echo rails console', app
34
+
35
+ - tag: psql
36
+ text: postgresql console
37
+ then:
38
+ eval: eval_psql
39
+ code: |
40
+ sh! 'echo psql "$1"', app
41
+
42
+ - tag: reset
43
+ text: git reset
44
+ then:
45
+ show_text: show_text_git_status
46
+ code: |
47
+ shc!('echo cd "$1" && echo git fetch --all && echo git status',
48
+ app, merge: true).stdout
49
+ then:
50
+ ask_yesno: ask_yesno_git_reset
51
+ text: Are you sure?
52
+ then:
53
+ eval: eval_git_reset
54
+ code: |
55
+ sh! 'echo cd "$1" && echo git reset --hard', app
56
+ else:
57
+ eval: eval_git_reset_cancelled
58
+ code: |
59
+ puts 'git reset cancelled'
60
+
61
+ menu: menu_apps
62
+ title: apps
63
+ text: Choose an app
64
+ choices: *_apps
65
+ then:
66
+ eval: eval_menu_apps
67
+ code: |
68
+ app = ctx[:menu_apps][:tag]
69
+ then: *_menu_commands
70
+
@@ -0,0 +1,6 @@
1
+ ask: ask_name
2
+ text: What is your name?
3
+ then:
4
+ eval: eval_hello
5
+ code: |
6
+ puts "Hello, #{ctx[:ask_name]}!"
data/examples/qux.yml ADDED
@@ -0,0 +1,66 @@
1
+ <% require 'securerandom' %>
2
+
3
+ _menu_stuff: &_menu_stuff
4
+ menu: menu_stuff
5
+ title: stuff
6
+ text: Choose something
7
+ choices:
8
+
9
+ - tag: secret
10
+ text: secret stuff
11
+ then:
12
+ ask_pass: ask_pass_secret
13
+ text: Enter the secret password
14
+ then:
15
+ eval: eval_secret
16
+ code: |
17
+ sh! 'echo the secret is "$1!"', ctx[:ask_pass_secret].to_s
18
+
19
+ - tag: special
20
+ text: special stuff
21
+ then:
22
+ show_text: show_text_services
23
+ file: /etc/services
24
+ scroll: true
25
+ then: *_menu_stuff
26
+
27
+ - tag: check
28
+ text: Checkboxes
29
+ then:
30
+ check: check_foo
31
+ text: Choose!
32
+ choices:
33
+ - tag: first
34
+ text: '#1'
35
+ - tag: second
36
+ text: '#2'
37
+ then:
38
+ eval: eval_check
39
+ code: |
40
+ ctx[:check_foo].length > 0
41
+ then:
42
+ show_msg: show_msg_more
43
+ text: you selected one or more
44
+ else:
45
+ show_msg: show_msg_securerandom
46
+ code: |
47
+ SecureRandom.hex 32
48
+ esc:
49
+ eval: eval_esc
50
+ code: |
51
+ puts 'ESCAPED!'
52
+
53
+ menu: menu_choose
54
+ title: choose
55
+ text: Choose
56
+ selected: two
57
+ choices:
58
+ - tag: one
59
+ text: 1
60
+ - tag: two
61
+ text: 2
62
+ then: *_menu_stuff
63
+ cancel:
64
+ eval: eval_cancelled
65
+ code: |
66
+ puts 'CANCELLED!'
@@ -0,0 +1,4 @@
1
+ module EftCmdr
2
+ VERSION = '0.4.0'
3
+ DATE = '2014-02-20'
4
+ end
data/lib/eftcmdr.rb ADDED
@@ -0,0 +1,258 @@
1
+ # -- ; {{{1
2
+ #
3
+ # File : eftcmdr.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 'erb'
13
+ require 'yaml'
14
+
15
+ require 'eft'
16
+ require 'obfusk/util/sh'
17
+
18
+ module EftCmdr
19
+
20
+ class InvalidFileNameError < RuntimeError; end
21
+ class InvalidSpecError < RuntimeError; end
22
+ class ValidationError < RuntimeError; end
23
+
24
+ # --
25
+
26
+ # state: context, data, binding
27
+ class State < Struct.new(:ctx, :data, :scope) # {{{1
28
+ def initialize(ctx, data, scope = nil)
29
+ super ctx, data, scope || data._binding
30
+ end
31
+ def merge_ctx(ctx_)
32
+ self.class.new ctx.merge(ctx_), data, scope
33
+ end
34
+ def eval(code)
35
+ data.ctx = ctx; scope.eval code
36
+ end
37
+ end # }}}1
38
+
39
+ # data: file, args, context
40
+ class Data < Struct.new(:file, :args, :ctx)
41
+ %w{ sh sh? sh! shc shc? shc! }.each do |m|
42
+ define_method(m) { |*a,&b| Obfusk::Util.send(m, *a, &b) }
43
+ end
44
+ def _binding; binding; end
45
+ end
46
+
47
+ # --
48
+
49
+ SSH_LINE = -> cmd, key, comment {
50
+ %Q{command="#{cmd}",no-agent-forwarding,no-port-forwarding,} +
51
+ %Q{no-X11-forwarding #{key} #{comment}}
52
+ }
53
+
54
+ ACTIONS = %w{ eval menu check radio ask ask_pass ask_yesno
55
+ show_msg show_text }
56
+
57
+ # --
58
+
59
+ # run self.$ACTION
60
+ def self.run(spec, state = new_state)
61
+ ACTIONS.each { |x| return self.send x, spec, state if spec[x] }
62
+ raise InvalidSpecError, 'no action found'
63
+ end
64
+
65
+ # run w/ merged ctx if there is a next action to run
66
+ def self.then_run(spec, state, ctx = {})
67
+ run spec, state.merge_ctx(ctx) if spec
68
+ end
69
+
70
+ # --
71
+
72
+ # evaluate and continue
73
+ def self.eval(spec, state, &b)
74
+ v = state.eval spec['code']
75
+ n = v ? spec['then'] : spec['else'] || spec['then']
76
+ b ? b[v,n] : then_run(n, state, spec['eval'].to_sym => v)
77
+ end
78
+
79
+ # --
80
+
81
+ # new state
82
+ def self.new_state(file = nil, args = [])
83
+ State.new({}, Data.new(file, args, nil))
84
+ end
85
+
86
+ # load yaml (parsed w/ ERB)
87
+ # @return [Array] [yaml,state]
88
+ def self.load_yaml(file, *args)
89
+ s = new_state file, args
90
+ y = YAML.load ERB.new(File.read(file)).result s.scope
91
+ [y,s]
92
+ end
93
+
94
+ # handle `on_{cancel,esc}`
95
+ def self.on_cancel_esc(e, spec, state)
96
+ e.on_cancel { then_run spec['cancel'], state } \
97
+ if e.respond_to? :on_cancel
98
+ e.on_esc { then_run spec['esc'], state } \
99
+ if e.respond_to? :on_esc
100
+ end
101
+
102
+ # helper
103
+ def self._opts(spec, more = {})
104
+ { title: spec['title'], scroll: spec['scroll'] } .merge more
105
+ end
106
+
107
+ # --
108
+
109
+ # menu
110
+ def self.menu(spec, state) # {{{1
111
+ Eft.menu spec['text'],
112
+ _opts(spec, selected: spec['selected']) do |m|
113
+ spec['choices'].each do |c|
114
+ m.on(c['tag'], c['text']) do |x|
115
+ then_run (c['then'] || spec['then']), state,
116
+ spec['menu'].to_sym => { tag: c['tag'], text: c['text'] }
117
+ end
118
+ end
119
+ on_cancel_esc m, spec, state
120
+ end
121
+ end # }}}1
122
+
123
+ # checkboxes
124
+ def self.check(spec, state) # {{{1
125
+ Eft.check spec['text'], _opts(spec) do |cb|
126
+ spec['choices'].each do |c|
127
+ cb.choice c['tag'], c['text'], c['selected']
128
+ end
129
+ cb.on_ok do |choices|
130
+ then_run spec['then'], state, spec['check'].to_sym => choices
131
+ end
132
+ on_cancel_esc cb, spec, state
133
+ end
134
+ end # }}}1
135
+
136
+ # radiolist
137
+ def self.radio(spec, state) # {{{1
138
+ Eft.radio spec['text'],
139
+ _opts(spec, selected: spec['selected']) do |r|
140
+ spec['choices'].each do |c|
141
+ c.choice c['tag'], c['text']
142
+ end
143
+ r.on_ok do |choice|
144
+ then_run spec['then'], state, spec['radio'].to_sym => choice
145
+ end
146
+ on_cancel_esc r, spec, state
147
+ end
148
+ end # }}}1
149
+
150
+ # --
151
+
152
+ # ask
153
+ def self.ask(spec, state) # {{{1
154
+ Eft.ask spec['text'], _opts(spec, default: spec['default']) do |q|
155
+ q.on_ok do |x|
156
+ x =~ Regexp.new(spec['validate']) \
157
+ or raise ValidationError, "#{x} !~ #{spec['validate']}" \
158
+ if spec['validate']
159
+ then_run spec['then'], state, spec['ask'].to_sym => x
160
+ end
161
+ on_cancel_esc q, spec, state
162
+ end
163
+ end # }}}1
164
+
165
+ # ask password
166
+ def self.ask_pass(spec, state) # {{{1
167
+ Eft.ask_pass spec['text'], _opts(spec) do |q|
168
+ q.on_ok do |x|
169
+ then_run spec['then'], state, spec['ask_pass'].to_sym => x
170
+ end
171
+ on_cancel_esc q, spec, state
172
+ end
173
+ end # }}}1
174
+
175
+ # ask yes/no
176
+ def self.ask_yesno(spec, state) # {{{1
177
+ Eft.ask_yesno spec['text'], _opts(spec) do |q|
178
+ q.on_yes do
179
+ then_run spec['then'], state, spec['ask_yesno'].to_sym => true
180
+ end
181
+ q.on_no do
182
+ then_run (spec['else'] || spec['then']), state,
183
+ spec['ask_yesno'].to_sym => false
184
+ end
185
+ on_cancel_esc q, spec, state
186
+ end
187
+ end # }}}1
188
+
189
+ # --
190
+
191
+ # show message
192
+ def self.show_msg(spec, state) # {{{1
193
+ o = _opts(spec)
194
+ if spec['code']
195
+ eval spec, state do |v,n|
196
+ Eft.show_msg v, o do |t|
197
+ t.on_ok { then_run n, state, spec['show_msg'].to_sym => v }
198
+ on_cancel_esc t, spec, state
199
+ end
200
+ end
201
+ elsif spec['text']
202
+ Eft.show_msg spec['text'], o do |t|
203
+ t.on_ok { then_run spec['then'], state }
204
+ on_cancel_esc t, spec, state
205
+ end
206
+ else
207
+ raise InvalidSpecError, 'show_msg needs code or text'
208
+ end
209
+ end # }}}1
210
+
211
+ # show text/file
212
+ def self.show_text(spec, state) # {{{1
213
+ if spec['code']
214
+ eval spec, state do |v,n|
215
+ Eft.show_text _opts(spec, text: v) do |t|
216
+ t.on_ok { then_run n, state, spec['show_text'].to_sym => v }
217
+ on_cancel_esc t, spec, state
218
+ end
219
+ end
220
+ elsif spec['text']
221
+ Eft.show_text _opts(spec, text: spec['text']) do |t|
222
+ t.on_ok { then_run spec['then'], state }
223
+ on_cancel_esc t, spec, state
224
+ end
225
+ elsif spec['file']
226
+ Eft.show_text _opts(spec, file: spec['file']) do |t|
227
+ t.on_ok { then_run spec['then'], state }
228
+ on_cancel_esc t, spec, state
229
+ end
230
+ else
231
+ raise InvalidSpecError, 'show_text needs code, text, or file'
232
+ end
233
+ end # }}}1
234
+
235
+ # --
236
+
237
+ # turn ~/.eftcmdr.d into ~/.ssh/authorized_keys
238
+ def self.build_authorized_keys(file, dir) # {{{1
239
+ dir =~ %r{\A[A-Za-z0-9_./-]+\z} \
240
+ or raise InvalidFileNameError, "invalid dir name: #{dir}"
241
+ original = (File.exists?(file) ? File.read(file) : '') \
242
+ .lines.reject { |l| l =~ /EFTCMDR/ }
243
+ lines = Dir["#{dir}/*.pub"].sort.map do |x|
244
+ b = File.basename x, '.pub'
245
+ b =~ %r{\A[A-Za-z0-9_.-]+\z} \
246
+ or raise InvalidFileNameError, "invalid file name: #{x}"
247
+ k = File.read(x).chomp
248
+ f = File.exists?("#{dir}/#{b}.yml") ? "#{b}.yml" : 'default.yml'
249
+ SSH_LINE["eftcmdr #{dir}/#{f} #{b}", k, "(EFTCMDR #{x})"]
250
+ end
251
+ File.open(file, 'w') do |f|
252
+ (original + lines).each { |l| f.puts l }
253
+ end
254
+ end # }}}1
255
+
256
+ end
257
+
258
+ # vim: set tw=70 sw=2 sts=2 et fdm=marker :
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: eftcmdr
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: eft
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: obfusk-util
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.5.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.5.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: |
56
+ EftCmdr is a yaml dsl that wraps whiptail to display dialog boxes.
57
+ It provides a yaml dsl on top of eft. See examples/ for examples.
58
+ email:
59
+ - flx@obfusk.net
60
+ executables:
61
+ - eftcmdr
62
+ - eftcmdr-ssh-setup
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - ".yardopts"
67
+ - README.md
68
+ - Rakefile
69
+ - eftcmdr.gemspec
70
+ - examples/hello.yml
71
+ - examples/qux.yml
72
+ - examples/bar.yml
73
+ - examples/foo.yml
74
+ - examples/foo.apps
75
+ - examples/bar.apps
76
+ - lib/eftcmdr.rb
77
+ - lib/eftcmdr/version.rb
78
+ - bin/eftcmdr
79
+ - bin/eftcmdr-ssh-setup
80
+ homepage: https://github.com/obfusk/eftcmdr
81
+ licenses:
82
+ - LGPLv3+
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 1.9.1
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 2.0.14
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: yaml + ruby + whiptail
104
+ test_files: []
105
+ has_rdoc: