boson 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +21 -14
- data/VERSION.yml +1 -1
- data/lib/boson.rb +5 -5
- data/lib/boson/command.rb +20 -21
- data/lib/boson/commands/core.rb +5 -6
- data/lib/boson/index.rb +21 -98
- data/lib/boson/inspector.rb +28 -2
- data/lib/boson/inspectors/comment_inspector.rb +5 -7
- data/lib/boson/inspectors/method_inspector.rb +4 -17
- data/lib/boson/libraries/file_library.rb +22 -27
- data/lib/boson/libraries/local_file_library.rb +30 -0
- data/lib/boson/libraries/module_library.rb +1 -1
- data/lib/boson/library.rb +15 -9
- data/lib/boson/loader.rb +3 -18
- data/lib/boson/manager.rb +4 -31
- data/lib/boson/option_command.rb +204 -0
- data/lib/boson/option_parser.rb +13 -2
- data/lib/boson/options.rb +1 -1
- data/lib/boson/pipe.rb +157 -0
- data/lib/boson/repo.rb +20 -1
- data/lib/boson/repo_index.rb +123 -0
- data/lib/boson/runner.rb +3 -4
- data/lib/boson/runners/bin_runner.rb +23 -8
- data/lib/boson/runners/console_runner.rb +1 -2
- data/lib/boson/scientist.rb +48 -225
- data/lib/boson/view.rb +50 -64
- data/test/bin_runner_test.rb +48 -7
- data/test/comment_inspector_test.rb +7 -6
- data/test/config/index.marshal +0 -0
- data/test/file_library_test.rb +1 -22
- data/test/loader_test.rb +5 -13
- data/test/manager_test.rb +4 -4
- data/test/method_inspector_test.rb +7 -2
- data/test/{view_test.rb → pipe_test.rb} +11 -11
- data/test/{index_test.rb → repo_index_test.rb} +26 -26
- data/test/scientist_test.rb +2 -2
- metadata +11 -6
@@ -0,0 +1,30 @@
|
|
1
|
+
# This class loads any local file and is most commonly used to load a local
|
2
|
+
# Bosonfile. Since this file doesn't exist inside a normal Repo, it is not indexed with any repo.
|
3
|
+
# Since file-based libraries need to be associated with a repository, Boson associates it
|
4
|
+
# with a local repository if it exists or defaults to Boson.repo. See Boson::FileLibrary
|
5
|
+
# for more info about this library.
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
# >> load_library 'Bosonfile'
|
9
|
+
# => true
|
10
|
+
class Boson::LocalFileLibrary < Boson::FileLibrary
|
11
|
+
handles {|source|
|
12
|
+
@repo = (File.exists?(source.to_s) ? (Boson.local_repo || Boson.repo) : nil)
|
13
|
+
!!@repo
|
14
|
+
}
|
15
|
+
|
16
|
+
#:stopdoc:
|
17
|
+
def set_name(name)
|
18
|
+
@lib_file = File.expand_path(name.to_s)
|
19
|
+
File.basename(@lib_file).downcase
|
20
|
+
end
|
21
|
+
|
22
|
+
def base_module
|
23
|
+
Boson::Commands
|
24
|
+
end
|
25
|
+
|
26
|
+
def library_file
|
27
|
+
@lib_file
|
28
|
+
end
|
29
|
+
#:startdoc:
|
30
|
+
end
|
@@ -24,7 +24,7 @@ module Boson
|
|
24
24
|
def set_name(name)
|
25
25
|
@module = name
|
26
26
|
underscore_lib = name.to_s[/^Boson::Commands/] ? name.to_s.split('::')[-1] : name.to_s
|
27
|
-
|
27
|
+
Util.underscore(underscore_lib)
|
28
28
|
end
|
29
29
|
|
30
30
|
def initialize_library_module
|
data/lib/boson/library.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Boson
|
2
2
|
# A library is a group of commands (Command objects) usually grouped together by a module.
|
3
3
|
# Libraries are loaded from different sources depending on the library subclass. Default library
|
4
|
-
# subclasses are FileLibrary, GemLibrary, RequireLibrary and
|
4
|
+
# subclasses are FileLibrary, GemLibrary, RequireLibrary, ModuleLibrary and LocalFileLibrary.
|
5
5
|
# See Loader for callbacks a library's module can have.
|
6
6
|
#
|
7
7
|
# == Naming a Library Module
|
@@ -15,12 +15,15 @@ module Boson
|
|
15
15
|
# over the top level module and the top level module has to be prefixed with '::' _everywhere_.
|
16
16
|
#
|
17
17
|
# == Configuration
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# you can
|
21
|
-
#
|
22
|
-
# :libraries:
|
23
|
-
#
|
18
|
+
# Libraries and their commands can be configured in different ways in this order:
|
19
|
+
# * If library is a FileLibrary, commands be configured with a config method attribute (see Inspector).
|
20
|
+
# * If a library has a module, you can set library + command attributes via the config() callback (see Loader).
|
21
|
+
# * All libraries can be configured by passing a hash of {library attributes}[link:classes/Boson/Library.html#M000077] under
|
22
|
+
# {the :libraries key}[link:classes/Boson/Repo.html#M000070] to the main config file ~/.boson/config/boson.yml.
|
23
|
+
# For most libraries this may be the only way to configure a library's commands.
|
24
|
+
# An example of a GemLibrary config:
|
25
|
+
# :libraries:
|
26
|
+
# httparty:
|
24
27
|
# :class_commands:
|
25
28
|
# delete: HTTParty.delete
|
26
29
|
# :commands:
|
@@ -28,6 +31,9 @@ module Boson
|
|
28
31
|
# :alias: d
|
29
32
|
# :description: Http delete a given url
|
30
33
|
#
|
34
|
+
# When installing a third-party library, use the config file as a way to override default library and command attributes
|
35
|
+
# without modifying the library.
|
36
|
+
#
|
31
37
|
# === Creating Your Own Library
|
32
38
|
# To create your own subclass you need to define what sources the subclass can handle with handles().
|
33
39
|
# If handles() returns true then the subclass is chosen to load. See Loader to see what instance methods
|
@@ -81,7 +87,7 @@ module Boson
|
|
81
87
|
def initialize(hash)
|
82
88
|
repo = set_repo
|
83
89
|
@repo_dir = repo.dir
|
84
|
-
@name = set_name
|
90
|
+
@name = set_name(hash.delete(:name)) or raise ArgumentError, "Library missing required key :name"
|
85
91
|
@loaded = false
|
86
92
|
@commands_hash = {}
|
87
93
|
@commands = []
|
@@ -117,7 +123,7 @@ module Boson
|
|
117
123
|
end
|
118
124
|
|
119
125
|
def set_name(name)
|
120
|
-
name.to_s
|
126
|
+
name.to_s
|
121
127
|
end
|
122
128
|
|
123
129
|
def set_config(config, force=false)
|
data/lib/boson/loader.rb
CHANGED
@@ -2,9 +2,9 @@ module Boson
|
|
2
2
|
# Raised if a library has a method which conflicts with existing methods in Boson.main_object.
|
3
3
|
class MethodConflictError < LoaderError; end
|
4
4
|
|
5
|
-
# This module is mixed into Library to give it load()
|
6
|
-
# When creating your own Library subclass, you should override load_source_and_set_module
|
7
|
-
#
|
5
|
+
# This module is mixed into Library to give it load() functionality.
|
6
|
+
# When creating your own Library subclass, you should override load_source_and_set_module
|
7
|
+
# You can override other methods in this module as needed.
|
8
8
|
#
|
9
9
|
# === Module Callbacks
|
10
10
|
# For libraries that have a module i.e. FileLibrary and GemLibrary, the following class methods
|
@@ -47,21 +47,6 @@ module Boson
|
|
47
47
|
!!@module
|
48
48
|
end
|
49
49
|
|
50
|
-
# Reloads a library from its source and adds new commands. Only implemented
|
51
|
-
# for FileLibrary for now.
|
52
|
-
def reload
|
53
|
-
original_commands = @commands
|
54
|
-
reload_source_and_set_module
|
55
|
-
detect_additions { load_module_commands } if @new_module
|
56
|
-
@new_commands = @commands - original_commands
|
57
|
-
true
|
58
|
-
end
|
59
|
-
|
60
|
-
# Same as load_source_and_set_module except it reloads.
|
61
|
-
def reload_source_and_set_module
|
62
|
-
raise LoaderError, "Reload not implemented"
|
63
|
-
end
|
64
|
-
|
65
50
|
#:stopdoc:
|
66
51
|
def module_callbacks
|
67
52
|
set_config(@module.config) if @module.respond_to?(:config)
|
data/lib/boson/manager.rb
CHANGED
@@ -4,7 +4,7 @@ module Boson
|
|
4
4
|
# Raised when a library's append_features returns false.
|
5
5
|
class AppendFeaturesFalseError < StandardError; end
|
6
6
|
|
7
|
-
# Handles loading
|
7
|
+
# Handles loading of libraries and commands.
|
8
8
|
class Manager
|
9
9
|
class <<self
|
10
10
|
attr_accessor :failed_libraries
|
@@ -23,28 +23,6 @@ module Boson
|
|
23
23
|
}.all?
|
24
24
|
end
|
25
25
|
|
26
|
-
# Reloads a library or an array of libraries with the following options:
|
27
|
-
# * :verbose: Boolean to print reload status. Default is false.
|
28
|
-
def reload(source, options={})
|
29
|
-
if (lib = Boson.library(source))
|
30
|
-
if lib.loaded
|
31
|
-
command_size = Boson.commands.size
|
32
|
-
@options = options
|
33
|
-
if (result = rescue_load_action(lib.name, :reload) { lib.reload })
|
34
|
-
after_reload(lib)
|
35
|
-
puts "Reloaded library #{source}: Added #{Boson.commands.size - command_size} commands" if options[:verbose]
|
36
|
-
end
|
37
|
-
result
|
38
|
-
else
|
39
|
-
puts "Library hasn't been loaded yet. Loading library #{source}..." if options[:verbose]
|
40
|
-
load(source, options)
|
41
|
-
end
|
42
|
-
else
|
43
|
-
puts "Library #{source} doesn't exist." if options[:verbose]
|
44
|
-
false
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
26
|
#:stopdoc:
|
49
27
|
def failed_libraries
|
50
28
|
@failed_libraries ||= []
|
@@ -123,11 +101,6 @@ module Boson
|
|
123
101
|
true
|
124
102
|
end
|
125
103
|
|
126
|
-
def after_reload(lib)
|
127
|
-
Boson.commands.delete_if {|e| e.lib == lib.name } if lib.new_module
|
128
|
-
create_commands(lib, lib.new_commands)
|
129
|
-
end
|
130
|
-
|
131
104
|
def before_create_commands(lib)
|
132
105
|
lib.is_a?(FileLibrary) && lib.module && Inspector.add_method_data_to_library(lib)
|
133
106
|
end
|
@@ -136,17 +109,17 @@ module Boson
|
|
136
109
|
before_create_commands(lib)
|
137
110
|
commands.each {|e| Boson.commands << Command.create(e, lib)}
|
138
111
|
create_command_aliases(lib, commands) if commands.size > 0 && !lib.no_alias_creation
|
139
|
-
|
112
|
+
redefine_commands(lib, commands)
|
140
113
|
end
|
141
114
|
|
142
|
-
def
|
115
|
+
def redefine_commands(lib, commands)
|
143
116
|
option_commands = lib.command_objects(commands).select {|e| e.option_command? }
|
144
117
|
accepted, rejected = option_commands.partition {|e| e.args(lib) || e.arg_size }
|
145
118
|
if @options[:verbose] && rejected.size > 0
|
146
119
|
puts "Following commands cannot have options until their arguments are configured: " +
|
147
120
|
rejected.map {|e| e.name}.join(', ')
|
148
121
|
end
|
149
|
-
accepted.each {|cmd| Scientist.
|
122
|
+
accepted.each {|cmd| Scientist.redefine_command(lib.namespace_object, cmd) }
|
150
123
|
end
|
151
124
|
|
152
125
|
def create_command_aliases(lib, commands)
|
@@ -0,0 +1,204 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
module Boson
|
3
|
+
# A class used by Scientist to wrap around Command objects. It's main purpose is to parse
|
4
|
+
# a command's global options (basic options, render options, pipe options) and local options.
|
5
|
+
# As the names imply, global options are available to all commands while local options are specific to a command.
|
6
|
+
# When passing options to commands, global ones _must_ be passed first, then local ones.
|
7
|
+
# For more about pipe and render options see Pipe and View respectively.
|
8
|
+
#
|
9
|
+
# === Basic Global Options
|
10
|
+
# Any command with options comes with basic global options. For example '-hv' on an option command
|
11
|
+
# prints a help summarizing global and local options. Another basic global option is --pretend. This
|
12
|
+
# option displays what global options have been parsed and the actual arguments to be passed to a
|
13
|
+
# command if executed. For example:
|
14
|
+
#
|
15
|
+
# # Define this command in a library
|
16
|
+
# options :level=>:numeric, :verbose=>:boolean
|
17
|
+
# def foo(*args)
|
18
|
+
# args
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# irb>> foo 'testin -p -l=1'
|
22
|
+
# Arguments: ["testin", {:level=>1}]
|
23
|
+
# Global options: {:pretend=>true}
|
24
|
+
#
|
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'
|
28
|
+
# # is the same as
|
29
|
+
# foo ' -g "p fields=f1,f2" -l=1 '
|
30
|
+
#
|
31
|
+
# === Toggling Views With the Basic Global Option --render
|
32
|
+
# One of the more important global options is --render. This option toggles the rendering of a command's
|
33
|
+
# output done with View and Hirb[http://github.com/cldwalker/hirb].
|
34
|
+
#
|
35
|
+
# Here's a simple example of toggling Hirb's table view:
|
36
|
+
# # Defined in a library file:
|
37
|
+
# #@options {}
|
38
|
+
# def list(options={})
|
39
|
+
# [1,2,3]
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# Using it in irb:
|
43
|
+
# >> list
|
44
|
+
# => [1,2,3]
|
45
|
+
# >> list '-r' # or list --render
|
46
|
+
# +-------+
|
47
|
+
# | value |
|
48
|
+
# +-------+
|
49
|
+
# | 1 |
|
50
|
+
# | 2 |
|
51
|
+
# | 3 |
|
52
|
+
# +-------+
|
53
|
+
# 3 rows in set
|
54
|
+
# => true
|
55
|
+
class OptionCommand
|
56
|
+
BASIC_OPTIONS = {
|
57
|
+
:help=>{:type=>:boolean, :desc=>"Display a command's help"},
|
58
|
+
:render=>{:type=>:boolean, :desc=>"Toggle a command's default rendering behavior"},
|
59
|
+
: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
|
+
:pretend=>{:type=>:boolean, :desc=>"Display what a command would execute without executing it"},
|
62
|
+
} #:nodoc:
|
63
|
+
|
64
|
+
RENDER_OPTIONS = {
|
65
|
+
:fields=>{:type=>:array, :desc=>"Displays fields in the order given"},
|
66
|
+
:class=>{:type=>:string, :desc=>"Hirb helper class which renders"},
|
67
|
+
:max_width=>{:type=>:numeric, :desc=>"Max width of a table"},
|
68
|
+
:vertical=>{:type=>:boolean, :desc=>"Display a vertical table"},
|
69
|
+
} #:nodoc:
|
70
|
+
|
71
|
+
PIPE_OPTIONS = {
|
72
|
+
:sort=>{:type=>:string, :desc=>"Sort by given field"},
|
73
|
+
:reverse_sort=>{:type=>:boolean, :desc=>"Reverse a given sort"},
|
74
|
+
:query=>{:type=>:hash, :desc=>"Queries fields given field:search pairs"},
|
75
|
+
} #:nodoc:
|
76
|
+
|
77
|
+
class <<self
|
78
|
+
#:stopdoc:
|
79
|
+
def default_option_parser
|
80
|
+
@default_option_parser ||= OptionParser.new default_pipe_options.
|
81
|
+
merge(default_render_options.merge(BASIC_OPTIONS))
|
82
|
+
end
|
83
|
+
|
84
|
+
def default_pipe_options
|
85
|
+
@default_pipe_options ||= PIPE_OPTIONS.merge Pipe.pipe_options
|
86
|
+
end
|
87
|
+
|
88
|
+
def default_render_options
|
89
|
+
@default_render_options ||= RENDER_OPTIONS.merge Boson.repo.config[:render_options] || {}
|
90
|
+
end
|
91
|
+
|
92
|
+
def delete_non_render_options(opt)
|
93
|
+
opt.delete_if {|k,v| BASIC_OPTIONS.keys.include?(k) }
|
94
|
+
end
|
95
|
+
#:startdoc:
|
96
|
+
end
|
97
|
+
|
98
|
+
attr_accessor :command
|
99
|
+
def initialize(cmd)
|
100
|
+
@command = cmd
|
101
|
+
end
|
102
|
+
|
103
|
+
# Parses arguments and returns global options, local options and leftover arguments.
|
104
|
+
def parse(args)
|
105
|
+
if args.size == 1 && args[0].is_a?(String)
|
106
|
+
global_opt, parsed_options, args = parse_options Shellwords.shellwords(args[0])
|
107
|
+
# last string argument interpreted as args + options
|
108
|
+
elsif args.size > 1 && args[-1].is_a?(String)
|
109
|
+
temp_args = Boson.const_defined?(:BinRunner) ? args : Shellwords.shellwords(args.pop)
|
110
|
+
global_opt, parsed_options, new_args = parse_options temp_args
|
111
|
+
args += new_args
|
112
|
+
# add default options
|
113
|
+
elsif @command.options.to_s.empty? || (!@command.has_splat_args? &&
|
114
|
+
args.size <= (@command.arg_size - 1).abs) || (@command.has_splat_args? && !args[-1].is_a?(Hash))
|
115
|
+
global_opt, parsed_options = parse_options([])[0,2]
|
116
|
+
# merge default options with given hash of options
|
117
|
+
elsif (@command.has_splat_args? || (args.size == @command.arg_size)) && args[-1].is_a?(Hash)
|
118
|
+
global_opt, parsed_options = parse_options([])[0,2]
|
119
|
+
parsed_options.merge!(args.pop)
|
120
|
+
end
|
121
|
+
[global_opt || {}, parsed_options, args]
|
122
|
+
end
|
123
|
+
|
124
|
+
#:stopdoc:
|
125
|
+
def parse_options(args)
|
126
|
+
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
|
134
|
+
[global_options, parsed_options, new_args]
|
135
|
+
end
|
136
|
+
|
137
|
+
def option_parser
|
138
|
+
@option_parser ||= @command.render_options ? OptionParser.new(all_global_options) :
|
139
|
+
self.class.default_option_parser
|
140
|
+
end
|
141
|
+
|
142
|
+
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
|
+
}
|
148
|
+
render_opts = Util.recursive_hash_merge(@command.render_options, Util.deep_copy(self.class.default_render_options))
|
149
|
+
merged_opts = Util.recursive_hash_merge Util.deep_copy(self.class.default_pipe_options), render_opts
|
150
|
+
opts = Util.recursive_hash_merge merged_opts, Util.deep_copy(BASIC_OPTIONS)
|
151
|
+
set_global_option_defaults opts
|
152
|
+
end
|
153
|
+
|
154
|
+
def set_global_option_defaults(opts)
|
155
|
+
if !opts[:fields].key?(:values)
|
156
|
+
if opts[:fields][:default]
|
157
|
+
opts[:fields][:values] = opts[:fields][:default]
|
158
|
+
else
|
159
|
+
if opts[:change_fields] && (changed = opts[:change_fields][:default])
|
160
|
+
opts[:fields][:values] = changed.is_a?(Array) ? changed : changed.values
|
161
|
+
end
|
162
|
+
opts[:fields][:values] ||= opts[:headers][:default].keys if opts[:headers] && opts[:headers][:default]
|
163
|
+
end
|
164
|
+
opts[:fields][:enum] = false if opts[:fields][:values] && !opts[:fields].key?(:enum)
|
165
|
+
end
|
166
|
+
if opts[:fields][:values]
|
167
|
+
opts[:sort][:values] ||= opts[:fields][:values]
|
168
|
+
opts[:query][:keys] ||= opts[:fields][:values]
|
169
|
+
opts[:query][:default_keys] ||= "*"
|
170
|
+
end
|
171
|
+
opts
|
172
|
+
end
|
173
|
+
|
174
|
+
def prepend_default_option(args)
|
175
|
+
if @command.default_option && @command.arg_size <= 1 && !@command.has_splat_args? && args[0].to_s[/./] != '-'
|
176
|
+
args[0] = "--#{@command.default_option}=#{args[0]}" unless args.join.empty? || args[0].is_a?(Hash)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def check_argument_size(args)
|
181
|
+
if args.size != @command.arg_size && !@command.has_splat_args?
|
182
|
+
command_size, args_size = args.size > @command.arg_size ? [@command.arg_size, args.size] :
|
183
|
+
[@command.arg_size - 1, args.size - 1]
|
184
|
+
raise ArgumentError, "wrong number of arguments (#{args_size} for #{command_size})"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def add_default_args(args, obj)
|
189
|
+
if @command.args && args.size < @command.args.size - 1
|
190
|
+
# leave off last arg since its an option
|
191
|
+
@command.args.slice(0..-2).each_with_index {|arr,i|
|
192
|
+
next if args.size >= i + 1 # only fill in once args run out
|
193
|
+
break if arr.size != 2 # a default arg value must exist
|
194
|
+
begin
|
195
|
+
args[i] = @command.file_parsed_args? ? obj.instance_eval(arr[1]) : arr[1]
|
196
|
+
rescue Exception
|
197
|
+
raise Scientist::Error, "Unable to set default argument at position #{i+1}.\nReason: #{$!.message}"
|
198
|
+
end
|
199
|
+
}
|
200
|
+
end
|
201
|
+
end
|
202
|
+
#:startdoc:
|
203
|
+
end
|
204
|
+
end
|
data/lib/boson/option_parser.rb
CHANGED
@@ -35,7 +35,7 @@ module Boson
|
|
35
35
|
# String, Integer, Float, Array, Hash, FalseClass, TrueClass.
|
36
36
|
# * Users can define their own option types which create objects for _any_ Ruby class. See Options.
|
37
37
|
# * Each option type can have attributes to enable more features (see OptionParser.new).
|
38
|
-
# * When options are parsed by
|
38
|
+
# * When options are parsed by parse(), an IndifferentAccessHash hash is returned.
|
39
39
|
# * Options are also called switches, parameters, flags etc.
|
40
40
|
#
|
41
41
|
# Default option types:
|
@@ -79,6 +79,17 @@ module Boson
|
|
79
79
|
|
80
80
|
attr_reader :leading_non_opts, :trailing_non_opts, :opt_aliases
|
81
81
|
|
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.
|
84
|
+
def self.parse(options, args=ARGV)
|
85
|
+
(@opt_parser ||= new(options)).parse(args)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Usage string summarizing options defined in parse
|
89
|
+
def self.usage
|
90
|
+
@opt_parser.to_s
|
91
|
+
end
|
92
|
+
|
82
93
|
# Array of arguments left after defined options have been parsed out by parse.
|
83
94
|
def non_opts
|
84
95
|
leading_non_opts + trailing_non_opts
|
@@ -134,7 +145,7 @@ module Boson
|
|
134
145
|
# [*:split*] For :array and :hash options. A string or regular expression on which an array value splits
|
135
146
|
# to produce an array of values. Default is ','.
|
136
147
|
# [*:keys*] :hash option only. An array of values a hash option's keys can have. Keys can be aliased just like :values.
|
137
|
-
# [
|
148
|
+
# [*:default_keys*] :hash option only. Default keys to assume when only a value is given. Multiple keys can be joined
|
138
149
|
# by the :split character. Defaults to first key of :keys if :keys given.
|
139
150
|
def initialize(opts)
|
140
151
|
@defaults = {}
|
data/lib/boson/options.rb
CHANGED