boson 0.2.1 → 0.2.2
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/README.rdoc +1 -2
- data/VERSION.yml +3 -2
- data/lib/boson.rb +7 -2
- data/lib/boson/command.rb +72 -27
- data/lib/boson/commands/core.rb +25 -18
- data/lib/boson/commands/web_core.rb +2 -2
- data/lib/boson/index.rb +9 -3
- data/lib/boson/inspector.rb +1 -1
- data/lib/boson/inspectors/argument_inspector.rb +2 -2
- data/lib/boson/inspectors/method_inspector.rb +7 -0
- data/lib/boson/libraries/file_library.rb +5 -9
- data/lib/boson/library.rb +7 -3
- data/lib/boson/namespace.rb +1 -20
- data/lib/boson/option_command.rb +34 -20
- data/lib/boson/option_parser.rb +62 -26
- data/lib/boson/options.rb +18 -8
- data/lib/boson/pipe.rb +2 -2
- data/lib/boson/repo.rb +1 -1
- data/lib/boson/repo_index.rb +6 -5
- data/lib/boson/runner.rb +27 -4
- data/lib/boson/runners/bin_runner.rb +28 -17
- data/lib/boson/scientist.rb +49 -24
- data/lib/boson/view.rb +8 -0
- data/test/argument_inspector_test.rb +4 -0
- data/test/bin_runner_test.rb +2 -2
- data/test/file_library_test.rb +4 -2
- data/test/loader_test.rb +4 -4
- data/test/option_parser_test.rb +29 -2
- data/test/runner_test.rb +1 -1
- data/test/scientist_test.rb +22 -17
- metadata +2 -3
- data/test/config/index.marshal +0 -0
data/lib/boson/option_command.rb
CHANGED
@@ -23,10 +23,11 @@ module Boson
|
|
23
23
|
# Global options: {:pretend=>true}
|
24
24
|
#
|
25
25
|
# If a global option conflicts with a local option, the local option takes precedence. You can get around
|
26
|
-
# this by passing
|
27
|
-
#
|
26
|
+
# this by passing global options after a '-'. For example, if the global option -f (--fields) conflicts with
|
27
|
+
# a local -f (--force):
|
28
|
+
# foo 'arg1 -v -f - -f=f1,f2'
|
28
29
|
# # is the same as
|
29
|
-
# foo ' -
|
30
|
+
# foo 'arg1 -v --fields=f1,f2 -f'
|
30
31
|
#
|
31
32
|
# === Toggling Views With the Basic Global Option --render
|
32
33
|
# One of the more important global options is --render. This option toggles the rendering of a command's
|
@@ -53,12 +54,15 @@ module Boson
|
|
53
54
|
# 3 rows in set
|
54
55
|
# => true
|
55
56
|
class OptionCommand
|
57
|
+
# ArgumentError specific to @command's arguments
|
58
|
+
class CommandArgumentError < ::ArgumentError; end
|
59
|
+
|
56
60
|
BASIC_OPTIONS = {
|
57
61
|
:help=>{:type=>:boolean, :desc=>"Display a command's help"},
|
58
62
|
:render=>{:type=>:boolean, :desc=>"Toggle a command's default rendering behavior"},
|
59
63
|
:verbose=>{:type=>:boolean, :desc=>"Increase verbosity for help, errors, etc."},
|
60
|
-
:global=>{:type=>:string, :desc=>"Pass a string of global options without the dashes"},
|
61
64
|
:pretend=>{:type=>:boolean, :desc=>"Display what a command would execute without executing it"},
|
65
|
+
:delete_options=>{:type=>:array, :desc=>'Deletes global options starting with given strings' }
|
62
66
|
} #:nodoc:
|
63
67
|
|
64
68
|
RENDER_OPTIONS = {
|
@@ -106,9 +110,9 @@ module Boson
|
|
106
110
|
global_opt, parsed_options, args = parse_options Shellwords.shellwords(args[0])
|
107
111
|
# last string argument interpreted as args + options
|
108
112
|
elsif args.size > 1 && args[-1].is_a?(String)
|
109
|
-
temp_args =
|
113
|
+
temp_args = Runner.in_shell? ? args : Shellwords.shellwords(args.pop)
|
110
114
|
global_opt, parsed_options, new_args = parse_options temp_args
|
111
|
-
args += new_args
|
115
|
+
Runner.in_shell? ? args = new_args : args += new_args
|
112
116
|
# add default options
|
113
117
|
elsif @command.options.to_s.empty? || (!@command.has_splat_args? &&
|
114
118
|
args.size <= (@command.arg_size - 1).abs) || (@command.has_splat_args? && !args[-1].is_a?(Hash))
|
@@ -124,14 +128,28 @@ module Boson
|
|
124
128
|
#:stopdoc:
|
125
129
|
def parse_options(args)
|
126
130
|
parsed_options = @command.option_parser.parse(args, :delete_invalid_opts=>true)
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
global_opts = Shellwords.shellwords(global_options[:global]).map {|str|
|
131
|
-
((str[/^(.*?)=/,1] || str).length > 1 ? "--" : "-") + str }
|
132
|
-
global_options.merge! option_parser.parse(global_opts)
|
133
|
-
end
|
131
|
+
trailing, unparseable = split_trailing
|
132
|
+
global_options = parse_global_options @command.option_parser.leading_non_opts + trailing
|
133
|
+
new_args = option_parser.non_opts.dup + unparseable
|
134
134
|
[global_options, parsed_options, new_args]
|
135
|
+
rescue OptionParser::Error
|
136
|
+
global_options = parse_global_options @command.option_parser.leading_non_opts + split_trailing[0]
|
137
|
+
global_options[:help] ? [global_options, nil, []] : raise
|
138
|
+
end
|
139
|
+
|
140
|
+
def split_trailing
|
141
|
+
trailing = @command.option_parser.trailing_non_opts
|
142
|
+
if trailing[0] == '--'
|
143
|
+
trailing.shift
|
144
|
+
[ [], trailing ]
|
145
|
+
else
|
146
|
+
trailing.shift if trailing[0] == '-'
|
147
|
+
[ trailing, [] ]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def parse_global_options(args)
|
152
|
+
option_parser.parse args
|
135
153
|
end
|
136
154
|
|
137
155
|
def option_parser
|
@@ -140,11 +158,7 @@ module Boson
|
|
140
158
|
end
|
141
159
|
|
142
160
|
def all_global_options
|
143
|
-
@command.render_options
|
144
|
-
if !v.is_a?(Hash) && !v.is_a?(Symbol)
|
145
|
-
@command.render_options[k] = {:default=>v}
|
146
|
-
end
|
147
|
-
}
|
161
|
+
OptionParser.make_mergeable! @command.render_options
|
148
162
|
render_opts = Util.recursive_hash_merge(@command.render_options, Util.deep_copy(self.class.default_render_options))
|
149
163
|
merged_opts = Util.recursive_hash_merge Util.deep_copy(self.class.default_pipe_options), render_opts
|
150
164
|
opts = Util.recursive_hash_merge merged_opts, Util.deep_copy(BASIC_OPTIONS)
|
@@ -171,7 +185,7 @@ module Boson
|
|
171
185
|
opts
|
172
186
|
end
|
173
187
|
|
174
|
-
def
|
188
|
+
def modify_args(args)
|
175
189
|
if @command.default_option && @command.arg_size <= 1 && !@command.has_splat_args? && args[0].to_s[/./] != '-'
|
176
190
|
args[0] = "--#{@command.default_option}=#{args[0]}" unless args.join.empty? || args[0].is_a?(Hash)
|
177
191
|
end
|
@@ -181,7 +195,7 @@ module Boson
|
|
181
195
|
if args.size != @command.arg_size && !@command.has_splat_args?
|
182
196
|
command_size, args_size = args.size > @command.arg_size ? [@command.arg_size, args.size] :
|
183
197
|
[@command.arg_size - 1, args.size - 1]
|
184
|
-
raise
|
198
|
+
raise CommandArgumentError, "wrong number of arguments (#{args_size} for #{command_size})"
|
185
199
|
end
|
186
200
|
end
|
187
201
|
|
data/lib/boson/option_parser.rb
CHANGED
@@ -3,7 +3,7 @@ module Boson
|
|
3
3
|
# merging should assume symbolic keys. Used by OptionParser.
|
4
4
|
class IndifferentAccessHash < ::Hash
|
5
5
|
#:stopdoc:
|
6
|
-
def initialize(hash)
|
6
|
+
def initialize(hash={})
|
7
7
|
super()
|
8
8
|
hash.each {|k,v| self[k] = v }
|
9
9
|
end
|
@@ -37,6 +37,7 @@ module Boson
|
|
37
37
|
# * Each option type can have attributes to enable more features (see OptionParser.new).
|
38
38
|
# * When options are parsed by parse(), an IndifferentAccessHash hash is returned.
|
39
39
|
# * Options are also called switches, parameters, flags etc.
|
40
|
+
# * Option parsing stops when it comes across a '--'.
|
40
41
|
#
|
41
42
|
# Default option types:
|
42
43
|
# [*:boolean*] This option has no passed value. To toogle a boolean, prepend with '--no-'.
|
@@ -79,10 +80,12 @@ module Boson
|
|
79
80
|
|
80
81
|
attr_reader :leading_non_opts, :trailing_non_opts, :opt_aliases
|
81
82
|
|
82
|
-
# Given options to pass to OptionParser.new, this method parses ARGV and returns
|
83
|
-
# parsed options. This is useful for scripts outside of Boson.
|
83
|
+
# Given options to pass to OptionParser.new, this method parses ARGV and returns the remaining arguments
|
84
|
+
# and a hash of parsed options. This is useful for scripts outside of Boson.
|
84
85
|
def self.parse(options, args=ARGV)
|
85
|
-
|
86
|
+
@opt_parser ||= new(options)
|
87
|
+
parsed_options = @opt_parser.parse(args)
|
88
|
+
[@opt_parser.non_opts, parsed_options]
|
86
89
|
end
|
87
90
|
|
88
91
|
# Usage string summarizing options defined in parse
|
@@ -90,6 +93,14 @@ module Boson
|
|
90
93
|
@opt_parser.to_s
|
91
94
|
end
|
92
95
|
|
96
|
+
def self.make_mergeable!(opts) #:nodoc:
|
97
|
+
opts.each {|k,v|
|
98
|
+
if !v.is_a?(Hash) && !v.is_a?(Symbol)
|
99
|
+
opts[k] = {:default=>v}
|
100
|
+
end
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
93
104
|
# Array of arguments left after defined options have been parsed out by parse.
|
94
105
|
def non_opts
|
95
106
|
leading_non_opts + trailing_non_opts
|
@@ -145,8 +156,11 @@ module Boson
|
|
145
156
|
# [*:split*] For :array and :hash options. A string or regular expression on which an array value splits
|
146
157
|
# to produce an array of values. Default is ','.
|
147
158
|
# [*:keys*] :hash option only. An array of values a hash option's keys can have. Keys can be aliased just like :values.
|
148
|
-
# [*:default_keys*] :hash option only. Default keys to assume when only a value is given. Multiple keys can be joined
|
149
|
-
#
|
159
|
+
# [*:default_keys*] For :hash option only. Default keys to assume when only a value is given. Multiple keys can be joined
|
160
|
+
# by the :split character. Defaults to first key of :keys if :keys given.
|
161
|
+
# [*:regexp*] For :array option with a :values attribute. Boolean indicating that each option value does a regular
|
162
|
+
# expression search of :values. If there are values that match, they replace the original option value. If none,
|
163
|
+
# then the original option value is used.
|
150
164
|
def initialize(opts)
|
151
165
|
@defaults = {}
|
152
166
|
@opt_aliases = {}
|
@@ -209,7 +223,8 @@ module Boson
|
|
209
223
|
# recognizes a valid option, it continues to parse until an non option argument is detected.
|
210
224
|
# Flags that can be passed to the parser:
|
211
225
|
# * :opts_before_args: When true options must come before arguments. Default is false.
|
212
|
-
# * :delete_invalid_opts: When true deletes any invalid options left after parsing.
|
226
|
+
# * :delete_invalid_opts: When true deletes any invalid options left after parsing. Will stop deleting if
|
227
|
+
# it comes across - or --. Default is false.
|
213
228
|
def parse(args, flags={})
|
214
229
|
@args = args
|
215
230
|
# start with defaults
|
@@ -217,7 +232,7 @@ module Boson
|
|
217
232
|
|
218
233
|
@leading_non_opts = []
|
219
234
|
unless flags[:opts_before_args]
|
220
|
-
@leading_non_opts << shift until current_is_option? || @args.empty?
|
235
|
+
@leading_non_opts << shift until current_is_option? || @args.empty? || peek == '--'
|
221
236
|
end
|
222
237
|
|
223
238
|
while current_is_option?
|
@@ -299,6 +314,29 @@ module Boson
|
|
299
314
|
(str.length > 1 ? "--" : "-") + str
|
300
315
|
end
|
301
316
|
|
317
|
+
# List of option types
|
318
|
+
def types
|
319
|
+
@opt_types.values
|
320
|
+
end
|
321
|
+
|
322
|
+
# List of option names
|
323
|
+
def names
|
324
|
+
@opt_types.keys.map {|e| undasherize e }
|
325
|
+
end
|
326
|
+
|
327
|
+
# List of option aliases
|
328
|
+
def aliases
|
329
|
+
@opt_aliases.keys.map {|e| undasherize e }
|
330
|
+
end
|
331
|
+
|
332
|
+
def option_type(opt)
|
333
|
+
if opt =~ /^--no-(\w+)$/
|
334
|
+
@opt_types[opt] || @opt_types[dasherize($1)] || @opt_types[original_no_opt($1)]
|
335
|
+
else
|
336
|
+
@opt_types[opt]
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
302
340
|
private
|
303
341
|
def determine_option_type(value)
|
304
342
|
return value if value.is_a?(Symbol)
|
@@ -327,8 +365,15 @@ module Boson
|
|
327
365
|
end
|
328
366
|
|
329
367
|
def auto_alias_value(values, possible_value)
|
330
|
-
values.find {|v| v.to_s =~ /^#{possible_value}/ }
|
331
|
-
|
368
|
+
values.find {|v| v.to_s =~ /^#{possible_value}/ } || possible_value
|
369
|
+
end
|
370
|
+
|
371
|
+
def validate_enum_values(values, possible_values)
|
372
|
+
if current_attributes[:enum]
|
373
|
+
Array(possible_values).each {|e|
|
374
|
+
raise(Error, "invalid value '#{e}' for option '#{@current_option}'") if !values.include?(e)
|
375
|
+
}
|
376
|
+
end
|
332
377
|
end
|
333
378
|
|
334
379
|
def validate_option_value(type)
|
@@ -340,13 +385,12 @@ module Boson
|
|
340
385
|
end
|
341
386
|
|
342
387
|
def delete_invalid_opts
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
end
|
388
|
+
@trailing_non_opts.delete_if {|e|
|
389
|
+
break if %w{- --}.include? e
|
390
|
+
invalid = e.to_s[/^-/]
|
391
|
+
$stderr.puts "Deleted invalid option '#{e}'" if invalid
|
392
|
+
invalid
|
393
|
+
}
|
350
394
|
end
|
351
395
|
|
352
396
|
def peek
|
@@ -367,7 +411,7 @@ module Boson
|
|
367
411
|
|
368
412
|
def valid?(arg)
|
369
413
|
if arg.to_s =~ /^--no-(\w+)$/
|
370
|
-
@opt_types.key?(arg) or (@opt_types[
|
414
|
+
@opt_types.key?(arg) or (@opt_types[dasherize($1)] == :boolean) or
|
371
415
|
(@opt_types[original_no_opt($1)] == :boolean)
|
372
416
|
else
|
373
417
|
@opt_types.key?(arg) or @opt_aliases.key?(arg)
|
@@ -387,14 +431,6 @@ module Boson
|
|
387
431
|
@opt_aliases.key?(opt) ? @opt_aliases[opt] : opt
|
388
432
|
end
|
389
433
|
|
390
|
-
def option_type(opt)
|
391
|
-
if opt =~ /^--no-(\w+)$/
|
392
|
-
@opt_types[opt] || @opt_types["--#{$1}"] || @opt_types[original_no_opt($1)]
|
393
|
-
else
|
394
|
-
@opt_types[opt]
|
395
|
-
end
|
396
|
-
end
|
397
|
-
|
398
434
|
def original_no_opt(opt)
|
399
435
|
@opt_aliases[dasherize(opt)]
|
400
436
|
end
|
data/lib/boson/options.rb
CHANGED
@@ -39,7 +39,8 @@ module Boson
|
|
39
39
|
# Parse/create methods
|
40
40
|
def create_string(value)
|
41
41
|
if (values = current_attributes[:values]) && (values = values.sort_by {|e| e.to_s})
|
42
|
-
|
42
|
+
value = auto_alias_value(values, value)
|
43
|
+
validate_enum_values(values, value)
|
43
44
|
end
|
44
45
|
value
|
45
46
|
end
|
@@ -61,10 +62,15 @@ module Boson
|
|
61
62
|
splitter = current_attributes[:split] || ','
|
62
63
|
array = value.split(splitter)
|
63
64
|
if (values = current_attributes[:values]) && (values = values.sort_by {|e| e.to_s })
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
if current_attributes[:regexp]
|
66
|
+
array = array.map {|e|
|
67
|
+
(new_values = values.grep(/#{e}/)).empty? ? e : new_values
|
68
|
+
}.compact.flatten.uniq
|
69
|
+
else
|
70
|
+
array.each {|e| array.delete(e) && array += values if e == '*'}
|
71
|
+
array.map! {|e| auto_alias_value(values, e) }
|
72
|
+
end
|
73
|
+
validate_enum_values(values, array)
|
68
74
|
end
|
69
75
|
array
|
70
76
|
end
|
@@ -79,9 +85,13 @@ module Boson
|
|
79
85
|
aoa = Hash[*value.split(/(?::)([^#{Regexp.quote(splitter)}]+)#{Regexp.quote(splitter)}?/)].to_a
|
80
86
|
aoa.each_with_index {|(k,v),i| aoa[i][0] = keys.join(splitter) if k == '*' } if keys
|
81
87
|
hash = aoa.inject({}) {|t,(k,v)| k.split(splitter).each {|e| t[e] = v }; t }
|
82
|
-
keys
|
83
|
-
|
84
|
-
|
88
|
+
if keys
|
89
|
+
hash = hash.inject({}) {|h,(k,v)|
|
90
|
+
h[auto_alias_value(keys, k)] = v; h
|
91
|
+
}
|
92
|
+
validate_enum_values(keys, hash.keys)
|
93
|
+
end
|
94
|
+
hash
|
85
95
|
end
|
86
96
|
|
87
97
|
# Validation methods
|
data/lib/boson/pipe.rb
CHANGED
@@ -23,8 +23,8 @@ module Boson
|
|
23
23
|
# # Searches commands in the full_name field for 'lib' and sorts results by that field.
|
24
24
|
# bash> boson commands -q=f:lib -s=f # or commands --query=full_name:lib --sort=full_name
|
25
25
|
#
|
26
|
-
# # Multiple fields can be searched if separated by a ','. This searches the full_name and
|
27
|
-
# bash> boson commands -q=f,d:web # or commands --query=full_name,
|
26
|
+
# # Multiple fields can be searched if separated by a ','. This searches the full_name and desc fields.
|
27
|
+
# bash> boson commands -q=f,d:web # or commands --query=full_name,desc:web
|
28
28
|
#
|
29
29
|
# # All fields can be queried using a '*'.
|
30
30
|
# # Searches all library fields and then reverse sorts on name field
|
data/lib/boson/repo.rb
CHANGED
@@ -46,7 +46,7 @@ module Boson
|
|
46
46
|
# Example:
|
47
47
|
# :command_aliases=>{'libraries'=>'lib', 'commands'=>'com'}
|
48
48
|
# [:defaults] Array of libraries to load at start up for commandline and irb. This is useful for extending boson i.e. adding your
|
49
|
-
# own option types. Default is no libraries.
|
49
|
+
# own option types since these are loaded before any other libraries. Default is no libraries.
|
50
50
|
# [:console_defaults] Array of libraries to load at start up when used in irb. Default is to load all library files and libraries
|
51
51
|
# defined in the config.
|
52
52
|
# [:bin_defaults] Array of libraries to load at start up when used from the commandline. Default is no libraries.
|
data/lib/boson/repo_index.rb
CHANGED
@@ -34,7 +34,8 @@ module Boson
|
|
34
34
|
# Reads and initializes index.
|
35
35
|
def read
|
36
36
|
return if @read
|
37
|
-
@libraries, @commands, @lib_hashes = exists? ?
|
37
|
+
@libraries, @commands, @lib_hashes = exists? ?
|
38
|
+
File.open( marshal_file, 'rb' ){|f| Marshal.load( f.read ) } : [[], [], {}]
|
38
39
|
delete_stale_libraries_and_commands
|
39
40
|
set_command_namespaces
|
40
41
|
@read = true
|
@@ -62,7 +63,7 @@ module Boson
|
|
62
63
|
end
|
63
64
|
|
64
65
|
def save_marshal_index(marshal_string)
|
65
|
-
File.open(marshal_file, '
|
66
|
+
File.open(marshal_file, 'wb') {|f| f.write marshal_string }
|
66
67
|
end
|
67
68
|
|
68
69
|
def delete_stale_libraries_and_commands
|
@@ -96,13 +97,13 @@ module Boson
|
|
96
97
|
File.join(repo.config_dir, 'index.marshal')
|
97
98
|
end
|
98
99
|
|
99
|
-
def find_library(command)
|
100
|
+
def find_library(command, object=false)
|
100
101
|
read
|
101
102
|
namespace_command = command.split('.')[0]
|
102
103
|
if (lib = @libraries.find {|e| e.namespace == namespace_command })
|
103
|
-
lib.name
|
104
|
+
object ? lib : lib.name
|
104
105
|
elsif (cmd = Command.find(command, @commands))
|
105
|
-
cmd.lib
|
106
|
+
object ? @libraries.find {|e| e.name == cmd.lib} : cmd.lib
|
106
107
|
end
|
107
108
|
end
|
108
109
|
|
data/lib/boson/runner.rb
CHANGED
@@ -11,7 +11,7 @@ module Boson
|
|
11
11
|
|
12
12
|
# Libraries that come with Boson
|
13
13
|
def default_libraries
|
14
|
-
|
14
|
+
Boson.repos.map {|e| e.config[:defaults] || [] }.flatten + [Boson::Commands::Core, Boson::Commands::WebCore]
|
15
15
|
end
|
16
16
|
|
17
17
|
# Libraries detected in repositories
|
@@ -24,7 +24,26 @@ module Boson
|
|
24
24
|
Boson.repos.map {|e| e.all_libraries }.flatten.uniq
|
25
25
|
end
|
26
26
|
|
27
|
+
# Returns true if commands are being executed from a non-ruby shell i.e. bash. Returns false if
|
28
|
+
# in a ruby shell i.e. irb.
|
29
|
+
def in_shell?
|
30
|
+
!!@in_shell
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns true if in commandline with verbose flag or if set explicitly. Useful in plugins.
|
34
|
+
def verbose?
|
35
|
+
@verbose.nil? ? Boson.const_defined?(:BinRunner) && BinRunner.options[:verbose] : @verbose
|
36
|
+
end
|
37
|
+
|
27
38
|
#:stopdoc:
|
39
|
+
def verbose=(val)
|
40
|
+
@verbose = val
|
41
|
+
end
|
42
|
+
|
43
|
+
def in_shell=(val)
|
44
|
+
@in_shell = val
|
45
|
+
end
|
46
|
+
|
28
47
|
def add_load_path
|
29
48
|
Boson.repos.each {|repo|
|
30
49
|
if repo.config[:add_load_path] || File.exists?(File.join(repo.dir, 'lib'))
|
@@ -37,12 +56,16 @@ module Boson
|
|
37
56
|
{:verbose=>@options[:verbose]}
|
38
57
|
end
|
39
58
|
|
59
|
+
def autoload_command(cmd)
|
60
|
+
Index.read
|
61
|
+
(lib = Index.find_library(cmd)) && Manager.load(lib, :verbose=>verbose?)
|
62
|
+
lib
|
63
|
+
end
|
64
|
+
|
40
65
|
def define_autoloader
|
41
66
|
class << ::Boson.main_object
|
42
67
|
def method_missing(method, *args, &block)
|
43
|
-
|
44
|
-
if lib = Boson::Index.find_library(method.to_s)
|
45
|
-
Boson::Manager.load lib, :verbose=>true
|
68
|
+
if Runner.autoload_command(method.to_s)
|
46
69
|
send(method, *args, &block) if respond_to?(method)
|
47
70
|
else
|
48
71
|
super
|
@@ -32,25 +32,24 @@ module Boson
|
|
32
32
|
# * Any of these cases can be toggled to render/not render with the global option :render
|
33
33
|
# To turn off auto-rendering by default, add a :no_auto_render: true entry to the main config.
|
34
34
|
class BinRunner < Runner
|
35
|
-
def self.all_libraries #:nodoc:
|
36
|
-
@all_libraries ||= ((libs = super) + libs.map {|e| File.basename(e) }).uniq
|
37
|
-
end
|
38
|
-
|
39
35
|
GLOBAL_OPTIONS = {
|
40
|
-
:verbose=>{:type=>:boolean, :desc=>"Verbose description of loading libraries or help"},
|
36
|
+
:verbose=>{:type=>:boolean, :desc=>"Verbose description of loading libraries, errors or help"},
|
41
37
|
:index=>{:type=>:array, :desc=>"Libraries to index. Libraries must be passed with '='.",
|
42
|
-
:bool_default=>nil, :values=>all_libraries, :enum=>false},
|
38
|
+
:bool_default=>nil, :values=>all_libraries, :regexp=>true, :enum=>false},
|
43
39
|
:execute=>{:type=>:string, :desc=>"Executes given arguments as a one line script"},
|
44
40
|
:console=>{:type=>:boolean, :desc=>"Drops into irb with default and explicit libraries loaded"},
|
45
41
|
:help=>{:type=>:boolean, :desc=>"Displays this help message or a command's help if given a command"},
|
46
|
-
:load=>{:type=>:array, :values=>all_libraries,
|
47
|
-
:
|
42
|
+
:load=>{:type=>:array, :values=>all_libraries, :regexp=>true, :enum=>false,
|
43
|
+
:desc=>"A comma delimited array of libraries to load"},
|
44
|
+
:unload=>{:type=>:string, :desc=>"Acts as a regular expression to unload default libraries"},
|
48
45
|
:render=>{:type=>:boolean, :desc=>"Renders a Hirb view from result of command without options"},
|
49
|
-
:pager_toggle=>{:type=>:boolean, :desc=>"Toggles Hirb's pager"}
|
46
|
+
:pager_toggle=>{:type=>:boolean, :desc=>"Toggles Hirb's pager"},
|
47
|
+
:option_commands=>{:type=>:boolean, :desc=>"Toggles on all commands to be defined as option commands" }
|
50
48
|
} #:nodoc:
|
51
49
|
|
52
50
|
class <<self
|
53
51
|
attr_accessor :command
|
52
|
+
|
54
53
|
# Starts, processes and ends a commandline request.
|
55
54
|
def start(args=ARGV)
|
56
55
|
@command, @options, @args = parse_args(args)
|
@@ -75,6 +74,8 @@ module Boson
|
|
75
74
|
|
76
75
|
# Loads the given command.
|
77
76
|
def init
|
77
|
+
Runner.in_shell = true
|
78
|
+
Command.all_option_commands = true if @options[:option_commands]
|
78
79
|
super
|
79
80
|
Index.update(:verbose=>true, :libraries=>@options[:index]) if @options.key?(:index)
|
80
81
|
if @options[:load]
|
@@ -86,9 +87,14 @@ module Boson
|
|
86
87
|
end
|
87
88
|
end
|
88
89
|
|
90
|
+
# Hash of global options passed in from commandline
|
91
|
+
def options
|
92
|
+
@options ||= {}
|
93
|
+
end
|
94
|
+
|
89
95
|
#:stopdoc:
|
90
96
|
def print_error_message(message)
|
91
|
-
message += "\nOriginal error: #{$!}\n" + $!.backtrace.slice(0,10).map {|e| " " + e }.join("\n") if
|
97
|
+
message += "\nOriginal error: #{$!}\n" + $!.backtrace.slice(0,10).map {|e| " " + e }.join("\n") if options[:verbose]
|
92
98
|
$stderr.puts message
|
93
99
|
end
|
94
100
|
|
@@ -101,16 +107,21 @@ module Boson
|
|
101
107
|
end
|
102
108
|
|
103
109
|
def default_libraries
|
104
|
-
super + Boson.repos.map {|e| e.config[:bin_defaults] || [] }.flatten + Dir.glob('Bosonfile')
|
110
|
+
libs = super + Boson.repos.map {|e| e.config[:bin_defaults] || [] }.flatten + Dir.glob('Bosonfile')
|
111
|
+
@options[:unload] ? libs.select {|e| e !~ /#{@options[:unload]}/} : libs
|
105
112
|
end
|
106
113
|
|
107
114
|
def execute_command
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
115
|
+
begin
|
116
|
+
output = Boson.full_invoke(@command, @args)
|
117
|
+
rescue ArgumentError
|
118
|
+
# for the rare case it's raised outside of boson
|
119
|
+
raise unless $!.backtrace.first.include?('boson/')
|
120
|
+
print_error_message "'#{@command}' was called incorrectly."
|
121
|
+
Boson.invoke(:usage, @command)
|
122
|
+
return
|
123
|
+
end
|
124
|
+
render_output output
|
114
125
|
end
|
115
126
|
|
116
127
|
def parse_args(args)
|