boson-more 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemspec +22 -0
- data/LICENSE.txt +22 -0
- data/README.md +97 -0
- data/Rakefile +35 -0
- data/deps.rip +1 -0
- data/lib/boson/alias.rb +75 -0
- data/lib/boson/argument_inspector.rb +90 -0
- data/lib/boson/commands/core.rb +67 -0
- data/lib/boson/commands/view_core.rb +19 -0
- data/lib/boson/commands/web_core.rb +153 -0
- data/lib/boson/comment_inspector.rb +100 -0
- data/lib/boson/console.rb +40 -0
- data/lib/boson/console_runner.rb +60 -0
- data/lib/boson/index.rb +48 -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/libraries.rb +183 -0
- data/lib/boson/more/version.rb +5 -0
- data/lib/boson/more.rb +18 -0
- data/lib/boson/more_commands.rb +14 -0
- data/lib/boson/more_inspector.rb +42 -0
- data/lib/boson/more_manager.rb +34 -0
- data/lib/boson/more_method_inspector.rb +74 -0
- data/lib/boson/more_option_parser.rb +28 -0
- data/lib/boson/more_scientist.rb +68 -0
- data/lib/boson/more_util.rb +30 -0
- data/lib/boson/namespace.rb +31 -0
- data/lib/boson/namespacer.rb +117 -0
- data/lib/boson/pipe.rb +156 -0
- data/lib/boson/pipe_runner.rb +44 -0
- data/lib/boson/pipes.rb +75 -0
- data/lib/boson/repo.rb +96 -0
- data/lib/boson/repo_index.rb +135 -0
- data/lib/boson/runner_options.rb +88 -0
- data/lib/boson/save.rb +198 -0
- data/lib/boson/science.rb +273 -0
- data/lib/boson/view.rb +98 -0
- data/lib/boson/viewable.rb +48 -0
- data/test/alias_test.rb +55 -0
- data/test/argument_inspector_test.rb +40 -0
- data/test/command_test.rb +22 -0
- data/test/commands_test.rb +53 -0
- data/test/comment_inspector_test.rb +126 -0
- data/test/console_runner_test.rb +58 -0
- data/test/deps.rip +4 -0
- data/test/file_library_test.rb +41 -0
- data/test/gem_library_test.rb +40 -0
- data/test/libraries_test.rb +55 -0
- data/test/loader_test.rb +38 -0
- data/test/module_library_test.rb +30 -0
- data/test/more_manager_test.rb +29 -0
- data/test/more_method_inspector_test.rb +42 -0
- data/test/more_scientist_test.rb +10 -0
- data/test/namespacer_test.rb +61 -0
- data/test/pipes_test.rb +65 -0
- data/test/repo_index_test.rb +123 -0
- data/test/repo_test.rb +23 -0
- data/test/runner_options_test.rb +29 -0
- data/test/save_test.rb +86 -0
- data/test/science_test.rb +58 -0
- data/test/scientist_test.rb +195 -0
- data/test/test_helper.rb +165 -0
- data/test/web_test.rb +22 -0
- metadata +169 -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 and config 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, :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 Boson.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,40 @@
|
|
1
|
+
require 'boson/console_runner'
|
2
|
+
|
3
|
+
module Boson
|
4
|
+
CONFIG.update console_defaults: []
|
5
|
+
|
6
|
+
# Additional options added to Repo:
|
7
|
+
# [:console_defaults] Array of libraries to load at start up when used in irb. Default is to load all library files and libraries
|
8
|
+
# defined in the config.
|
9
|
+
# [:console] Console to load when using --console from commandline. Default is irb.
|
10
|
+
module Console
|
11
|
+
# Start Boson by loading repositories and their configured libraries.
|
12
|
+
# See ConsoleRunner.start for its options.
|
13
|
+
def start(options={})
|
14
|
+
ConsoleRunner.start(options)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
extend Console
|
18
|
+
|
19
|
+
# [:console] This drops Boson into irb after having loaded default commands and any explict libraries with
|
20
|
+
# :load option. This is a good way to start irb with only certain libraries loaded.
|
21
|
+
module ConsoleOptions
|
22
|
+
def early_option?(args)
|
23
|
+
if @options[:console]
|
24
|
+
ConsoleRunner.bin_start(@options[:console], @options[:load])
|
25
|
+
true
|
26
|
+
else
|
27
|
+
super
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
if defined? BinRunner
|
33
|
+
class BinRunner < BareRunner
|
34
|
+
GLOBAL_OPTIONS.update console:
|
35
|
+
{:type=>:boolean,
|
36
|
+
:desc=>"Drops into irb with default and explicit libraries loaded"}
|
37
|
+
extend ConsoleOptions
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'boson/save'
|
2
|
+
|
3
|
+
module Boson
|
4
|
+
# Runner used when starting irb. To use in irb, drop this in your ~/.irbrc:
|
5
|
+
# require 'boson'
|
6
|
+
# Boson.start
|
7
|
+
class ConsoleRunner < BareRunner
|
8
|
+
class <<self
|
9
|
+
# Starts Boson by loading configured libraries. If no default libraries are specified in the config,
|
10
|
+
# it will load up all detected libraries. Options:
|
11
|
+
# [:libraries] Array of libraries to load.
|
12
|
+
# [:verbose] Boolean to be verbose about libraries loading. Default is true.
|
13
|
+
# [:no_defaults] Boolean or :all which turns off loading default libraries. If set to true,
|
14
|
+
# effects loading user's console default libraries. If set to :all, effects
|
15
|
+
# all libraries including boson's. Default is false.
|
16
|
+
# [:autoload_libraries] Boolean which makes any command execution easier. It redefines
|
17
|
+
# method_missing on Boson.main_object so that commands with unloaded
|
18
|
+
# libraries are automatically loaded. Default is false.
|
19
|
+
def start(options={})
|
20
|
+
super
|
21
|
+
@options = {:verbose=>true}.merge options
|
22
|
+
init unless @initialized
|
23
|
+
Manager.load(@options[:libraries], load_options) if @options[:libraries]
|
24
|
+
end
|
25
|
+
|
26
|
+
# Loads libraries and then starts irb (or the configured console) from the commandline.
|
27
|
+
def bin_start(repl, libraries)
|
28
|
+
start :no_defaults=>true, :libraries=>libraries
|
29
|
+
repl = Boson.repo.config[:console] if Boson.repo.config[:console]
|
30
|
+
repl = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb' unless repl.is_a?(String)
|
31
|
+
unless repl.index('/') == 0 || (repl = Util.which(repl))
|
32
|
+
abort "Console not found. Please specify full path in config[:console]."
|
33
|
+
else
|
34
|
+
load_repl(repl)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def load_repl(repl) #:nodoc:
|
39
|
+
ARGV.replace ['-f']
|
40
|
+
$progname = $0
|
41
|
+
alias $0 $progname
|
42
|
+
Kernel.load $0 = repl
|
43
|
+
end
|
44
|
+
|
45
|
+
def init #:nodoc:
|
46
|
+
super
|
47
|
+
define_autoloader if @options[:autoload_libraries]
|
48
|
+
@initialized = true
|
49
|
+
end
|
50
|
+
|
51
|
+
def default_libraries #:nodoc:
|
52
|
+
return [] if @options[:no_defaults] == :all
|
53
|
+
return super if @options[:no_defaults]
|
54
|
+
defaults = super + Boson.repos.map {|e| e.config[:console_defaults] }.flatten
|
55
|
+
defaults += detected_libraries if defaults.empty?
|
56
|
+
defaults.uniq
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/boson/index.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Boson
|
2
|
+
# This class manages indexing/storing all commands and libraries. See RepoIndex for details
|
3
|
+
# about the index created for each Repo.
|
4
|
+
module Index
|
5
|
+
extend self
|
6
|
+
# Array of indexes, one per repo in Boson.repos.
|
7
|
+
def indexes
|
8
|
+
@indexes ||= Boson.repos.map {|e| RepoIndex.new(e) }
|
9
|
+
end
|
10
|
+
|
11
|
+
# Updates all repo indexes.
|
12
|
+
def update(options={})
|
13
|
+
indexes.each {|e| e.update(options) }
|
14
|
+
end
|
15
|
+
|
16
|
+
#:stopdoc:
|
17
|
+
def read
|
18
|
+
indexes.each {|e| e.read }
|
19
|
+
end
|
20
|
+
|
21
|
+
def find_library(command, object=false)
|
22
|
+
indexes.each {|e|
|
23
|
+
(lib = e.find_library(command, object)) and return lib
|
24
|
+
}
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def find_command(command)
|
29
|
+
indexes.each {|e|
|
30
|
+
(cmd = Command.find(command, e.commands)) and return(cmd)
|
31
|
+
}
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def commands
|
36
|
+
indexes.map {|e| e.commands}.flatten
|
37
|
+
end
|
38
|
+
|
39
|
+
def libraries
|
40
|
+
indexes.map {|e| e.libraries}.flatten
|
41
|
+
end
|
42
|
+
|
43
|
+
def all_main_methods
|
44
|
+
indexes.map {|e| e.all_main_methods}.flatten
|
45
|
+
end
|
46
|
+
#:startdoc:
|
47
|
+
end
|
48
|
+
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 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 load_commands
|
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
|