mothership 0.0.15 → 0.1.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.
- data/lib/mothership/base.rb +13 -7
- data/lib/mothership/command.rb +8 -6
- data/lib/mothership/help.rb +1 -1
- data/lib/mothership/inputs.rb +49 -23
- data/lib/mothership/parser.rb +20 -19
- data/lib/mothership/version.rb +1 -1
- data/lib/mothership.rb +7 -19
- data/spec/helpers.rb +1 -1
- metadata +4 -4
data/lib/mothership/base.rb
CHANGED
@@ -5,12 +5,12 @@ class Mothership
|
|
5
5
|
# all commands
|
6
6
|
@@commands = {}
|
7
7
|
|
8
|
-
|
9
|
-
@@inputs = nil
|
8
|
+
attr_accessor :input
|
10
9
|
|
11
10
|
# Initialize with the command being executed.
|
12
|
-
def initialize(command = nil)
|
11
|
+
def initialize(command = nil, input = nil)
|
13
12
|
@command = command
|
13
|
+
@input = input
|
14
14
|
end
|
15
15
|
|
16
16
|
class << self
|
@@ -41,8 +41,8 @@ class Mothership
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
def execute(cmd, argv)
|
45
|
-
cmd.invoke(Parser.new(cmd).
|
44
|
+
def execute(cmd, argv, global = {})
|
45
|
+
cmd.invoke({}, Parser.new(cmd).parse_argv(argv), global)
|
46
46
|
rescue Mothership::Error => e
|
47
47
|
$stderr.puts e
|
48
48
|
$stderr.puts ""
|
@@ -51,10 +51,16 @@ class Mothership
|
|
51
51
|
exit_status 1
|
52
52
|
end
|
53
53
|
|
54
|
+
# wrap this with your error handling/etc.
|
55
|
+
def run(name)
|
56
|
+
send(name)
|
57
|
+
end
|
58
|
+
|
54
59
|
# invoke a command with inputs
|
55
|
-
def invoke(
|
60
|
+
def invoke(
|
61
|
+
name, inputs = {}, given = {}, global = @input ? @input.global : {})
|
56
62
|
if cmd = @@commands[name]
|
57
|
-
cmd.invoke(given,
|
63
|
+
cmd.invoke(inputs, given, global)
|
58
64
|
else
|
59
65
|
unknown_command(name)
|
60
66
|
end
|
data/lib/mothership/command.rb
CHANGED
@@ -52,28 +52,30 @@ class Mothership
|
|
52
52
|
str
|
53
53
|
end
|
54
54
|
|
55
|
-
def invoke(given,
|
55
|
+
def invoke(inputs = {}, given = {}, global = {})
|
56
56
|
@before.each { |f, c| c.new.instance_exec(&f) }
|
57
57
|
|
58
58
|
name = @name
|
59
59
|
ctx = @context.new(self)
|
60
|
-
input = Inputs.new(self, ctx, given,
|
60
|
+
ctx.input = Inputs.new(self, ctx, inputs, given, global)
|
61
61
|
|
62
62
|
action = proc do |*given_inputs|
|
63
|
-
ctx.
|
63
|
+
ctx.input = given_inputs.first || ctx.input
|
64
|
+
ctx.run(name)
|
64
65
|
end
|
65
66
|
|
66
67
|
cmd = self
|
67
68
|
@around.each do |a, c|
|
68
69
|
before = action
|
69
70
|
|
70
|
-
sub = c.new(cmd)
|
71
|
+
sub = c.new(cmd, ctx.input)
|
71
72
|
action = proc do |*given_inputs|
|
72
|
-
|
73
|
+
ctx.input = given_inputs.first || ctx.input
|
74
|
+
sub.instance_exec(before, ctx.input, &a)
|
73
75
|
end
|
74
76
|
end
|
75
77
|
|
76
|
-
res = ctx.instance_exec(input, &action)
|
78
|
+
res = ctx.instance_exec(ctx.input, &action)
|
77
79
|
|
78
80
|
@after.each { |f, c| c.new.instance_exec(&f) }
|
79
81
|
|
data/lib/mothership/help.rb
CHANGED
@@ -215,7 +215,7 @@ class Mothership
|
|
215
215
|
desc "Help!"
|
216
216
|
input :command, :argument => :optional
|
217
217
|
input :all, :type => :boolean
|
218
|
-
def help
|
218
|
+
def help
|
219
219
|
if name = input[:command]
|
220
220
|
Mothership::Help.command_help(@@commands[name.gsub("-", "_").to_sym])
|
221
221
|
elsif Help.has_groups?
|
data/lib/mothership/inputs.rb
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
class Mothership
|
2
2
|
class Inputs
|
3
|
-
attr_reader :inputs
|
3
|
+
attr_reader :inputs, :given, :global
|
4
4
|
|
5
|
-
def initialize(
|
5
|
+
def initialize(
|
6
|
+
command, context = nil,
|
7
|
+
inputs = {}, given = {}, global = {})
|
6
8
|
@command = command
|
7
9
|
@context = context
|
8
|
-
@given = given
|
9
10
|
@inputs = inputs
|
11
|
+
@given = given
|
12
|
+
@global = global
|
10
13
|
end
|
11
14
|
|
12
15
|
def given?(name)
|
@@ -14,15 +17,19 @@ class Mothership
|
|
14
17
|
end
|
15
18
|
|
16
19
|
def given(name)
|
17
|
-
@inputs
|
20
|
+
if @inputs.key?(name)
|
21
|
+
@inputs[name]
|
22
|
+
else
|
23
|
+
@given[name]
|
24
|
+
end
|
18
25
|
end
|
19
26
|
|
20
27
|
def merge(inputs)
|
21
|
-
self.class.new(@command, @context, @
|
28
|
+
self.class.new(@command, @context, @inputs.merge(inputs), @given)
|
22
29
|
end
|
23
30
|
|
24
31
|
def merge_given(inputs)
|
25
|
-
self.class.new(@command, @context, @given.merge(inputs)
|
32
|
+
self.class.new(@command, @context, @inputs, @given.merge(inputs))
|
26
33
|
end
|
27
34
|
|
28
35
|
def without(*names)
|
@@ -40,31 +47,32 @@ class Mothership
|
|
40
47
|
get(name, @context, *args)
|
41
48
|
end
|
42
49
|
|
50
|
+
# search:
|
51
|
+
# 1. cache
|
52
|
+
# 2. cache, singular
|
53
|
+
# 3. given
|
54
|
+
# 4. given, singular
|
55
|
+
# 5. global
|
56
|
+
# 6. global, singular
|
43
57
|
def get(name, context, *args)
|
44
58
|
return @inputs[name] if @inputs.key?(name)
|
45
59
|
|
46
|
-
meta = @command.inputs[name]
|
47
|
-
|
60
|
+
if meta = @command.inputs[name]
|
61
|
+
# special case so #invoke can be called with singular-named inputs
|
62
|
+
singular = meta[:singular]
|
63
|
+
return @inputs[name] = [@inputs[singular]] if @inputs.key?(singular)
|
48
64
|
|
49
|
-
|
50
|
-
return @inputs[name] = [@inputs[singular]] if @inputs.key?(singular)
|
51
|
-
|
52
|
-
given = @given[name] if @given.key?(name)
|
53
|
-
given ||= [@given[singular]] if @given.key?(singular)
|
54
|
-
|
55
|
-
# value given; convert if needed
|
56
|
-
if given && given != []
|
57
|
-
return @inputs[name] = convert_given(meta, context, given, *args)
|
65
|
+
found, val = find_in(@given, name, meta, context, *args)
|
58
66
|
end
|
59
67
|
|
60
|
-
#
|
61
|
-
val
|
62
|
-
|
63
|
-
unless meta[:forget]
|
64
|
-
@inputs[name] = val
|
68
|
+
# if not found locally and the default is nil, search globally
|
69
|
+
if !found && val.nil? && meta = Mothership.global_option(name)
|
70
|
+
found, val = find_in(@global, name, meta, context, *args)
|
65
71
|
end
|
66
72
|
|
67
|
-
val
|
73
|
+
return val if not found
|
74
|
+
|
75
|
+
@inputs[name] = convert_given(meta, context, val, *args)
|
68
76
|
end
|
69
77
|
|
70
78
|
def forget(name)
|
@@ -74,6 +82,24 @@ class Mothership
|
|
74
82
|
|
75
83
|
private
|
76
84
|
|
85
|
+
def find_in(where, name, meta, context, *args)
|
86
|
+
singular = meta[:singular]
|
87
|
+
|
88
|
+
if where.key?(name)
|
89
|
+
[true, where[name]]
|
90
|
+
elsif where.key?(singular)
|
91
|
+
[true, [where[singular]]]
|
92
|
+
else
|
93
|
+
# no value given; set as default
|
94
|
+
val = default_for(meta, context, *args)
|
95
|
+
|
96
|
+
# cache default value
|
97
|
+
@inputs[name] = val unless meta[:forget]
|
98
|
+
|
99
|
+
[false, val]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
77
103
|
def convert_given(meta, context, given, *args)
|
78
104
|
if convert = meta[:from_given]
|
79
105
|
if given.is_a?(Array)
|
data/lib/mothership/parser.rb
CHANGED
@@ -1,20 +1,21 @@
|
|
1
1
|
class Mothership
|
2
2
|
class Parser
|
3
|
-
|
3
|
+
attr_reader :given
|
4
|
+
|
5
|
+
def initialize(command, given = {})
|
4
6
|
@command = command
|
7
|
+
@given = given
|
5
8
|
end
|
6
9
|
|
7
|
-
def
|
8
|
-
|
9
|
-
|
10
|
-
args = parse_flags(inputs, argv.dup)
|
10
|
+
def parse_argv(argv)
|
11
|
+
args = parse_flags(argv.dup)
|
11
12
|
|
12
|
-
parse_arguments(
|
13
|
+
parse_arguments(args)
|
13
14
|
|
14
|
-
|
15
|
+
@given
|
15
16
|
end
|
16
17
|
|
17
|
-
def parse_flags(
|
18
|
+
def parse_flags(argv, find_in = nil)
|
18
19
|
local = nil
|
19
20
|
args = []
|
20
21
|
|
@@ -43,19 +44,19 @@ class Mothership
|
|
43
44
|
case input[:type]
|
44
45
|
when :bool, :boolean
|
45
46
|
if argv.first == "false" || argv.first == "true"
|
46
|
-
|
47
|
+
@given[name] = argv.shift == "true"
|
47
48
|
else
|
48
|
-
|
49
|
+
@given[name] = true
|
49
50
|
end
|
50
51
|
when :float, :floating
|
51
52
|
if !argv.empty? && argv.first =~ /^[0-9]+(\.[0-9]*)?$/
|
52
|
-
|
53
|
+
@given[name] = argv.shift.to_f
|
53
54
|
else
|
54
55
|
raise TypeMismatch.new(@command.name, name, "floating")
|
55
56
|
end
|
56
57
|
when :integer, :number, :numeric
|
57
58
|
if !argv.empty? && argv.first =~ /^[0-9]+$/
|
58
|
-
|
59
|
+
@given[name] = argv.shift.to_i
|
59
60
|
else
|
60
61
|
raise TypeMismatch.new(@command.name, name, "numeric")
|
61
62
|
end
|
@@ -63,7 +64,7 @@ class Mothership
|
|
63
64
|
if argv.empty? || !argv.first.start_with?("-")
|
64
65
|
arg = argv.shift || ""
|
65
66
|
|
66
|
-
|
67
|
+
@given[name] =
|
67
68
|
if input[:argument] == :splat
|
68
69
|
arg.split(",")
|
69
70
|
else
|
@@ -80,7 +81,7 @@ class Mothership
|
|
80
81
|
# 1 2 => :fizz => 1, :buzz => 2
|
81
82
|
# 1 2 3 => :foo => 1, :fizz => 2, :buzz => 3
|
82
83
|
# 1 2 3 4 => :foo => 1, :bar => 2, :fizz => 3, :buzz => 4
|
83
|
-
def parse_arguments(
|
84
|
+
def parse_arguments(args)
|
84
85
|
total = @command.arguments.size
|
85
86
|
required = 0
|
86
87
|
optional = 0
|
@@ -99,25 +100,25 @@ class Mothership
|
|
99
100
|
|
100
101
|
@command.arguments.each do |arg|
|
101
102
|
name = arg[:name]
|
102
|
-
next if
|
103
|
+
next if @given.key? name
|
103
104
|
|
104
105
|
case arg[:type]
|
105
106
|
when :splat
|
106
|
-
|
107
|
+
@given[name] = []
|
107
108
|
|
108
109
|
until args.empty?
|
109
|
-
|
110
|
+
@given[name] << args.shift
|
110
111
|
end
|
111
112
|
|
112
113
|
when :optional
|
113
114
|
if parse_optionals > 0 && val = args.shift
|
114
|
-
|
115
|
+
@given[name] = val
|
115
116
|
parse_optionals -= 1
|
116
117
|
end
|
117
118
|
|
118
119
|
else
|
119
120
|
if val = args.shift
|
120
|
-
|
121
|
+
@given[name] = val
|
121
122
|
elsif !@command.inputs[name][:default]
|
122
123
|
raise MissingArgument.new(@command.name, name)
|
123
124
|
end
|
data/lib/mothership/version.rb
CHANGED
data/lib/mothership.rb
CHANGED
@@ -9,9 +9,6 @@ class Mothership
|
|
9
9
|
# [Mothership::Command] global options
|
10
10
|
@@global = Command.new(self, "(global options)")
|
11
11
|
|
12
|
-
# [Mothershp::Inputs] inputs from global options
|
13
|
-
@@inputs = Inputs.new(@@global)
|
14
|
-
|
15
12
|
# [Fixnum] exit status; reassign as appropriate error code (e.g. 1)
|
16
13
|
@@exit_status = 0
|
17
14
|
|
@@ -27,11 +24,8 @@ class Mothership
|
|
27
24
|
# arguments and flags can be in any order; all flags will be parsed out
|
28
25
|
# first, and the bits left over will be treated as arguments
|
29
26
|
def start(argv)
|
30
|
-
|
31
|
-
|
32
|
-
@@inputs.inputs,
|
33
|
-
argv,
|
34
|
-
@@commands)
|
27
|
+
global_parser = Parser.new(@@global)
|
28
|
+
name, *argv = global_parser.parse_flags(argv, @@commands)
|
35
29
|
|
36
30
|
app = new
|
37
31
|
|
@@ -42,7 +36,7 @@ class Mothership
|
|
42
36
|
cmd = @@commands[cmdname]
|
43
37
|
return app.unknown_command(cmdname) unless cmd
|
44
38
|
|
45
|
-
app.execute(cmd, argv)
|
39
|
+
app.execute(cmd, argv, global_parser.given)
|
46
40
|
|
47
41
|
code = @@exit_status
|
48
42
|
|
@@ -51,20 +45,14 @@ class Mothership
|
|
51
45
|
|
52
46
|
exit code
|
53
47
|
end
|
48
|
+
|
49
|
+
def global_option(name)
|
50
|
+
@@global.inputs[name]
|
51
|
+
end
|
54
52
|
end
|
55
53
|
|
56
54
|
# set the exit status
|
57
55
|
def exit_status(num)
|
58
56
|
@@exit_status = num
|
59
57
|
end
|
60
|
-
|
61
|
-
# get value of global option
|
62
|
-
def option(name, *args)
|
63
|
-
@@inputs.get(name, self, *args)
|
64
|
-
end
|
65
|
-
|
66
|
-
# test if an option was explicitly provided
|
67
|
-
def option_given?(name)
|
68
|
-
@@inputs.given? name
|
69
|
-
end
|
70
58
|
end
|
data/spec/helpers.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mothership
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.15
|
10
|
+
version: 0.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Alex Suraci
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-08-
|
18
|
+
date: 2012-08-22 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rake
|