eftcmdr 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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: