bosonson 0.304.1
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/CHANGELOG.rdoc +108 -0
- data/LICENSE.txt +22 -0
- data/README.rdoc +181 -0
- data/bin/bss +6 -0
- data/bosonson.gemspec +24 -0
- data/deps.rip +2 -0
- data/lib/boson.rb +96 -0
- data/lib/boson/command.rb +196 -0
- data/lib/boson/commands.rb +7 -0
- data/lib/boson/commands/core.rb +77 -0
- data/lib/boson/commands/web_core.rb +153 -0
- data/lib/boson/index.rb +48 -0
- data/lib/boson/inspector.rb +120 -0
- data/lib/boson/inspectors/argument_inspector.rb +97 -0
- data/lib/boson/inspectors/comment_inspector.rb +100 -0
- data/lib/boson/inspectors/method_inspector.rb +98 -0
- data/lib/boson/libraries/file_library.rb +144 -0
- data/lib/boson/libraries/gem_library.rb +30 -0
- data/lib/boson/libraries/local_file_library.rb +30 -0
- data/lib/boson/libraries/module_library.rb +37 -0
- data/lib/boson/libraries/require_library.rb +23 -0
- data/lib/boson/library.rb +179 -0
- data/lib/boson/loader.rb +118 -0
- data/lib/boson/manager.rb +169 -0
- data/lib/boson/namespace.rb +31 -0
- data/lib/boson/option_command.rb +222 -0
- data/lib/boson/option_parser.rb +475 -0
- data/lib/boson/options.rb +146 -0
- data/lib/boson/pipe.rb +147 -0
- data/lib/boson/pipes.rb +75 -0
- data/lib/boson/repo.rb +107 -0
- data/lib/boson/repo_index.rb +124 -0
- data/lib/boson/runner.rb +81 -0
- data/lib/boson/runners/bin_runner.rb +208 -0
- data/lib/boson/runners/console_runner.rb +58 -0
- data/lib/boson/scientist.rb +182 -0
- data/lib/boson/util.rb +129 -0
- data/lib/boson/version.rb +3 -0
- data/lib/boson/view.rb +95 -0
- data/test/argument_inspector_test.rb +62 -0
- data/test/bin_runner_test.rb +223 -0
- data/test/command_test.rb +22 -0
- data/test/commands_test.rb +22 -0
- data/test/comment_inspector_test.rb +126 -0
- data/test/deps.rip +4 -0
- data/test/file_library_test.rb +42 -0
- data/test/loader_test.rb +235 -0
- data/test/manager_test.rb +114 -0
- data/test/method_inspector_test.rb +90 -0
- data/test/option_parser_test.rb +367 -0
- data/test/options_test.rb +189 -0
- data/test/pipes_test.rb +65 -0
- data/test/repo_index_test.rb +122 -0
- data/test/repo_test.rb +23 -0
- data/test/runner_test.rb +40 -0
- data/test/scientist_test.rb +341 -0
- data/test/test_helper.rb +130 -0
- data/test/util_test.rb +56 -0
- data/vendor/bundle/gems/bacon-bits-0.1.0/deps.rip +1 -0
- data/vendor/bundle/gems/hirb-0.6.0/test/deps.rip +4 -0
- metadata +217 -0
@@ -0,0 +1,179 @@
|
|
1
|
+
module Boson
|
2
|
+
# A library is a group of commands (Command objects) usually grouped together by a module.
|
3
|
+
# Libraries are loaded from different sources depending on the library subclass. Default library
|
4
|
+
# subclasses are FileLibrary, GemLibrary, RequireLibrary, ModuleLibrary and LocalFileLibrary.
|
5
|
+
# See Loader for callbacks a library's module can have.
|
6
|
+
#
|
7
|
+
# == Naming a Library Module
|
8
|
+
# Although you can name a library module almost anything, here's the fine print:
|
9
|
+
# * A module can have any name if it's the only module in a library.
|
10
|
+
# * If there are multiple modules in a file library, the module's name must be a camelized version
|
11
|
+
# of the file's basename i.e. ~/.boson/commands/ruby_core.rb -> RubyCore.
|
12
|
+
# * Although modules are evaluated under the Boson::Commands namespace, Boson will warn you about creating
|
13
|
+
# modules whose name is the same as a top level class/module. The warning is to encourage users to stay
|
14
|
+
# away from error-prone libraries. Once you introduce such a module, _all_ libraries assume the nested module
|
15
|
+
# over the top level module and the top level module has to be prefixed with '::' _everywhere_.
|
16
|
+
#
|
17
|
+
# == Configuration
|
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:
|
27
|
+
# :class_commands:
|
28
|
+
# delete: HTTParty.delete
|
29
|
+
# :commands:
|
30
|
+
# delete:
|
31
|
+
# :alias: d
|
32
|
+
# :desc: Http delete a given url
|
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
|
+
#
|
37
|
+
# === Creating Your Own Library
|
38
|
+
# To create your own subclass you need to define what sources the subclass can handle with handles().
|
39
|
+
# If handles() returns true then the subclass is chosen to load. See Loader to see what instance methods
|
40
|
+
# to override for a subclass.
|
41
|
+
class Library
|
42
|
+
include Loader
|
43
|
+
class <<self
|
44
|
+
#:stopdoc:
|
45
|
+
attr_accessor :handle_blocks
|
46
|
+
def handles(&block)
|
47
|
+
(Library.handle_blocks ||= []) << [self,block]
|
48
|
+
end
|
49
|
+
#:startdoc:
|
50
|
+
end
|
51
|
+
|
52
|
+
# Public attributes for use outside of Boson.
|
53
|
+
ATTRIBUTES = [:gems, :dependencies, :commands, :loaded, :module, :name, :namespace, :indexed_namespace]
|
54
|
+
attr_reader *(ATTRIBUTES + [:commands_hash, :library_file, :object_namespace])
|
55
|
+
# Private attribute for use within Boson.
|
56
|
+
attr_reader :no_alias_creation, :new_module, :new_commands, :class_commands, :lib_file, :repo_dir
|
57
|
+
# Optional namespace name for a library. When enabled defaults to a library's name.
|
58
|
+
attr_writer :namespace
|
59
|
+
|
60
|
+
# Creates a library object with a hash of attributes which must include a :name attribute.
|
61
|
+
# Each hash pair maps directly to an instance variable and value. Defaults for attributes
|
62
|
+
# are read from config[:libraries][@library_name][@attribute]. When loading libraries, attributes
|
63
|
+
# can also be set via a library module's config() method (see Loader).
|
64
|
+
#
|
65
|
+
# Attributes that can be configured:
|
66
|
+
# [*:dependencies*] An array of libraries that this library depends on. A library won't load
|
67
|
+
# unless its dependencies are loaded first.
|
68
|
+
# [*:commands*] A hash or array of commands that belong to this library. A hash configures command attributes
|
69
|
+
# for the given commands with command names pointing to their configs. See Command.new for a
|
70
|
+
# command's configurable attributes. If an array, the commands are set for the given library,
|
71
|
+
# overidding default command detection. Example:
|
72
|
+
# :commands=>{'commands'=>{:desc=>'Lists commands', :alias=>'com'}}
|
73
|
+
# [*:class_commands*] A hash of commands to create. A hash key-pair can map command names to any string of ruby code
|
74
|
+
# that ends with a method call. Or a key-pair can map a class to an array of its class methods
|
75
|
+
# to create commands of the same name. Example:
|
76
|
+
# :class_commands=>{'spy'=>'Bond.spy', 'create'=>'Alias.manager.create',
|
77
|
+
# 'Boson::Util'=>['detect', 'any_const_get']}
|
78
|
+
# [*:force*] Boolean which forces a library to ignore when a library's methods are overriding existing ones.
|
79
|
+
# Use with caution. Default is false.
|
80
|
+
# [*:object_methods*] Boolean which detects any Object/Kernel methods created when loading a library and automatically
|
81
|
+
# adds them to a library's commands. Default is true.
|
82
|
+
# [*:namespace*] Boolean or string which namespaces a library. When true, the library is automatically namespaced
|
83
|
+
# to the library's name. When a string, the library is namespaced to the string. Default is nil.
|
84
|
+
# To control the namespacing of all libraries see Boson::Repo.config.
|
85
|
+
# [*:no_alias_creation*] Boolean which doesn't create aliases for a library. Useful for libraries that configure command
|
86
|
+
# aliases outside of Boson's control. Default is false.
|
87
|
+
def initialize(hash)
|
88
|
+
repo = set_repo
|
89
|
+
@repo_dir = repo.dir
|
90
|
+
@name = set_name(hash.delete(:name)) or raise ArgumentError, "Library missing required key :name"
|
91
|
+
@loaded = false
|
92
|
+
@commands_hash = {}
|
93
|
+
@commands = []
|
94
|
+
set_config (repo.config[:libraries][@name] || {}).merge(hash), true
|
95
|
+
set_command_aliases(repo.config[:command_aliases])
|
96
|
+
end
|
97
|
+
|
98
|
+
# A concise symbol version of a library type i.e. FileLibrary -> :file.
|
99
|
+
def library_type
|
100
|
+
str = self.class.to_s[/::(\w+)Library$/, 1] || 'library'
|
101
|
+
str.downcase.to_sym
|
102
|
+
end
|
103
|
+
|
104
|
+
def namespace(orig=@namespace)
|
105
|
+
@namespace = [String,FalseClass].include?(orig.class) ? orig : begin
|
106
|
+
if (@namespace == true || (Boson.repo.config[:auto_namespace] && !@index))
|
107
|
+
@namespace = clean_name
|
108
|
+
else
|
109
|
+
@namespace = false
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# The object a library uses for executing its commands.
|
115
|
+
def namespace_object
|
116
|
+
@namespace_object ||= namespace ? Boson.invoke(namespace) : Boson.main_object
|
117
|
+
end
|
118
|
+
|
119
|
+
#:stopdoc:
|
120
|
+
# handles names under directories
|
121
|
+
def clean_name
|
122
|
+
@name[/\w+$/]
|
123
|
+
end
|
124
|
+
|
125
|
+
def local?
|
126
|
+
is_a?(LocalFileLibrary) || (Boson.local_repo && Boson.local_repo.dir == @repo_dir)
|
127
|
+
end
|
128
|
+
|
129
|
+
def set_name(name)
|
130
|
+
name.to_s
|
131
|
+
end
|
132
|
+
|
133
|
+
def set_config(config, force=false)
|
134
|
+
if (commands = config.delete(:commands))
|
135
|
+
if commands.is_a?(Array)
|
136
|
+
@commands += commands
|
137
|
+
@pre_defined_commands = true
|
138
|
+
elsif commands.is_a?(Hash)
|
139
|
+
@commands += commands.keys
|
140
|
+
@commands_hash = Util.recursive_hash_merge commands, @commands_hash
|
141
|
+
end
|
142
|
+
end
|
143
|
+
set_command_aliases config.delete(:command_aliases) if config[:command_aliases]
|
144
|
+
set_attributes config, force
|
145
|
+
end
|
146
|
+
|
147
|
+
def set_command_aliases(command_aliases)
|
148
|
+
(command_aliases || {}).each do |cmd, cmd_alias|
|
149
|
+
@commands_hash[cmd] ||= {}
|
150
|
+
@commands_hash[cmd][:alias] ||= cmd_alias
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def set_repo
|
155
|
+
Boson.repo
|
156
|
+
end
|
157
|
+
|
158
|
+
def set_attributes(hash, force=false)
|
159
|
+
hash.each {|k,v| instance_variable_set("@#{k}", v) if instance_variable_get("@#{k}").nil? || force }
|
160
|
+
end
|
161
|
+
|
162
|
+
def command_objects(names=self.commands, command_array=Boson.commands)
|
163
|
+
command_array.select {|e| names.include?(e.name) && e.lib == self.name }
|
164
|
+
end
|
165
|
+
|
166
|
+
def command_object(name)
|
167
|
+
command_objects([name])[0]
|
168
|
+
end
|
169
|
+
|
170
|
+
def marshal_dump
|
171
|
+
[@name, @commands, @gems, @module.to_s, @repo_dir, @indexed_namespace]
|
172
|
+
end
|
173
|
+
|
174
|
+
def marshal_load(ary)
|
175
|
+
@name, @commands, @gems, @module, @repo_dir, @indexed_namespace = ary
|
176
|
+
end
|
177
|
+
#:startdoc:
|
178
|
+
end
|
179
|
+
end
|
data/lib/boson/loader.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
module Boson
|
2
|
+
# Raised if a library has a method which conflicts with existing methods in Boson.main_object.
|
3
|
+
class MethodConflictError < LoaderError; end
|
4
|
+
|
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
|
+
#
|
9
|
+
# === Module Callbacks
|
10
|
+
# For libraries that have a module i.e. FileLibrary and GemLibrary, the following class methods
|
11
|
+
# are invoked in the order below when loading a library:
|
12
|
+
#
|
13
|
+
# [*:config*] This method returns a library's hash of attributes as explained by Library.new. This is useful
|
14
|
+
# for distributing libraries with a default configuration. The library attributes specified here
|
15
|
+
# are overridden by ones a user has in their config file except for the :commands attribute, which
|
16
|
+
# is recursively merged together.
|
17
|
+
# [*:append_features*] In addition to its normal behavior, this method's return value determines if a
|
18
|
+
# library is loaded in the current environment. This is useful for libraries that you
|
19
|
+
# want loaded by default but not in some environments i.e. different ruby versions or
|
20
|
+
# in irb but not in script/console. Remember to use super when returning true.
|
21
|
+
# [*:included*] In addition to its normal behavior, this method should be used to require external libraries.
|
22
|
+
# Although requiring dependencies could be done anywhere in a module, putting dependencies here
|
23
|
+
# are encouraged. By not having dependencies hardcoded in a module, it's possible to analyze
|
24
|
+
# and view a library's commands without having to install and load its dependencies.
|
25
|
+
# If creating commands here, note that conflicts with existing commands won't be detected.
|
26
|
+
# [*:after_included*] This method is called after included() to initialize functionality. This is useful for
|
27
|
+
# libraries that are primarily executing ruby code i.e. defining ruby extensions or
|
28
|
+
# setting irb features. This method isn't called when indexing a library.
|
29
|
+
module Loader
|
30
|
+
# Loads a library and its dependencies and returns true if library loads correctly.
|
31
|
+
def load
|
32
|
+
@gems ||= []
|
33
|
+
load_source_and_set_module
|
34
|
+
module_callbacks if @module
|
35
|
+
yield if block_given?
|
36
|
+
(@module || @class_commands) ? detect_additions { load_module_commands } : @namespace = false
|
37
|
+
set_library_commands
|
38
|
+
@indexed_namespace = (@namespace == false) ? nil : @namespace if @index
|
39
|
+
loaded_correctly? && (@loaded = true)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Load the source and set instance variables necessary to make a library valid i.e. @module.
|
43
|
+
def load_source_and_set_module; end
|
44
|
+
|
45
|
+
# Boolean which indicates if library loaded correctly.
|
46
|
+
def loaded_correctly?
|
47
|
+
!!@module
|
48
|
+
end
|
49
|
+
|
50
|
+
#:stopdoc:
|
51
|
+
def module_callbacks
|
52
|
+
set_config(@module.config) if @module.respond_to?(:config)
|
53
|
+
if @module.respond_to?(:append_features)
|
54
|
+
raise AppendFeaturesFalseError unless @module.append_features(Module.new)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def load_module_commands
|
59
|
+
initialize_library_module
|
60
|
+
rescue MethodConflictError=>e
|
61
|
+
if Boson.repo.config[:error_method_conflicts] || namespace
|
62
|
+
raise MethodConflictError, e.message
|
63
|
+
else
|
64
|
+
@namespace = clean_name
|
65
|
+
@method_conflict = true
|
66
|
+
$stderr.puts "#{e.message}. Attempting load into the namespace #{@namespace}..."
|
67
|
+
initialize_library_module
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def detect_additions(options={}, &block)
|
72
|
+
options[:object_methods] = @object_methods if !@object_methods.nil?
|
73
|
+
detected = Util.detect(options, &block)
|
74
|
+
@gems += detected[:gems] if detected[:gems]
|
75
|
+
@commands += detected[:methods].map {|e| e.to_s }
|
76
|
+
detected
|
77
|
+
end
|
78
|
+
|
79
|
+
def initialize_library_module
|
80
|
+
@module = @module ? Util.constantize(@module) : Util.create_module(Boson::Commands, clean_name)
|
81
|
+
raise(LoaderError, "No module for library #{@name}") unless @module
|
82
|
+
if (conflict = Util.top_level_class_conflict(Boson::Commands, @module.to_s))
|
83
|
+
warn "Library module '#{@module}' may conflict with top level class/module '#{conflict}' references in"+
|
84
|
+
" your libraries. Rename your module to avoid this warning."
|
85
|
+
end
|
86
|
+
|
87
|
+
Manager.create_class_aliases(@module, @class_commands) unless @class_commands.nil? ||
|
88
|
+
@class_commands.empty? || @method_conflict
|
89
|
+
check_for_method_conflicts unless @force
|
90
|
+
@namespace = clean_name if @object_namespace
|
91
|
+
namespace ? Namespace.create(namespace, self) : include_in_universe
|
92
|
+
end
|
93
|
+
|
94
|
+
def include_in_universe(lib_module=@module)
|
95
|
+
Boson::Universe.send :include, lib_module
|
96
|
+
@module.after_included if lib_module.respond_to?(:after_included) && !@index
|
97
|
+
Boson::Universe.send :extend_object, Boson.main_object
|
98
|
+
end
|
99
|
+
|
100
|
+
def check_for_method_conflicts
|
101
|
+
conflicts = namespace ? (Boson.can_invoke?(namespace) ? [namespace] : []) :
|
102
|
+
(@module.instance_methods + @module.private_instance_methods) & (Boson.main_object.methods +
|
103
|
+
Boson.main_object.private_methods)
|
104
|
+
unless conflicts.empty?
|
105
|
+
raise MethodConflictError,"The following commands conflict with existing commands: #{conflicts.join(', ')}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def set_library_commands
|
110
|
+
aliases = @commands_hash.select {|k,v| @commands.include?(k) }.map {|k,v| v[:alias]}.compact
|
111
|
+
@commands -= aliases
|
112
|
+
@commands.delete(namespace) if namespace
|
113
|
+
@commands += Boson.invoke(namespace).boson_commands if namespace && !@pre_defined_commands
|
114
|
+
@commands.uniq!
|
115
|
+
end
|
116
|
+
#:startdoc:
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
module Boson
|
2
|
+
# Base class for library loading errors. Raised mostly in Boson::Loader and rescued by Boson::Manager.
|
3
|
+
class LoaderError < StandardError; end
|
4
|
+
# Raised when a library's append_features returns false.
|
5
|
+
class AppendFeaturesFalseError < StandardError; end
|
6
|
+
|
7
|
+
# Handles loading of libraries and commands.
|
8
|
+
class Manager
|
9
|
+
class <<self
|
10
|
+
attr_accessor :failed_libraries
|
11
|
+
|
12
|
+
# Loads a library or an array of libraries with options. Manager loads the first library subclass
|
13
|
+
# to meet a library subclass' criteria in this order: ModuleLibrary, FileLibrary, GemLibrary, RequireLibrary.
|
14
|
+
# ==== Examples:
|
15
|
+
# Manager.load 'my_commands' -> Loads a FileLibrary object from ~/.boson/commands/my_commands.rb
|
16
|
+
# Manager.load 'method_lister' -> Loads a GemLibrary object which requires the method_lister gem
|
17
|
+
# Any options that aren't listed here are passed as library attributes to the libraries (see Library.new)
|
18
|
+
# ==== Options:
|
19
|
+
# [:verbose] Boolean to print each library's loaded status along with more verbose errors. Default is false.
|
20
|
+
def load(libraries, options={})
|
21
|
+
Array(libraries).map {|e|
|
22
|
+
(@library = load_once(e, options)) ? after_load : false
|
23
|
+
}.all?
|
24
|
+
end
|
25
|
+
|
26
|
+
#:stopdoc:
|
27
|
+
def failed_libraries
|
28
|
+
@failed_libraries ||= []
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_library(lib)
|
32
|
+
Boson.libraries.delete(Boson.library(lib.name))
|
33
|
+
Boson.libraries << lib
|
34
|
+
end
|
35
|
+
|
36
|
+
def loaded?(lib_name)
|
37
|
+
((lib = Boson.library(lib_name)) && lib.loaded) ? true : false
|
38
|
+
end
|
39
|
+
|
40
|
+
def rescue_load_action(library, load_method)
|
41
|
+
yield
|
42
|
+
rescue AppendFeaturesFalseError
|
43
|
+
warn "DEBUG: Library #{library} didn't load due to append_features" if Runner.debug
|
44
|
+
rescue LoaderError=>e
|
45
|
+
FileLibrary.reset_file_cache(library.to_s)
|
46
|
+
failed_libraries << library
|
47
|
+
$stderr.puts "Unable to #{load_method} library #{library}. Reason: #{e.message}"
|
48
|
+
rescue StandardError, SyntaxError, LoadError =>e
|
49
|
+
FileLibrary.reset_file_cache(library.to_s)
|
50
|
+
failed_libraries << library
|
51
|
+
message = "Unable to #{load_method} library #{library}. Reason: #{$!}"
|
52
|
+
if Runner.debug
|
53
|
+
message += "\n" + e.backtrace.map {|e| " " + e }.join("\n")
|
54
|
+
elsif @options[:verbose]
|
55
|
+
message += "\n" + e.backtrace.slice(0,3).map {|e| " " + e }.join("\n")
|
56
|
+
end
|
57
|
+
$stderr.puts message
|
58
|
+
ensure
|
59
|
+
Inspector.disable if Inspector.enabled
|
60
|
+
end
|
61
|
+
|
62
|
+
def load_once(source, options={})
|
63
|
+
@options = options
|
64
|
+
rescue_load_action(source, :load) do
|
65
|
+
lib = loader_create(source)
|
66
|
+
if loaded?(lib.name)
|
67
|
+
$stderr.puts "Library #{lib.name} already exists." if options[:verbose] && !options[:dependency]
|
68
|
+
false
|
69
|
+
else
|
70
|
+
if lib.load { load_dependencies(lib, options) }
|
71
|
+
lib
|
72
|
+
else
|
73
|
+
$stderr.puts "Library #{lib.name} did not load successfully." if !options[:dependency]
|
74
|
+
$stderr.puts " "+lib.inspect if Runner.debug
|
75
|
+
false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def lib_dependencies
|
82
|
+
@lib_dependencies ||= {}
|
83
|
+
end
|
84
|
+
|
85
|
+
def load_dependencies(lib, options={})
|
86
|
+
lib_dependencies[lib] = Array(lib.dependencies).map do |e|
|
87
|
+
next if loaded?(e)
|
88
|
+
load_once(e, options.merge(:dependency=>true)) ||
|
89
|
+
raise(LoaderError, "Can't load dependency #{e}")
|
90
|
+
end.compact
|
91
|
+
end
|
92
|
+
|
93
|
+
def loader_create(source)
|
94
|
+
lib_class = Library.handle_blocks.find {|k,v| v.call(source) } or raise(LoaderError, "Library #{source} not found.")
|
95
|
+
lib_class[0].new(@options.merge(:name=>source))
|
96
|
+
end
|
97
|
+
|
98
|
+
def after_load
|
99
|
+
create_commands(@library)
|
100
|
+
add_library(@library)
|
101
|
+
puts "Loaded library #{@library.name}" if @options[:verbose]
|
102
|
+
(lib_dependencies[@library] || []).each do |e|
|
103
|
+
create_commands(e)
|
104
|
+
add_library(e)
|
105
|
+
puts "Loaded library dependency #{e.name}" if @options[:verbose]
|
106
|
+
end
|
107
|
+
true
|
108
|
+
end
|
109
|
+
|
110
|
+
def before_create_commands(lib)
|
111
|
+
lib.is_a?(FileLibrary) && lib.module && Inspector.add_method_data_to_library(lib)
|
112
|
+
end
|
113
|
+
|
114
|
+
def create_commands(lib, commands=lib.commands)
|
115
|
+
before_create_commands(lib)
|
116
|
+
commands.each {|e| Boson.commands << Command.create(e, lib)}
|
117
|
+
create_command_aliases(lib, commands) if commands.size > 0 && !lib.no_alias_creation
|
118
|
+
redefine_commands(lib, commands)
|
119
|
+
end
|
120
|
+
|
121
|
+
def redefine_commands(lib, commands)
|
122
|
+
option_commands = lib.command_objects(commands).select {|e| e.option_command? }
|
123
|
+
accepted, rejected = option_commands.partition {|e| e.args(lib) || e.arg_size }
|
124
|
+
if @options[:verbose] && rejected.size > 0
|
125
|
+
puts "Following commands cannot have options until their arguments are configured: " +
|
126
|
+
rejected.map {|e| e.name}.join(', ')
|
127
|
+
end
|
128
|
+
accepted.each {|cmd| Scientist.redefine_command(lib.namespace_object, cmd) }
|
129
|
+
end
|
130
|
+
|
131
|
+
def create_command_aliases(lib, commands)
|
132
|
+
lib.module ? prep_and_create_instance_aliases(commands, lib.module) : check_for_uncreated_aliases(lib, commands)
|
133
|
+
end
|
134
|
+
|
135
|
+
def prep_and_create_instance_aliases(commands, lib_module)
|
136
|
+
aliases_hash = {}
|
137
|
+
select_commands = Boson.commands.select {|e| commands.include?(e.name)}
|
138
|
+
select_commands.each do |e|
|
139
|
+
if e.alias
|
140
|
+
aliases_hash[lib_module.to_s] ||= {}
|
141
|
+
aliases_hash[lib_module.to_s][e.name] = e.alias
|
142
|
+
end
|
143
|
+
end
|
144
|
+
create_instance_aliases(aliases_hash)
|
145
|
+
end
|
146
|
+
|
147
|
+
def create_instance_aliases(aliases_hash)
|
148
|
+
Alias.manager.create_aliases(:instance_method, aliases_hash)
|
149
|
+
end
|
150
|
+
|
151
|
+
def create_class_aliases(mod, class_commands)
|
152
|
+
class_commands.dup.each {|k,v|
|
153
|
+
if v.is_a?(Array)
|
154
|
+
class_commands.delete(k).each {|e| class_commands[e] = "#{k}.#{e}"}
|
155
|
+
end
|
156
|
+
}
|
157
|
+
Alias.manager.create_aliases(:any_to_instance_method, mod.to_s=>class_commands.invert)
|
158
|
+
end
|
159
|
+
|
160
|
+
def check_for_uncreated_aliases(lib, commands)
|
161
|
+
return if lib.is_a?(GemLibrary)
|
162
|
+
if (found_commands = Boson.commands.select {|e| commands.include?(e.name)}) && found_commands.find {|e| e.alias }
|
163
|
+
$stderr.puts "No aliases created for library #{lib.name} because it has no module"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
#:startdoc:
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|