cloulu 0.0.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/{cloulu → cl} +0 -0
- data/lib/cc_api_stub/applications.rb +53 -0
- data/lib/cc_api_stub/domains.rb +16 -0
- data/lib/cc_api_stub/frameworks.rb +22 -0
- data/lib/cc_api_stub/helper.rb +131 -0
- data/lib/cc_api_stub/login.rb +21 -0
- data/lib/cc_api_stub/organization_users.rb +21 -0
- data/lib/cc_api_stub/organizations.rb +70 -0
- data/lib/cc_api_stub/routes.rb +26 -0
- data/lib/cc_api_stub/runtimes.rb +22 -0
- data/lib/cc_api_stub/service_bindings.rb +22 -0
- data/lib/cc_api_stub/service_instances.rb +22 -0
- data/lib/cc_api_stub/services.rb +25 -0
- data/lib/cc_api_stub/spaces.rb +49 -0
- data/lib/cc_api_stub/users.rb +84 -0
- data/lib/cc_api_stub.rb +17 -0
- data/lib/cfoundry/auth_token.rb +63 -0
- data/lib/cfoundry/baseclient.rb +201 -0
- data/lib/cfoundry/chatty_hash.rb +46 -0
- data/lib/cfoundry/client.rb +46 -0
- data/lib/cfoundry/concerns/login_helpers.rb +13 -0
- data/lib/cfoundry/errors.rb +160 -0
- data/lib/cfoundry/rest_client.rb +299 -0
- data/lib/cfoundry/test_support.rb +3 -0
- data/lib/cfoundry/trace_helpers.rb +40 -0
- data/lib/cfoundry/uaaclient.rb +112 -0
- data/lib/cfoundry/upload_helpers.rb +187 -0
- data/lib/cfoundry/v1/app.rb +363 -0
- data/lib/cfoundry/v1/base.rb +72 -0
- data/lib/cfoundry/v1/client.rb +193 -0
- data/lib/cfoundry/v1/framework.rb +21 -0
- data/lib/cfoundry/v1/model.rb +178 -0
- data/lib/cfoundry/v1/model_magic.rb +129 -0
- data/lib/cfoundry/v1/runtime.rb +24 -0
- data/lib/cfoundry/v1/service.rb +39 -0
- data/lib/cfoundry/v1/service_instance.rb +32 -0
- data/lib/cfoundry/v1/service_plan.rb +19 -0
- data/lib/cfoundry/v1/user.rb +22 -0
- data/lib/cfoundry/v2/app.rb +392 -0
- data/lib/cfoundry/v2/base.rb +83 -0
- data/lib/cfoundry/v2/client.rb +138 -0
- data/lib/cfoundry/v2/domain.rb +11 -0
- data/lib/cfoundry/v2/framework.rb +14 -0
- data/lib/cfoundry/v2/model.rb +148 -0
- data/lib/cfoundry/v2/model_magic.rb +449 -0
- data/lib/cfoundry/v2/organization.rb +16 -0
- data/lib/cfoundry/v2/route.rb +15 -0
- data/lib/cfoundry/v2/runtime.rb +12 -0
- data/lib/cfoundry/v2/service.rb +19 -0
- data/lib/cfoundry/v2/service_auth_token.rb +9 -0
- data/lib/cfoundry/v2/service_binding.rb +10 -0
- data/lib/cfoundry/v2/service_instance.rb +14 -0
- data/lib/cfoundry/v2/service_plan.rb +12 -0
- data/lib/cfoundry/v2/space.rb +18 -0
- data/lib/cfoundry/v2/user.rb +64 -0
- data/lib/cfoundry/validator.rb +39 -0
- data/lib/cfoundry/version.rb +4 -0
- data/lib/cfoundry/zip.rb +56 -0
- data/lib/cfoundry.rb +2 -0
- data/lib/manifests-vmc-plugin/errors.rb +21 -0
- data/lib/manifests-vmc-plugin/loader/builder.rb +34 -0
- data/lib/manifests-vmc-plugin/loader/normalizer.rb +149 -0
- data/lib/manifests-vmc-plugin/loader/resolver.rb +79 -0
- data/lib/manifests-vmc-plugin/loader.rb +31 -0
- data/lib/manifests-vmc-plugin/plugin.rb +145 -0
- data/lib/manifests-vmc-plugin/version.rb +3 -0
- data/lib/manifests-vmc-plugin.rb +313 -0
- data/lib/mothership/base.rb +99 -0
- data/lib/mothership/callbacks.rb +85 -0
- data/lib/mothership/command.rb +146 -0
- data/lib/mothership/errors.rb +38 -0
- data/lib/mothership/help/commands.rb +53 -0
- data/lib/mothership/help/printer.rb +170 -0
- data/lib/mothership/help.rb +64 -0
- data/lib/mothership/inputs.rb +189 -0
- data/lib/mothership/parser.rb +182 -0
- data/lib/mothership/version.rb +3 -0
- data/lib/mothership.rb +64 -0
- data/lib/tunnel-vmc-plugin/plugin.rb +178 -0
- data/lib/tunnel-vmc-plugin/tunnel.rb +308 -0
- data/lib/tunnel-vmc-plugin/version.rb +3 -0
- data/lib/uaa/http.rb +168 -0
- data/lib/uaa/misc.rb +121 -0
- data/lib/uaa/scim.rb +292 -0
- data/lib/uaa/token_coder.rb +196 -0
- data/lib/uaa/token_issuer.rb +255 -0
- data/lib/uaa/util.rb +235 -0
- data/lib/uaa/version.rb +19 -0
- data/lib/uaa.rb +18 -0
- data/lib/vmc/cli/app/app.rb +45 -0
- data/lib/vmc/cli/app/apps.rb +99 -0
- data/lib/vmc/cli/app/base.rb +90 -0
- data/lib/vmc/cli/app/crashes.rb +42 -0
- data/lib/vmc/cli/app/delete.rb +95 -0
- data/lib/vmc/cli/app/deprecated.rb +11 -0
- data/lib/vmc/cli/app/env.rb +78 -0
- data/lib/vmc/cli/app/files.rb +137 -0
- data/lib/vmc/cli/app/health.rb +26 -0
- data/lib/vmc/cli/app/instances.rb +53 -0
- data/lib/vmc/cli/app/logs.rb +76 -0
- data/lib/vmc/cli/app/push/create.rb +165 -0
- data/lib/vmc/cli/app/push/interactions.rb +94 -0
- data/lib/vmc/cli/app/push/sync.rb +64 -0
- data/lib/vmc/cli/app/push.rb +109 -0
- data/lib/vmc/cli/app/rename.rb +35 -0
- data/lib/vmc/cli/app/restart.rb +20 -0
- data/lib/vmc/cli/app/scale.rb +71 -0
- data/lib/vmc/cli/app/start.rb +143 -0
- data/lib/vmc/cli/app/stats.rb +67 -0
- data/lib/vmc/cli/app/stop.rb +27 -0
- data/lib/vmc/cli/help.rb +11 -0
- data/lib/vmc/cli/interactive.rb +105 -0
- data/lib/vmc/cli/route/base.rb +12 -0
- data/lib/vmc/cli/route/map.rb +82 -0
- data/lib/vmc/cli/route/routes.rb +25 -0
- data/lib/vmc/cli/route/unmap.rb +94 -0
- data/lib/vmc/cli/service/base.rb +8 -0
- data/lib/vmc/cli/service/bind.rb +44 -0
- data/lib/vmc/cli/service/create.rb +126 -0
- data/lib/vmc/cli/service/delete.rb +86 -0
- data/lib/vmc/cli/service/rename.rb +35 -0
- data/lib/vmc/cli/service/service.rb +42 -0
- data/lib/vmc/cli/service/services.rb +114 -0
- data/lib/vmc/cli/service/unbind.rb +38 -0
- data/lib/vmc/cli/start/base.rb +94 -0
- data/lib/vmc/cli/start/colors.rb +13 -0
- data/lib/vmc/cli/start/info.rb +126 -0
- data/lib/vmc/cli/start/login.rb +97 -0
- data/lib/vmc/cli/start/logout.rb +17 -0
- data/lib/vmc/cli/start/target.rb +60 -0
- data/lib/vmc/cli/start/target_interactions.rb +37 -0
- data/lib/vmc/cli/start/targets.rb +16 -0
- data/lib/vmc/cli/user/base.rb +29 -0
- data/lib/vmc/cli/user/create.rb +39 -0
- data/lib/vmc/cli/user/delete.rb +27 -0
- data/lib/vmc/cli/user/passwd.rb +50 -0
- data/lib/vmc/cli/user/register.rb +42 -0
- data/lib/vmc/cli/user/users.rb +32 -0
- data/lib/vmc/cli/v2_check_cli.rb +16 -0
- data/lib/vmc/cli.rb +474 -0
- data/lib/vmc/constants.rb +13 -0
- data/lib/vmc/detect.rb +129 -0
- data/lib/vmc/errors.rb +19 -0
- data/lib/vmc/plugin.rb +56 -0
- data/lib/vmc/spacing.rb +89 -0
- data/lib/vmc/spec_helper.rb +1 -0
- data/lib/vmc/test_support.rb +6 -0
- data/lib/vmc/version.rb +3 -0
- data/lib/vmc.rb +8 -0
- data/vendor/errors/v1.yml +189 -0
- data/vendor/errors/v2.yml +360 -0
- metadata +303 -190
@@ -0,0 +1,53 @@
|
|
1
|
+
require "mothership/help/printer"
|
2
|
+
|
3
|
+
class Mothership
|
4
|
+
class << self
|
5
|
+
# add command to help group
|
6
|
+
def group(*names)
|
7
|
+
options =
|
8
|
+
if names.last.is_a? Hash
|
9
|
+
names.pop
|
10
|
+
else
|
11
|
+
{}
|
12
|
+
end
|
13
|
+
|
14
|
+
Mothership::Help.add_to_group(@command, names, options)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def default_action
|
19
|
+
invoke :help
|
20
|
+
end
|
21
|
+
|
22
|
+
def unknown_command(name)
|
23
|
+
$stderr.print "Unknown command '#{name.to_s.gsub("_", "-")}'. "
|
24
|
+
$stderr.puts "See 'help' for available commands."
|
25
|
+
exit_status 1
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "Help!"
|
29
|
+
input :command, :argument => :optional
|
30
|
+
input :all, :type => :boolean
|
31
|
+
def help
|
32
|
+
# custom header
|
33
|
+
puts "\x1B[1m\x1B[33m===========================================================\x1B[00m"
|
34
|
+
puts "\x1B[1m\x1B[33m* Welcome Cloulu Platform\x1B[00m"
|
35
|
+
puts "\x1B[1m\x1B[33m*\x1B[00m"
|
36
|
+
puts "\x1B[1m\x1B[33m* @author clouluteam <cloulu@sk.com>\x1B[00m"
|
37
|
+
puts "\x1B[1m\x1B[33m* @homepage https://cloulu.com, http://blog.cloulu.com\x1B[00m"
|
38
|
+
puts "\x1B[1m\x1B[33m============================================================\x1B[00m"
|
39
|
+
puts
|
40
|
+
|
41
|
+
if name = input[:command]
|
42
|
+
if cmd = @@commands[name.gsub("-", "_").to_sym]
|
43
|
+
Mothership::Help.command_help(cmd)
|
44
|
+
else
|
45
|
+
unknown_command(name)
|
46
|
+
end
|
47
|
+
elsif Help.has_groups?
|
48
|
+
Mothership::Help.print_help_groups(@@global, input[:all])
|
49
|
+
else
|
50
|
+
Mothership::Help.basic_help(@@commands, @@global)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
module Mothership::Help
|
2
|
+
class << self
|
3
|
+
def print_help_groups(global = nil, all = false)
|
4
|
+
@@groups.each do |commands|
|
5
|
+
print_help_group(commands, all)
|
6
|
+
end
|
7
|
+
|
8
|
+
command_options(global)
|
9
|
+
end
|
10
|
+
|
11
|
+
def print_help_group(group, all = false, indent = 0)
|
12
|
+
return if nothing_printable?(group, all)
|
13
|
+
|
14
|
+
members = group[:members]
|
15
|
+
|
16
|
+
unless all
|
17
|
+
members = members.reject do |_, opts|
|
18
|
+
opts[:hidden]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
commands = members.collect(&:first)
|
23
|
+
|
24
|
+
i = " " * indent
|
25
|
+
|
26
|
+
# set prefix
|
27
|
+
prefix = "*"
|
28
|
+
prefix = ">>" if indent == 1
|
29
|
+
|
30
|
+
# set color
|
31
|
+
color = "31"
|
32
|
+
color = "32" if indent == 1
|
33
|
+
|
34
|
+
print i
|
35
|
+
puts "\x1B[1m\x1B[#{color}m" + prefix + " " + group[:description] + "\x1B[00m"
|
36
|
+
|
37
|
+
commands = unique_commands(commands)
|
38
|
+
|
39
|
+
width = 0
|
40
|
+
commands.each do |cmd|
|
41
|
+
len = cmd.usage.size
|
42
|
+
if len > width
|
43
|
+
width = len
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
commands.each do |cmd|
|
48
|
+
puts "#{i} #{cmd.usage.ljust(width)}\t#{cmd.description}"
|
49
|
+
end
|
50
|
+
|
51
|
+
puts "" unless commands.empty?
|
52
|
+
|
53
|
+
group[:children].each do |group|
|
54
|
+
print_help_group(group, all, indent + 1)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def basic_help(commands, global)
|
59
|
+
puts "Commands:"
|
60
|
+
|
61
|
+
width = 0
|
62
|
+
commands.each do |_, c|
|
63
|
+
len = c.usage.size
|
64
|
+
width = len if len > width
|
65
|
+
end
|
66
|
+
|
67
|
+
commands.each do |_, c|
|
68
|
+
puts " #{c.usage.ljust(width)}\t#{c.description}"
|
69
|
+
end
|
70
|
+
|
71
|
+
unless global.flags.empty?
|
72
|
+
puts ""
|
73
|
+
command_options(global)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def command_help(cmd)
|
78
|
+
puts cmd.description
|
79
|
+
puts ""
|
80
|
+
command_usage(cmd)
|
81
|
+
end
|
82
|
+
|
83
|
+
def command_usage(cmd, io = $stdout)
|
84
|
+
io.puts "Usage: #{cmd.usage}"
|
85
|
+
|
86
|
+
unless cmd.flags.empty?
|
87
|
+
io.puts ""
|
88
|
+
command_options(cmd, io)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def command_options(cmd, io = $stdout)
|
93
|
+
io.puts "Options:"
|
94
|
+
|
95
|
+
rev_flags = Hash.new { |h, k| h[k] = [] }
|
96
|
+
|
97
|
+
cmd.flags.each do |f, n|
|
98
|
+
rev_flags[n] << f
|
99
|
+
end
|
100
|
+
|
101
|
+
usages = []
|
102
|
+
|
103
|
+
max_width = 0
|
104
|
+
rev_flags.collect do |name, fs|
|
105
|
+
info = cmd.inputs[name]
|
106
|
+
next if info[:hidden]
|
107
|
+
|
108
|
+
flag = name.to_s.gsub("_", "-")
|
109
|
+
|
110
|
+
# move full form to the front
|
111
|
+
fs.unshift fs.delete("--#{flag}")
|
112
|
+
|
113
|
+
if short = fs.find { |x| x =~ /^-.$/ }
|
114
|
+
fs.delete short
|
115
|
+
end
|
116
|
+
|
117
|
+
if info[:type] == :boolean && info[:default]
|
118
|
+
fs[0] = "--[no-]#{flag}"
|
119
|
+
end
|
120
|
+
|
121
|
+
if info.key?(:default) && info.key?(:interact)
|
122
|
+
fs.unshift "--ask-#{flag}"
|
123
|
+
end
|
124
|
+
|
125
|
+
usage = "#{short ? short + "," : " "} #{fs.join ", "}"
|
126
|
+
|
127
|
+
unless info[:type] == :boolean
|
128
|
+
usage << " #{(info[:value] || name).to_s.upcase}"
|
129
|
+
end
|
130
|
+
|
131
|
+
max_width = usage.size if usage.size > max_width
|
132
|
+
|
133
|
+
usages << [usage, info[:description]]
|
134
|
+
end
|
135
|
+
|
136
|
+
usages.sort! { |a, b| a.first <=> b.first }
|
137
|
+
|
138
|
+
usages.each do |u, d|
|
139
|
+
if d
|
140
|
+
io.puts " #{u.ljust(max_width)} #{d}"
|
141
|
+
else
|
142
|
+
io.puts " #{u}"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def nothing_printable?(group, all = false)
|
150
|
+
group[:members].reject { |_, opts| !all && opts[:hidden] }.empty? &&
|
151
|
+
group[:children].all? { |g| nothing_printable?(g) }
|
152
|
+
end
|
153
|
+
|
154
|
+
def unique_commands(commands)
|
155
|
+
uniq_commands = []
|
156
|
+
cmd_index = {}
|
157
|
+
|
158
|
+
commands.each do |cmd|
|
159
|
+
if idx = cmd_index[cmd.name]
|
160
|
+
uniq_commands[idx] = cmd
|
161
|
+
else
|
162
|
+
cmd_index[cmd.name] = uniq_commands.size
|
163
|
+
uniq_commands << cmd
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
uniq_commands
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "mothership/base"
|
2
|
+
require "mothership/help/commands"
|
3
|
+
|
4
|
+
module Mothership::Help
|
5
|
+
@@groups = []
|
6
|
+
@@tree = {}
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def has_groups?
|
10
|
+
!@@groups.empty?
|
11
|
+
end
|
12
|
+
|
13
|
+
# define help groups
|
14
|
+
def groups(*tree)
|
15
|
+
tree.each do |*args|
|
16
|
+
add_group(@@groups, @@tree, *args.first)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def group(*names)
|
21
|
+
if where = find_group(names, @@tree)
|
22
|
+
where[:members].collect(&:first)
|
23
|
+
else
|
24
|
+
[]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_to_group(command, names, options)
|
29
|
+
where = find_group(names, @@tree)
|
30
|
+
raise "unknown help group: #{names.join("/")}" unless where
|
31
|
+
|
32
|
+
where[:members] << [command, options]
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def find_group(names, where)
|
38
|
+
names.each_with_index do |n, index|
|
39
|
+
where = where[:children] unless index == 0
|
40
|
+
break unless where
|
41
|
+
|
42
|
+
where = where[n]
|
43
|
+
break unless where
|
44
|
+
end
|
45
|
+
|
46
|
+
where
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_group(groups, tree, name, desc, *subs)
|
50
|
+
members = []
|
51
|
+
|
52
|
+
meta = { :members => members, :children => [] }
|
53
|
+
groups << meta
|
54
|
+
|
55
|
+
tree[name] = { :members => members, :children => {} }
|
56
|
+
|
57
|
+
meta[:description] = desc
|
58
|
+
|
59
|
+
subs.each do |*args|
|
60
|
+
add_group(meta[:children], tree[name][:children], *args.first)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
class Mothership
|
2
|
+
class Inputs
|
3
|
+
attr_reader :inputs, :given, :global
|
4
|
+
|
5
|
+
# the input being processed; set during #get
|
6
|
+
attr_reader :current_input
|
7
|
+
|
8
|
+
def initialize(
|
9
|
+
command, context = nil,
|
10
|
+
inputs = {}, given = {}, global = {})
|
11
|
+
@command = command
|
12
|
+
@context = context
|
13
|
+
@inputs = inputs
|
14
|
+
@given = given
|
15
|
+
@global = global
|
16
|
+
end
|
17
|
+
|
18
|
+
def has?(name)
|
19
|
+
@inputs.key?(name) || @given.key?(name)
|
20
|
+
end
|
21
|
+
|
22
|
+
def direct(name)
|
23
|
+
if @inputs.key?(name)
|
24
|
+
@inputs[name]
|
25
|
+
elsif (given = @given[name]) != :interact
|
26
|
+
given
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def merge(inputs)
|
31
|
+
self.class.new(@command, @context, @inputs.merge(inputs), @given, @global)
|
32
|
+
end
|
33
|
+
|
34
|
+
def merge_given(given)
|
35
|
+
self.class.new(@command, @context, @inputs.dup, @given.merge(given), @global)
|
36
|
+
end
|
37
|
+
|
38
|
+
def rebase(inputs)
|
39
|
+
self.class.new(@command, @context, inputs.merge(@inputs), @given, @global)
|
40
|
+
end
|
41
|
+
|
42
|
+
def rebase_given(given)
|
43
|
+
self.class.new(@command, @context, @inputs.dup, given.merge(@given), @global)
|
44
|
+
end
|
45
|
+
|
46
|
+
def without(*names)
|
47
|
+
given = @given.dup
|
48
|
+
inputs = @inputs.dup
|
49
|
+
names.each do |n|
|
50
|
+
given.delete(n)
|
51
|
+
inputs.delete(n)
|
52
|
+
end
|
53
|
+
|
54
|
+
self.class.new(@command, @context, inputs, given, @global)
|
55
|
+
end
|
56
|
+
|
57
|
+
def [](name, *args)
|
58
|
+
return @inputs[name] if @inputs.key?(name)
|
59
|
+
|
60
|
+
if @command && meta = @command.inputs[name]
|
61
|
+
# special case so #invoke can be called with singular-named inputs
|
62
|
+
singular = meta[:singular]
|
63
|
+
|
64
|
+
if @inputs.key?(singular)
|
65
|
+
return @inputs[name] = [@inputs[singular]]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
found, val = get(name, @context, *args)
|
70
|
+
|
71
|
+
@inputs[name] = val unless meta && meta[:forget]
|
72
|
+
|
73
|
+
val
|
74
|
+
end
|
75
|
+
|
76
|
+
def interact(name, context, *args)
|
77
|
+
meta =
|
78
|
+
if @command
|
79
|
+
@command.inputs[name]
|
80
|
+
else
|
81
|
+
Mothership.global_option(name)
|
82
|
+
end
|
83
|
+
|
84
|
+
interact = meta[:interact] || :"ask_#{name}"
|
85
|
+
|
86
|
+
case interact
|
87
|
+
when Symbol, String
|
88
|
+
context.send(interact, *args)
|
89
|
+
else
|
90
|
+
context.instance_exec(*args, &interact)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# search:
|
95
|
+
# 1. cache
|
96
|
+
# 2. cache, singular
|
97
|
+
# 3. given
|
98
|
+
# 4. given, singular
|
99
|
+
# 5. global
|
100
|
+
# 6. global, singular
|
101
|
+
def get(name, context, *args)
|
102
|
+
before_input = @current_input
|
103
|
+
@current_input = [name, args]
|
104
|
+
|
105
|
+
if @command && meta = @command.inputs[name]
|
106
|
+
found, val = find_in(@given, name, meta, context, *args)
|
107
|
+
elsif @global.is_a?(self.class)
|
108
|
+
return @global.get(name, context, *args)
|
109
|
+
elsif @global.key?(name)
|
110
|
+
return [true, @global[name]]
|
111
|
+
end
|
112
|
+
|
113
|
+
return [false, val] if not found
|
114
|
+
|
115
|
+
if val == :interact
|
116
|
+
[true, interact(name, context, *args)]
|
117
|
+
else
|
118
|
+
[true, convert_given(meta, context, val, *args)]
|
119
|
+
end
|
120
|
+
ensure
|
121
|
+
@current_input = before_input
|
122
|
+
end
|
123
|
+
|
124
|
+
def forget(name)
|
125
|
+
@inputs.delete(name)
|
126
|
+
@given.delete(name)
|
127
|
+
end
|
128
|
+
|
129
|
+
def interactive?(name)
|
130
|
+
@given[name] == :interact
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
def find_in(where, name, meta, context, *args)
|
136
|
+
singular = meta[:singular]
|
137
|
+
|
138
|
+
if where.key?(name)
|
139
|
+
[true, where[name]]
|
140
|
+
elsif where.key?(singular)
|
141
|
+
[true, [where[singular]]]
|
142
|
+
else
|
143
|
+
# no value given; set as default
|
144
|
+
[false, default_for(name, meta, context, *args)]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def convert_given(meta, context, given, *args)
|
149
|
+
if convert = meta[:from_given]
|
150
|
+
if given.is_a?(Array)
|
151
|
+
given.collect do |i|
|
152
|
+
context.instance_exec(i, *args, &convert)
|
153
|
+
end
|
154
|
+
else
|
155
|
+
context.instance_exec(given, *args, &convert)
|
156
|
+
end
|
157
|
+
else
|
158
|
+
case meta[:type]
|
159
|
+
when :integer, :number, :numeric
|
160
|
+
given.to_i
|
161
|
+
when :float, :floating
|
162
|
+
given.to_f
|
163
|
+
when :bool, :boolean
|
164
|
+
given == "true"
|
165
|
+
else
|
166
|
+
given
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def default_for(name, meta, context, *args)
|
172
|
+
if meta.key?(:default)
|
173
|
+
default = meta[:default]
|
174
|
+
|
175
|
+
if default.respond_to? :to_proc
|
176
|
+
context.instance_exec(*args, &default)
|
177
|
+
else
|
178
|
+
default
|
179
|
+
end
|
180
|
+
elsif meta[:interact] || context.respond_to?(:"ask_#{name}", true)
|
181
|
+
interact(name, context, *args)
|
182
|
+
elsif meta[:type] == :boolean
|
183
|
+
false
|
184
|
+
elsif meta[:argument] == :splat
|
185
|
+
[]
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
class Mothership
|
2
|
+
class Parser
|
3
|
+
attr_reader :given
|
4
|
+
|
5
|
+
def initialize(command, given = {})
|
6
|
+
@command = command
|
7
|
+
@given = given
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse_argv(argv)
|
11
|
+
args = parse_flags(argv.dup)
|
12
|
+
|
13
|
+
parse_arguments(args)
|
14
|
+
|
15
|
+
@given
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse_flags(argv, find_in = nil)
|
19
|
+
local = nil
|
20
|
+
args = []
|
21
|
+
|
22
|
+
until argv.empty?
|
23
|
+
flag = normalize_flag(argv.shift, argv)
|
24
|
+
|
25
|
+
name = local && local.flags[flag] || @command.flags[flag]
|
26
|
+
unless name
|
27
|
+
# assume first argument is subcommand
|
28
|
+
if args.empty? && find_in && !local
|
29
|
+
local = find_in[flag.gsub("-", "_").to_sym]
|
30
|
+
end
|
31
|
+
|
32
|
+
args << flag
|
33
|
+
next
|
34
|
+
end
|
35
|
+
|
36
|
+
# skip flags defined by the local cmd
|
37
|
+
if local && local.inputs[name]
|
38
|
+
args << flag
|
39
|
+
next
|
40
|
+
end
|
41
|
+
|
42
|
+
input = @command.inputs[name]
|
43
|
+
|
44
|
+
if argv.first == "--ask"
|
45
|
+
@given[name] = :interact
|
46
|
+
argv.shift
|
47
|
+
next
|
48
|
+
end
|
49
|
+
|
50
|
+
case input[:type]
|
51
|
+
when :bool, :boolean
|
52
|
+
if argv.first == "false" || argv.first == "true"
|
53
|
+
@given[name] = argv.shift
|
54
|
+
else
|
55
|
+
@given[name] = "true"
|
56
|
+
end
|
57
|
+
when :float, :floating
|
58
|
+
if !argv.empty? && argv.first =~ /^[0-9]+(\.[0-9]*)?$/
|
59
|
+
@given[name] = argv.shift
|
60
|
+
else
|
61
|
+
raise TypeMismatch.new(@command, name, "floating")
|
62
|
+
end
|
63
|
+
when :integer, :number, :numeric
|
64
|
+
if !argv.empty? && argv.first =~ /^[0-9]+$/
|
65
|
+
@given[name] = argv.shift
|
66
|
+
else
|
67
|
+
raise TypeMismatch.new(@command, name, "numeric")
|
68
|
+
end
|
69
|
+
else
|
70
|
+
arg =
|
71
|
+
if argv.empty? || argv.first.start_with?("-")
|
72
|
+
""
|
73
|
+
else
|
74
|
+
argv.shift
|
75
|
+
end
|
76
|
+
|
77
|
+
@given[name] =
|
78
|
+
if input[:argument] == :splat
|
79
|
+
arg.split(",")
|
80
|
+
else
|
81
|
+
arg
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
args
|
87
|
+
end
|
88
|
+
|
89
|
+
# [FOO] [BAR] FIZZ BUZZ:
|
90
|
+
# 1 2 => :fizz => 1, :buzz => 2
|
91
|
+
# 1 2 3 => :foo => 1, :fizz => 2, :buzz => 3
|
92
|
+
# 1 2 3 4 => :foo => 1, :bar => 2, :fizz => 3, :buzz => 4
|
93
|
+
def parse_arguments(args)
|
94
|
+
total = @command.arguments.size
|
95
|
+
required = 0
|
96
|
+
optional = 0
|
97
|
+
@command.arguments.each do |arg|
|
98
|
+
case arg[:type]
|
99
|
+
when :optional
|
100
|
+
optional += 1
|
101
|
+
when :splat
|
102
|
+
break
|
103
|
+
else
|
104
|
+
required += 1
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
parse_optionals = args.size - required
|
109
|
+
|
110
|
+
@command.arguments.each do |arg|
|
111
|
+
name = arg[:name]
|
112
|
+
next if @given.key? name
|
113
|
+
|
114
|
+
input = @command.inputs[name]
|
115
|
+
|
116
|
+
case arg[:type]
|
117
|
+
when :splat
|
118
|
+
@given[name] = []
|
119
|
+
|
120
|
+
until args.empty?
|
121
|
+
@given[name] << args.shift
|
122
|
+
end
|
123
|
+
|
124
|
+
when :optional
|
125
|
+
if parse_optionals > 0 && val = args.shift
|
126
|
+
@given[name] = val
|
127
|
+
parse_optionals -= 1
|
128
|
+
end
|
129
|
+
|
130
|
+
else
|
131
|
+
if val = args.shift
|
132
|
+
@given[name] = val
|
133
|
+
elsif !input[:default] && !input[:interact]
|
134
|
+
raise MissingArgument.new(@command, name)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
raise ExtraArguments.new(@command, args) unless args.empty?
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
# --no-foo => --foo false
|
145
|
+
# --no-foo true => --foo false
|
146
|
+
# --no-foo false => --foo true
|
147
|
+
#
|
148
|
+
# --foo=bar => --foo bar
|
149
|
+
def normalize_flag(flag, argv)
|
150
|
+
case flag
|
151
|
+
# boolean negation
|
152
|
+
when /^--no-(.+)/
|
153
|
+
case argv.first
|
154
|
+
when "true"
|
155
|
+
argv[0] = "false"
|
156
|
+
when "false"
|
157
|
+
argv[0] = "true"
|
158
|
+
else
|
159
|
+
argv.unshift "false"
|
160
|
+
end
|
161
|
+
|
162
|
+
"--#$1"
|
163
|
+
|
164
|
+
when /^--ask-(.+)/
|
165
|
+
argv.unshift "--ask"
|
166
|
+
"--#$1"
|
167
|
+
|
168
|
+
# --foo=bar form
|
169
|
+
when /^--([^=]+)=(.+)/
|
170
|
+
argv.unshift $2
|
171
|
+
"--#$1"
|
172
|
+
|
173
|
+
# normal flag name
|
174
|
+
when /^--([^ ]+)$/
|
175
|
+
"--#$1"
|
176
|
+
|
177
|
+
else
|
178
|
+
flag
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|