boson 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 a --global option which takes a string of options without their dashes. For example:
27
- # foo '-p --fields=f1,f2 -l=1'
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 ' -g "p fields=f1,f2" -l=1 '
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 = Boson.const_defined?(:BinRunner) ? args : Shellwords.shellwords(args.pop)
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
- global_options = option_parser.parse @command.option_parser.leading_non_opts
128
- new_args = option_parser.non_opts.dup + @command.option_parser.trailing_non_opts
129
- if global_options[:global]
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.each {|k,v|
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 prepend_default_option(args)
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 ArgumentError, "wrong number of arguments (#{args_size} for #{command_size})"
198
+ raise CommandArgumentError, "wrong number of arguments (#{args_size} for #{command_size})"
185
199
  end
186
200
  end
187
201
 
@@ -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 a hash of
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
- (@opt_parser ||= new(options)).parse(args)
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
- # by the :split character. Defaults to first key of :keys if :keys given.
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. Default is false.
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}/ } or (@option_attributes[@current_option][:enum] ?
331
- raise(Error, "invalid value '#{possible_value}' for option '#{@current_option}'") : possible_value)
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
- [@trailing_non_opts].each do |args|
344
- args.delete_if {|e|
345
- invalid = e.to_s[/^-/]
346
- $stderr.puts "Deleted invalid option '#{e}'" if invalid
347
- invalid
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["--#{$1}"] == :boolean) or
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
- (val = auto_alias_value(values, value)) && value = val
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
- array.each {|e| array.delete(e) && array += values if e == '*'}
65
- array.each_with_index {|e,i|
66
- (value = auto_alias_value(values, e)) && array[i] = value
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 ? hash.each {|k,v|
83
- (new_key = auto_alias_value(keys, k)) && hash[new_key] = hash.delete(k)
84
- } : hash
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 description fields.
27
- # bash> boson commands -q=f,d:web # or commands --query=full_name,description:web
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.
@@ -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? ? Marshal.load(File.read(marshal_file)) : [[], [], {}]
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, 'w') {|f| f.write marshal_string }
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
- [Boson::Commands::Core, Boson::Commands::WebCore] + Boson.repos.map {|e| e.config[:defaults] || [] }.flatten
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
- Boson::Index.read
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
- :enum=>false, :desc=>"A comma delimited array of libraries to load"},
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 @options && @options[:verbose]
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
- render_output Boson.full_invoke(@command, @args)
109
- rescue ArgumentError
110
- # for the rare case it's raise outside of boson
111
- raise unless $!.backtrace.first.include?('boson/')
112
- print_error_message "'#{@command}' was called incorrectly."
113
- Boson.invoke(:usage, @command)
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)