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,100 @@
|
|
1
|
+
module Boson
|
2
|
+
# Scrapes comments right before a method for its attributes. Method attributes must begin with '@' i.e.:
|
3
|
+
# # @desc Does foo
|
4
|
+
# # @options :verbose=>true
|
5
|
+
# def foo(options={})
|
6
|
+
#
|
7
|
+
# Some rules about these attributes:
|
8
|
+
# * Attribute definitions can span multiple lines. When a new attribute starts a line or the comments end,
|
9
|
+
# then a definition ends.
|
10
|
+
# * If no @desc is found in the comment block, then the first comment line directly above the method
|
11
|
+
# is assumed to be the value for @desc. This means that no multi-line attribute definitions can occur
|
12
|
+
# without a description since the last line is assumed to be a description.
|
13
|
+
# * options, option, config and render_options attributes can take any valid ruby since they're evaled in
|
14
|
+
# their module's context.
|
15
|
+
# * desc attribute is not evaled and is simply text to be set as a string.
|
16
|
+
#
|
17
|
+
# This module was inspired by
|
18
|
+
# {pragdave}[http://github.com/pragdavespc/rake/commit/45231ac094854da9f4f2ac93465ed9b9ca67b2da].
|
19
|
+
module CommentInspector
|
20
|
+
extend self
|
21
|
+
EVAL_ATTRIBUTES = [:options, :render_options, :config]
|
22
|
+
|
23
|
+
# Given a method's file string, line number and defining module, returns a hash
|
24
|
+
# of attributes defined for that method.
|
25
|
+
def scrape(file_string, line, mod, attribute=nil)
|
26
|
+
hash = scrape_file(file_string, line) || {}
|
27
|
+
options = (arr = hash.delete(:option)) ? parse_option_comments(arr, mod) : {}
|
28
|
+
hash.select {|k,v| v && (attribute.nil? || attribute == k) }.each do |k,v|
|
29
|
+
hash[k] = EVAL_ATTRIBUTES.include?(k) ? eval_comment(v.join(' '), mod, k) : v.join(' ')
|
30
|
+
end
|
31
|
+
(hash[:options] ||= {}).merge!(options) if !options.empty?
|
32
|
+
attribute ? hash[attribute] : hash
|
33
|
+
end
|
34
|
+
|
35
|
+
#:stopdoc:
|
36
|
+
def parse_option_comments(arr, mod)
|
37
|
+
arr.inject({}) {|t,e|
|
38
|
+
key, val = e.join(' ').split(/\s*,\s*/, 2)
|
39
|
+
if val
|
40
|
+
key = key.sub(/^\s*:/, '').to_sym
|
41
|
+
t[key] = eval_comment(val, mod, 'option')
|
42
|
+
end
|
43
|
+
t
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def eval_comment(value, mod, mattr)
|
48
|
+
value = "{#{value}}" if !value[/^\s*\{/] && value[/=>/]
|
49
|
+
mod.module_eval(value)
|
50
|
+
rescue Exception
|
51
|
+
if Runner.debug
|
52
|
+
warn "DEBUG: Error while evaluating @#{mattr} in module #{mod.to_s[/\w+$/]}:\n " +
|
53
|
+
$!.message.gsub(/\n/, "\n ")
|
54
|
+
end
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
|
58
|
+
# Scrapes a given string for commented @keywords, starting with the line above the given line
|
59
|
+
def scrape_file(file_string, line)
|
60
|
+
lines = file_string.split("\n")
|
61
|
+
saved = []
|
62
|
+
i = line -2
|
63
|
+
while lines[i] =~ /^\s*#\s*(\S+)/ && i >= 0
|
64
|
+
saved << lines[i]
|
65
|
+
i -= 1
|
66
|
+
end
|
67
|
+
|
68
|
+
saved.empty? ? {} : splitter(saved.reverse)
|
69
|
+
end
|
70
|
+
|
71
|
+
def splitter(lines)
|
72
|
+
hash = {}
|
73
|
+
i = 0
|
74
|
+
# to magically make the last comment a description
|
75
|
+
unless lines.any? {|e| e =~ /^\s*#\s*@desc/ }
|
76
|
+
last_line = lines.pop
|
77
|
+
hash[:desc] = (last_line =~ /^\s*#\s*([^@\s].*)/) ? [$1] : nil
|
78
|
+
lines << last_line unless hash[:desc]
|
79
|
+
end
|
80
|
+
|
81
|
+
option = []
|
82
|
+
while i < lines.size
|
83
|
+
while lines[i] =~ /^\s*#\s*@(\w+)\s*(.*)/
|
84
|
+
key = $1.to_sym
|
85
|
+
hash[key] = [$2]
|
86
|
+
i += 1
|
87
|
+
while lines[i] =~ /^\s*#\s*([^@\s].*)/
|
88
|
+
hash[key] << $1
|
89
|
+
i+= 1
|
90
|
+
end
|
91
|
+
option << hash.delete(:option) if key == :option
|
92
|
+
end
|
93
|
+
i += 1
|
94
|
+
end
|
95
|
+
hash[:option] = option if !option.empty?
|
96
|
+
hash
|
97
|
+
end
|
98
|
+
#:startdoc:
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Boson
|
2
|
+
# Gathers method attributes by redefining method_added and capturing method
|
3
|
+
# calls before a method. This module also saves method locations so CommentInspector
|
4
|
+
# can scrape their commented method attributes.
|
5
|
+
module MethodInspector
|
6
|
+
extend self
|
7
|
+
attr_accessor :current_module, :mod_store
|
8
|
+
@mod_store ||= {}
|
9
|
+
METHODS = [:config, :desc, :options, :render_options]
|
10
|
+
METHOD_CLASSES = {:config=>Hash, :desc=>String, :options=>Hash, :render_options=>Hash}
|
11
|
+
ALL_METHODS = METHODS + [:option]
|
12
|
+
|
13
|
+
# The method_added used while scraping method attributes.
|
14
|
+
def new_method_added(mod, meth)
|
15
|
+
return unless mod.to_s[/^Boson::Commands::/]
|
16
|
+
self.current_module = mod
|
17
|
+
store[:temp] ||= {}
|
18
|
+
METHODS.each do |e|
|
19
|
+
store[e][meth.to_s] = store[:temp][e] if store[:temp][e]
|
20
|
+
end
|
21
|
+
(store[:options][meth.to_s] ||= {}).merge! store[:temp][:option] if store[:temp][:option]
|
22
|
+
|
23
|
+
if store[:temp].size < ALL_METHODS.size
|
24
|
+
store[:method_locations] ||= {}
|
25
|
+
if (result = find_method_locations(caller))
|
26
|
+
store[:method_locations][meth.to_s] = result
|
27
|
+
end
|
28
|
+
end
|
29
|
+
store[:temp] = {}
|
30
|
+
scrape_arguments(meth) if has_inspector_method?(meth, :options) || has_inspector_method?(meth,:render_options)
|
31
|
+
end
|
32
|
+
|
33
|
+
METHODS.each do |e|
|
34
|
+
define_method(e) do |mod, val|
|
35
|
+
(@mod_store[mod] ||= {})[e] ||= {}
|
36
|
+
(store(mod)[:temp] ||= {})[e] = val
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def option(mod, name, value)
|
41
|
+
(@mod_store[mod] ||= {})[:options] ||= {}
|
42
|
+
(store(mod)[:temp] ||= {})[:option] ||= {}
|
43
|
+
(store(mod)[:temp] ||= {})[:option][name] = value
|
44
|
+
end
|
45
|
+
|
46
|
+
# Scrapes a method's arguments using ArgumentInspector.
|
47
|
+
def scrape_arguments(meth)
|
48
|
+
store[:args] ||= {}
|
49
|
+
|
50
|
+
o = Object.new
|
51
|
+
o.extend(@current_module)
|
52
|
+
# private methods return nil
|
53
|
+
if (val = ArgumentInspector.scrape_with_eval(meth, @current_module, o))
|
54
|
+
store[:args][meth.to_s] = val
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
CALLER_REGEXP = RUBY_VERSION < '1.9' ? /in `load_source'/ : /in `<module:.*>'/
|
59
|
+
# Returns an array of the file and line number at which a method starts using
|
60
|
+
# a caller array. Necessary information for CommentInspector to function.
|
61
|
+
def find_method_locations(stack)
|
62
|
+
if (line = stack.find {|e| e =~ CALLER_REGEXP })
|
63
|
+
(line =~ /^(.*):(\d+)/) ? [$1, $2.to_i] : nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
#:stopdoc:
|
68
|
+
def find_method_locations_for_19(klass, meth)
|
69
|
+
if (klass = Util.any_const_get(klass)) && (meth_location = klass.method(meth).source_location) &&
|
70
|
+
meth_location[0]
|
71
|
+
meth_location
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Hash of a module's method attributes i.e. descriptions, options by method and then attribute
|
76
|
+
def store(mod=@current_module)
|
77
|
+
@mod_store[mod]
|
78
|
+
end
|
79
|
+
|
80
|
+
def current_module=(mod)
|
81
|
+
@current_module = mod
|
82
|
+
@mod_store[mod] ||= {}
|
83
|
+
end
|
84
|
+
|
85
|
+
def has_inspector_method?(meth, inspector)
|
86
|
+
(store[inspector] && store[inspector].key?(meth.to_s)) || inspector_in_file?(meth.to_s, inspector)
|
87
|
+
end
|
88
|
+
|
89
|
+
def inspector_in_file?(meth, inspector_method)
|
90
|
+
return false if !(file_line = store[:method_locations] && store[:method_locations][meth])
|
91
|
+
if File.exists?(file_line[0]) && (options = CommentInspector.scrape(
|
92
|
+
FileLibrary.read_library_file(file_line[0]), file_line[1], @current_module, inspector_method) )
|
93
|
+
(store[inspector_method] ||= {})[meth] = options
|
94
|
+
end
|
95
|
+
end
|
96
|
+
#:startdoc:
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
module Boson
|
2
|
+
# This class loads a file by its path relative to the commands directory of a repository.
|
3
|
+
# For example the library 'public/misc' could refer to the file '~/.boson/commands/public/misc.rb'.
|
4
|
+
# If a file's basename is unique in its repository, then it can be loaded with its basename i.e. 'misc'
|
5
|
+
# for the previous example. When loading a library, this class searches repositories in the order given by
|
6
|
+
# Boson.repos.
|
7
|
+
#
|
8
|
+
# === Creating a FileLibrary
|
9
|
+
# Start by creating a file with a module and some methods (See Library for naming a module).
|
10
|
+
# Non-private methods are automatically loaded as a library's commands.
|
11
|
+
#
|
12
|
+
# Take for example a library brain.rb:
|
13
|
+
# # Drop this in ~/.boson/commands/brain.rb
|
14
|
+
# module Brain
|
15
|
+
# def take_over(destination)
|
16
|
+
# puts "Pinky, it's time to take over the #{destination}!"
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# Once loaded, this library can be run from the commandline or irb:
|
21
|
+
# $ boson take_over world
|
22
|
+
# >> take_over 'world'
|
23
|
+
#
|
24
|
+
# If the library is namespaced, the command would be run as brain.take_over.
|
25
|
+
#
|
26
|
+
# Let's give Brain an option in his conquest:
|
27
|
+
# module Brain
|
28
|
+
# options :execute=>:string
|
29
|
+
# def take_over(destination, options={})
|
30
|
+
# puts "Pinky, it's time to take over the #{destination}!"
|
31
|
+
# system(options[:execute]) if options[:execute]
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# From the commandline and irb this runs as:
|
36
|
+
# $ boson take_over world -e initiate_brainiac
|
37
|
+
# >> take_over 'world -e initiate_brainiac'
|
38
|
+
#
|
39
|
+
# Since Boson aims to make your libraries just standard ruby, we can achieve the above
|
40
|
+
# by making options a commented method attribute:
|
41
|
+
# module Brain
|
42
|
+
# # @options :execute=>:string
|
43
|
+
# # Help Brain live the dream
|
44
|
+
# def take_over(destination, options={})
|
45
|
+
# puts "Pinky, it's time to take over the #{destination}!"
|
46
|
+
# system(options[:execute]) if options[:execute]
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# Some points about the above:
|
51
|
+
# * A '@' must prefix options and other method attributes that become comments.
|
52
|
+
# * Note the comment above the method. One-line comments right before a method set a command's description.
|
53
|
+
# * See Inspector for other method attributes, like config and render_options, that can be placed above a method.
|
54
|
+
#
|
55
|
+
# Once a command has a defined option, a command can also recognize a slew of global options:
|
56
|
+
# >> take_over '-h'
|
57
|
+
# take_over [destination] [--execute=STRING]
|
58
|
+
#
|
59
|
+
# # prints much more verbose help
|
60
|
+
# >> take_over '-hv'
|
61
|
+
#
|
62
|
+
# For more about these global options see OptionCommand and View.
|
63
|
+
class FileLibrary < Library
|
64
|
+
#:stopdoc:
|
65
|
+
def self.library_file(library, dir)
|
66
|
+
File.join(Repo.commands_dir(dir), library + ".rb")
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.matched_repo; @repo; end
|
70
|
+
|
71
|
+
def self.read_library_file(file, reload=false)
|
72
|
+
@file_cache ||= {}
|
73
|
+
@file_cache[file] = File.read(file) if (!@file_cache.has_key?(file) || reload)
|
74
|
+
@file_cache[file]
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.reset_file_cache(name=nil)
|
78
|
+
if name && @file_cache
|
79
|
+
@file_cache.delete(library_file(name, (matched_repo || Boson.repo).dir))
|
80
|
+
else
|
81
|
+
@file_cache = nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
handles {|source|
|
86
|
+
@repo = Boson.repos.find {|e| File.exists? library_file(source.to_s, e.dir) } ||
|
87
|
+
Boson.repos.find {|e|
|
88
|
+
Dir["#{e.commands_dir}/**/*.rb"].grep(/\/#{source}\.rb/).size == 1
|
89
|
+
}
|
90
|
+
!!@repo
|
91
|
+
}
|
92
|
+
|
93
|
+
def library_file(name=@name)
|
94
|
+
self.class.library_file(name, @repo_dir)
|
95
|
+
end
|
96
|
+
|
97
|
+
def set_repo
|
98
|
+
self.class.matched_repo
|
99
|
+
end
|
100
|
+
|
101
|
+
def set_name(name)
|
102
|
+
@lib_file = File.exists?(library_file(name.to_s)) ? library_file(name.to_s) :
|
103
|
+
Dir[self.class.matched_repo.commands_dir.to_s+'/**/*.rb'].find {|e| e =~ /\/#{name}\.rb$/}
|
104
|
+
@lib_file.gsub(/^#{self.class.matched_repo.commands_dir}\/|\.rb$/, '')
|
105
|
+
end
|
106
|
+
|
107
|
+
def base_module
|
108
|
+
@base_module ||= @name.include?('/') ? create_module_from_path : Commands
|
109
|
+
end
|
110
|
+
|
111
|
+
def load_source(reload=false)
|
112
|
+
library_string = self.class.read_library_file(@lib_file, reload)
|
113
|
+
Inspector.enable
|
114
|
+
base_module.module_eval(library_string, @lib_file)
|
115
|
+
Inspector.disable
|
116
|
+
end
|
117
|
+
|
118
|
+
def create_module_from_path(index=-2)
|
119
|
+
@name.split('/')[0..index].inject(Boson::Commands) {|base, e|
|
120
|
+
base.const_defined?(sub_mod = Util.camelize(e)) ? base.const_get(sub_mod) :
|
121
|
+
Util.create_module(base, e)
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
def load_source_and_set_module
|
126
|
+
detected = detect_additions(:modules=>true) { load_source }
|
127
|
+
@module = determine_lib_module(detected[:modules]) unless @module
|
128
|
+
end
|
129
|
+
|
130
|
+
def determine_lib_module(detected_modules)
|
131
|
+
detected_modules = detected_modules.select {|e| e.to_s[/^#{base_module}::/] }
|
132
|
+
case detected_modules.size
|
133
|
+
when 1 then lib_module = detected_modules[0]
|
134
|
+
when 0 then lib_module = create_module_from_path(-1)
|
135
|
+
else
|
136
|
+
unless (lib_module = Util.constantize("boson/commands/#{@name}")) && lib_module.to_s[/^Boson::Commands/]
|
137
|
+
raise LoaderError, "Can't detect module. Specify a module in this library's config."
|
138
|
+
end
|
139
|
+
end
|
140
|
+
lib_module
|
141
|
+
end
|
142
|
+
#:startdoc:
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Boson
|
2
|
+
# This library loads a gem by the given name. Unlike FileLibrary or ModuleLibrary, this library
|
3
|
+
# doesn't need a module to provide its functionality.
|
4
|
+
#
|
5
|
+
# Example:
|
6
|
+
# >> load_library 'httparty', :class_commands=>{'put'=>'HTTParty.put',
|
7
|
+
# 'delete'=>'HTTParty.delete' }
|
8
|
+
# => true
|
9
|
+
# >> put 'http://someurl.com'
|
10
|
+
class GemLibrary < Library
|
11
|
+
#:stopdoc:
|
12
|
+
def self.is_a_gem?(name)
|
13
|
+
return false unless defined? Gem
|
14
|
+
Gem::VERSION >= '1.8.0' ?
|
15
|
+
Gem::Specification.find_all_by_name(name)[0].is_a?(Gem::Specification) :
|
16
|
+
Gem.searcher.find(name).is_a?(Gem::Specification)
|
17
|
+
end
|
18
|
+
|
19
|
+
handles {|source| is_a_gem?(source.to_s) }
|
20
|
+
|
21
|
+
def loaded_correctly?
|
22
|
+
!@gems.empty? || !@commands.empty? || !!@module
|
23
|
+
end
|
24
|
+
|
25
|
+
def load_source_and_set_module
|
26
|
+
detect_additions { Util.safe_require @name }
|
27
|
+
end
|
28
|
+
#:startdoc:
|
29
|
+
end
|
30
|
+
end
|
@@ -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
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Boson
|
2
|
+
# This library takes a module or class as a library's name and loads its class methods
|
3
|
+
# as commands. If no commands are given it defaults to loading all of its class methods
|
4
|
+
# as commands. The only method callback (see Loader) this library calls on the
|
5
|
+
# original module/class is config().
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
# >> load_library Math, :commands=>%w{sin cos tan}
|
9
|
+
# => true
|
10
|
+
#
|
11
|
+
# # Let's brush up on ol trig
|
12
|
+
# >> sin (Math::PI/2)
|
13
|
+
# => 1.0
|
14
|
+
# >> tan (Math::PI/4)
|
15
|
+
# => 1.0
|
16
|
+
# # Close enough :)
|
17
|
+
# >> cos (Math::PI/2)
|
18
|
+
# => 6.12323399573677e-17
|
19
|
+
|
20
|
+
class ModuleLibrary < Library
|
21
|
+
#:stopdoc:
|
22
|
+
handles {|source| source.is_a?(Module) }
|
23
|
+
|
24
|
+
def set_name(name)
|
25
|
+
@module = name
|
26
|
+
underscore_lib = name.to_s[/^Boson::Commands/] ? name.to_s.split('::')[-1] : name.to_s
|
27
|
+
Util.underscore(underscore_lib)
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize_library_module
|
31
|
+
@class_commands = {@module.to_s=>Array(@commands).empty? ? @module.methods(false) : @commands }
|
32
|
+
@module = nil
|
33
|
+
super
|
34
|
+
end
|
35
|
+
#:startdoc:
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# This library requires the given name. This is useful for loading standard libraries,
|
2
|
+
# non-gem libraries (i.e. rip packages) and anything else in $LOAD_PATH.
|
3
|
+
#
|
4
|
+
# Example:
|
5
|
+
# >> load_library 'fileutils', :class_commands=>{'cd'=>'FileUtils.cd', 'cp'=>'FileUtils.cp'}
|
6
|
+
# => true
|
7
|
+
# >> cd '/home'
|
8
|
+
# => 0
|
9
|
+
# >> Dir.pwd
|
10
|
+
# >> '/home'
|
11
|
+
class Boson::RequireLibrary < Boson::GemLibrary
|
12
|
+
EXTENSIONS = ['', '.rb', '.rbw', '.so', '.bundle', '.dll', '.sl', '.jar']
|
13
|
+
handles {|source|
|
14
|
+
extensions_glob = "{#{EXTENSIONS.join(',')}}"
|
15
|
+
($LOAD_PATH - ['.']).any? {|dir|
|
16
|
+
Dir["#{File.expand_path source.to_s, dir}#{extensions_glob}"].size > 0
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
def loaded_correctly?
|
21
|
+
super || $".grep(/^#{@name}\.([a-z]+)?$/).size > 0
|
22
|
+
end
|
23
|
+
end
|