boson 0.2.5 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{gemspec → .gemspec} +8 -3
- data/CHANGELOG.rdoc +13 -0
- data/README.rdoc +7 -5
- data/Rakefile +3 -3
- data/deps.rip +2 -0
- data/lib/boson/command.rb +14 -7
- data/lib/boson/commands/core.rb +10 -10
- data/lib/boson/inspector.rb +25 -7
- data/lib/boson/inspectors/argument_inspector.rb +8 -3
- data/lib/boson/inspectors/comment_inspector.rb +27 -4
- data/lib/boson/inspectors/method_inspector.rb +10 -1
- data/lib/boson/libraries/require_library.rb +5 -5
- data/lib/boson/manager.rb +8 -3
- data/lib/boson/pipes.rb +5 -1
- data/lib/boson/runner.rb +2 -0
- data/lib/boson/runners/bin_runner.rb +13 -8
- data/lib/boson/runners/console_runner.rb +8 -2
- data/lib/boson/scientist.rb +1 -1
- data/lib/boson/version.rb +1 -1
- data/test/bin_runner_test.rb +32 -17
- data/test/command_test.rb +22 -0
- data/test/comment_inspector_test.rb +37 -9
- data/test/deps.rip +4 -0
- data/test/file_library_test.rb +1 -1
- data/test/loader_test.rb +1 -1
- data/test/manager_test.rb +16 -2
- data/test/method_inspector_test.rb +16 -1
- data/test/pipes_test.rb +9 -0
- data/test/test_helper.rb +7 -4
- metadata +76 -11
- data/test/bacon_extensions.rb +0 -26
data/{gemspec → .gemspec}
RENAMED
@@ -9,12 +9,17 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.email = "gabriel.horner@gmail.com"
|
10
10
|
s.homepage = "http://tagaholic.me/boson/"
|
11
11
|
s.summary = "A command/task framework similar to rake and thor that opens your ruby universe to the commandline and irb."
|
12
|
-
s.description = "Boson
|
12
|
+
s.description = "Boson is a command/task framework with the power to turn any ruby method into a full-fledged executable with options. Some unique features that differentiate it from rake and thor include being usable from irb and the commandline, optional automated views generated by hirb and allowing libraries to be written as plain ruby. For my libraries that use this, see irbfiles. Works with all major ruby versions."
|
13
13
|
s.required_rubygems_version = ">= 1.3.6"
|
14
14
|
s.rubyforge_project = 'tagaholic'
|
15
15
|
s.executables = ['boson']
|
16
16
|
s.add_dependency 'hirb', '>= 0.3.2'
|
17
|
-
s.add_dependency 'alias', '>= 0.2.
|
18
|
-
s.
|
17
|
+
s.add_dependency 'alias', '>= 0.2.2'
|
18
|
+
s.add_development_dependency 'mocha'
|
19
|
+
s.add_development_dependency 'bacon', '>= 1.1.0'
|
20
|
+
s.add_development_dependency 'mocha-on-bacon'
|
21
|
+
s.add_development_dependency 'bacon-bits'
|
22
|
+
s.files = Dir.glob(%w[{lib,test}/**/*.rb bin/* [A-Z]*.{txt,rdoc} ext/**/*.{rb,c} **/deps.rip]) + %w{Rakefile .gemspec}
|
19
23
|
s.extra_rdoc_files = ["README.rdoc", "LICENSE.txt"]
|
24
|
+
s.license = 'MIT'
|
20
25
|
end
|
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
== 0.3.0
|
2
|
+
* Added --debug to executable with multiple debug hooks
|
3
|
+
* Added --ruby_debug and -I to executable to change $LOAD_PATH and $DEBUG
|
4
|
+
* Added @option method attribute as a more readable complement to @options
|
5
|
+
* Added proper exit code for failed commands (#12)
|
6
|
+
* Added friendlier errors for libraries with SyntaxError or LoaderError
|
7
|
+
* Added validation to method attributes
|
8
|
+
* Improved RequireLibrary to more robustly handle gems like httparty
|
9
|
+
* Fixed 1.9.2-rc2 bugs including #14
|
10
|
+
* Fixed finding commands with same names
|
11
|
+
* Fixed --console for ruby >= 1.8.7
|
12
|
+
* Fixed --help for namespaced commands
|
13
|
+
|
1
14
|
== 0.2.5
|
2
15
|
* Fixed critical gemspec error
|
3
16
|
|
data/README.rdoc
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
To read a linkable version of this README, {see here}[http://tagaholic.me/boson/doc/].
|
2
2
|
|
3
3
|
== Description
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
Boson is a command/task framework with the power to turn any ruby method into a full-fledged
|
5
|
+
executable with options. Some unique features that differentiate it from rake and thor include
|
6
|
+
being usable from irb and the commandline, optional automated views generated by hirb and allowing
|
7
|
+
libraries to be written as plain ruby. For my libraries that use this, see
|
8
|
+
{irbfiles}[http://github.com/cldwalker/irbfiles]. Works with all major ruby versions.
|
7
9
|
|
8
10
|
== Features
|
9
11
|
* Simple organization: Commands are just methods on an object (default is main) and command libraries are just modules.
|
@@ -159,10 +161,10 @@ My {tagging obsession}[http://github.com/cldwalker/tag-tree] from the ruby conso
|
|
159
161
|
* http://tagaholic.me/2009/10/15/boson-and-hirb-interactions.html
|
160
162
|
* http://tagaholic.me/2009/10/19/how-boson-enhances-your-irb-experience.html
|
161
163
|
|
162
|
-
==
|
164
|
+
== Credits
|
163
165
|
Boson stands on the shoulders of these people and their ideas:
|
164
166
|
* Yehuda Katz for inspiring me with Thor and its awesome option parser (Boson::OptionParser).
|
165
167
|
* Daniel Berger for his original work on thor's awesome option parser.
|
166
168
|
* Dave Thomas for scraping a method's comments (Boson::CommentInspector)
|
167
169
|
* Mauricio Fernandez for scraping a method's arguments (Boson::ArgumentInspector)
|
168
|
-
* Chris Wanstrath for inspiring Boson's libraries with Rip's packages.
|
170
|
+
* Chris Wanstrath for inspiring Boson's libraries with Rip's packages.
|
data/Rakefile
CHANGED
@@ -2,12 +2,12 @@ require 'rake'
|
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
4
|
def gemspec
|
5
|
-
@gemspec ||= eval(File.read('gemspec'), binding, 'gemspec')
|
5
|
+
@gemspec ||= eval(File.read('.gemspec'), binding, '.gemspec')
|
6
6
|
end
|
7
7
|
|
8
8
|
desc "Build the gem"
|
9
9
|
task :gem=>:gemspec do
|
10
|
-
sh "gem build gemspec"
|
10
|
+
sh "gem build .gemspec"
|
11
11
|
FileUtils.mkdir_p 'pkg'
|
12
12
|
FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", 'pkg'
|
13
13
|
end
|
@@ -32,4 +32,4 @@ task :test do |t|
|
|
32
32
|
sh 'bacon -q -Ilib -I. test/*_test.rb'
|
33
33
|
end
|
34
34
|
|
35
|
-
task :default => :test
|
35
|
+
task :default => :test
|
data/deps.rip
ADDED
data/lib/boson/command.rb
CHANGED
@@ -20,13 +20,20 @@ module Boson
|
|
20
20
|
# Finds a command, namespaced or not and aliased or not. If found returns the
|
21
21
|
# command object, otherwise returns nil.
|
22
22
|
def self.find(command, commands=Boson.commands)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
if command.to_s.include?(NAMESPACE)
|
24
|
+
command, subcommand = command.to_s.split(NAMESPACE, 2)
|
25
|
+
commands.find {|current_command|
|
26
|
+
[current_command.name, current_command.alias].include?(subcommand) &&
|
27
|
+
current_command.library && (current_command.library.namespace == command)
|
28
|
+
}
|
29
|
+
else
|
30
|
+
commands.find {|e| [e.name, e.alias].include?(command) && !e.namespace}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# One line usage for a command if it exists
|
35
|
+
def self.usage(command)
|
36
|
+
(cmd = find(command)) ? "#{command} #{cmd.usage}" : "Command '#{command}' not found"
|
30
37
|
end
|
31
38
|
|
32
39
|
ATTRIBUTES = [:name, :lib, :alias, :desc, :options, :args, :config]
|
data/lib/boson/commands/core.rb
CHANGED
@@ -61,17 +61,17 @@ module Boson::Commands::Core #:nodoc:
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def usage(command, options={})
|
64
|
-
|
65
|
-
puts msg
|
66
|
-
return if options[:one_line] || !cmd
|
64
|
+
puts Boson::Command.usage(command)
|
67
65
|
|
68
|
-
if cmd
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
66
|
+
if (cmd = Boson::Command.find(command))
|
67
|
+
if cmd.options && !cmd.options.empty?
|
68
|
+
puts "\nLOCAL OPTIONS"
|
69
|
+
cmd.option_parser.print_usage_table options[:render_options].dup.merge(:local=>true)
|
70
|
+
end
|
71
|
+
if options[:verbose] && cmd.render_option_parser
|
72
|
+
puts "\nGLOBAL OPTIONS"
|
73
|
+
cmd.render_option_parser.print_usage_table options[:render_options].dup
|
74
|
+
end
|
75
75
|
end
|
76
76
|
end
|
77
77
|
end
|
data/lib/boson/inspector.rb
CHANGED
@@ -9,16 +9,19 @@ module Boson
|
|
9
9
|
# # @render_options :fields=>%w{one two}
|
10
10
|
# # @config :alias=>'so'
|
11
11
|
# options :verbose=>:boolean
|
12
|
+
# option :count, :numeric
|
12
13
|
# # Something descriptive perhaps
|
13
14
|
# def some_method(opts)
|
14
15
|
# # ...
|
15
16
|
# end
|
16
17
|
# end
|
17
18
|
#
|
18
|
-
# Method attributes serve as configuration for a method's command.
|
19
|
+
# Method attributes serve as configuration for a method's command. All attributes should only be called once per
|
20
|
+
# method except for option. Available method attributes:
|
19
21
|
# * config: Hash to define any command attributes (see Command.new).
|
20
22
|
# * desc: String to define a command's description for a command. Defaults to first commented line above a method.
|
21
23
|
# * options: Hash to define an OptionParser object for a command's options.
|
24
|
+
# * option: Option name and value to be merged in with options. See OptionParser for what an option value can be.
|
22
25
|
# * render_options: Hash to define an OptionParser object for a command's local/global render options (see View).
|
23
26
|
#
|
24
27
|
# When deciding whether to use commented or normal Module methods, remember that commented Module methods allow
|
@@ -31,9 +34,9 @@ module Boson
|
|
31
34
|
# loading its methods.
|
32
35
|
def enable
|
33
36
|
@enabled = true
|
34
|
-
body = MethodInspector::
|
35
|
-
%[def #{e}(
|
36
|
-
Boson::MethodInspector.#{e}(self,
|
37
|
+
body = MethodInspector::ALL_METHODS.map {|e|
|
38
|
+
%[def #{e}(*args)
|
39
|
+
Boson::MethodInspector.#{e}(self, *args)
|
37
40
|
end]
|
38
41
|
}.join("\n") +
|
39
42
|
%[
|
@@ -50,7 +53,7 @@ module Boson
|
|
50
53
|
# Disable scraping method data.
|
51
54
|
def disable
|
52
55
|
::Module.module_eval %[
|
53
|
-
Boson::MethodInspector::
|
56
|
+
Boson::MethodInspector::ALL_METHODS.each {|e| remove_method e }
|
54
57
|
alias_method :method_added, :_old_method_added
|
55
58
|
]
|
56
59
|
@enabled = false
|
@@ -71,7 +74,17 @@ module Boson
|
|
71
74
|
(MethodInspector::METHODS + [:args]).each do |key|
|
72
75
|
(@store[key] || []).each do |cmd, val|
|
73
76
|
@commands_hash[cmd] ||= {}
|
74
|
-
|
77
|
+
add_valid_data_to_config(key, val, cmd)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def add_valid_data_to_config(key, value, cmd)
|
83
|
+
if valid_attr_value?(key, value)
|
84
|
+
add_scraped_data_to_config(key, value, cmd)
|
85
|
+
else
|
86
|
+
if Runner.debug
|
87
|
+
warn "DEBUG: Command '#{cmd}' has #{key.inspect} attribute with invalid value '#{value.inspect}'"
|
75
88
|
end
|
76
89
|
end
|
77
90
|
end
|
@@ -88,12 +101,17 @@ module Boson
|
|
88
101
|
end
|
89
102
|
end
|
90
103
|
|
104
|
+
def valid_attr_value?(key, value)
|
105
|
+
return true if (klass = MethodInspector::METHOD_CLASSES[key]).nil?
|
106
|
+
value.is_a?(klass) || value.nil?
|
107
|
+
end
|
108
|
+
|
91
109
|
def add_comment_scraped_data
|
92
110
|
(@store[:method_locations] || []).select {|k,(f,l)| f == @library_file }.each do |cmd, (file, lineno)|
|
93
111
|
scraped = CommentInspector.scrape(FileLibrary.read_library_file(file), lineno, MethodInspector.current_module)
|
94
112
|
@commands_hash[cmd] ||= {}
|
95
113
|
MethodInspector::METHODS.each do |e|
|
96
|
-
|
114
|
+
add_valid_data_to_config(e, scraped[e], cmd)
|
97
115
|
end
|
98
116
|
end
|
99
117
|
end
|
@@ -26,11 +26,15 @@ module Boson::ArgumentInspector
|
|
26
26
|
return if local_variables == params # nothing new found
|
27
27
|
format_arguments(params, values, arity, num_args)
|
28
28
|
rescue Exception
|
29
|
-
|
29
|
+
print_debug_message(klass, meth) if Boson::Runner.debug
|
30
30
|
ensure
|
31
31
|
set_trace_func(nil)
|
32
32
|
end
|
33
33
|
|
34
|
+
def print_debug_message(klass, meth) #:nodoc:
|
35
|
+
warn "DEBUG: Error while scraping arguments from #{klass.to_s[/\w+$/]}##{meth}: #{$!.message}"
|
36
|
+
end
|
37
|
+
|
34
38
|
# process params + values to return array of argument arrays
|
35
39
|
def format_arguments(params, values, arity, num_args) #:nodoc:
|
36
40
|
params ||= []
|
@@ -55,10 +59,11 @@ module Boson::ArgumentInspector
|
|
55
59
|
begin
|
56
60
|
if event[/call/] && classname == klass && id == meth
|
57
61
|
params = eval("local_variables", binding)
|
58
|
-
values = eval("local_variables.map{|x| eval(x)}", binding)
|
62
|
+
values = eval("local_variables.map{|x| eval(x.to_s)}", binding)
|
59
63
|
throw :done
|
60
64
|
end
|
61
65
|
rescue Exception
|
66
|
+
print_debug_message(klass, meth) if Boson::Runner.debug
|
62
67
|
end
|
63
68
|
}
|
64
69
|
if arity >= 0
|
@@ -70,7 +75,7 @@ module Boson::ArgumentInspector
|
|
70
75
|
MAX_ARGS.downto(arity.abs - 1) do |i|
|
71
76
|
catch(:done) do
|
72
77
|
begin
|
73
|
-
object.send(meth, *(0...i))
|
78
|
+
object.send(meth, *(0...i))
|
74
79
|
rescue Exception
|
75
80
|
end
|
76
81
|
end
|
@@ -10,7 +10,8 @@ module Boson
|
|
10
10
|
# * If no @desc is found in the comment block, then the first comment line directly above the method
|
11
11
|
# is assumed to be the value for @desc. This means that no multi-line attribute definitions can occur
|
12
12
|
# without a description since the last line is assumed to be a description.
|
13
|
-
# * options, config and render_options attributes can take any valid ruby since they're evaled in
|
13
|
+
# * options, option, config and render_options attributes can take any valid ruby since they're evaled in
|
14
|
+
# their module's context.
|
14
15
|
# * desc attribute is not evaled and is simply text to be set as a string.
|
15
16
|
#
|
16
17
|
# This module was inspired by
|
@@ -23,16 +24,35 @@ module Boson
|
|
23
24
|
# of attributes defined for that method.
|
24
25
|
def scrape(file_string, line, mod, attribute=nil)
|
25
26
|
hash = scrape_file(file_string, line) || {}
|
27
|
+
options = (arr = hash.delete(:option)) ? parse_option_comments(arr, mod) : {}
|
26
28
|
hash.select {|k,v| v && (attribute.nil? || attribute == k) }.each do |k,v|
|
27
|
-
hash[k] = EVAL_ATTRIBUTES.include?(k) ? eval_comment(v.join(' '), mod) : v.join(' ')
|
29
|
+
hash[k] = EVAL_ATTRIBUTES.include?(k) ? eval_comment(v.join(' '), mod, k) : v.join(' ')
|
28
30
|
end
|
31
|
+
(hash[:options] ||= {}).merge!(options) if !options.empty?
|
29
32
|
attribute ? hash[attribute] : hash
|
30
33
|
end
|
31
34
|
|
32
35
|
#:stopdoc:
|
33
|
-
def
|
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)
|
34
48
|
value = "{#{value}}" if !value[/^\s*\{/] && value[/=>/]
|
35
|
-
|
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
|
36
56
|
end
|
37
57
|
|
38
58
|
# Scrapes a given string for commented @keywords, starting with the line above the given line
|
@@ -58,6 +78,7 @@ module Boson
|
|
58
78
|
lines << last_line unless hash[:desc]
|
59
79
|
end
|
60
80
|
|
81
|
+
option = []
|
61
82
|
while i < lines.size
|
62
83
|
while lines[i] =~ /^\s*#\s*@(\w+)\s*(.*)/
|
63
84
|
key = $1.to_sym
|
@@ -67,9 +88,11 @@ module Boson
|
|
67
88
|
hash[key] << $1
|
68
89
|
i+= 1
|
69
90
|
end
|
91
|
+
option << hash.delete(:option) if key == :option
|
70
92
|
end
|
71
93
|
i += 1
|
72
94
|
end
|
95
|
+
hash[:option] = option if !option.empty?
|
73
96
|
hash
|
74
97
|
end
|
75
98
|
#:startdoc:
|
@@ -8,6 +8,8 @@ module Boson
|
|
8
8
|
attr_reader :mod_store
|
9
9
|
@mod_store ||= {}
|
10
10
|
METHODS = [:config, :desc, :options, :render_options]
|
11
|
+
METHOD_CLASSES = {:config=>Hash, :desc=>String, :options=>Hash, :render_options=>Hash}
|
12
|
+
ALL_METHODS = METHODS + [:option]
|
11
13
|
|
12
14
|
# The method_added used while scraping method attributes.
|
13
15
|
def new_method_added(mod, meth)
|
@@ -17,8 +19,9 @@ module Boson
|
|
17
19
|
METHODS.each do |e|
|
18
20
|
store[e][meth.to_s] = store[:temp][e] if store[:temp][e]
|
19
21
|
end
|
22
|
+
(store[:options][meth.to_s] ||= {}).merge! store[:temp][:option] if store[:temp][:option]
|
20
23
|
|
21
|
-
if store[:temp].size <
|
24
|
+
if store[:temp].size < ALL_METHODS.size
|
22
25
|
store[:method_locations] ||= {}
|
23
26
|
if (result = find_method_locations(caller))
|
24
27
|
store[:method_locations][meth.to_s] = result
|
@@ -35,6 +38,12 @@ module Boson
|
|
35
38
|
end
|
36
39
|
end
|
37
40
|
|
41
|
+
def option(mod, name, value)
|
42
|
+
(@mod_store[mod] ||= {})[:options] ||= {}
|
43
|
+
(store(mod)[:temp] ||= {})[:option] ||= {}
|
44
|
+
(store(mod)[:temp] ||= {})[:option][name] = value
|
45
|
+
end
|
46
|
+
|
38
47
|
# Scrapes a method's arguments using ArgumentInspector.
|
39
48
|
def scrape_arguments(meth)
|
40
49
|
store[:args] ||= {}
|
@@ -9,11 +9,11 @@
|
|
9
9
|
# >> Dir.pwd
|
10
10
|
# >> '/home'
|
11
11
|
class Boson::RequireLibrary < Boson::GemLibrary
|
12
|
+
EXTENSIONS = ['', '.rb', '.rbw', '.so', '.bundle', '.dll', '.sl', '.jar']
|
12
13
|
handles {|source|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
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
18
|
}
|
19
19
|
end
|
data/lib/boson/manager.rb
CHANGED
@@ -40,15 +40,20 @@ module Boson
|
|
40
40
|
def rescue_load_action(library, load_method)
|
41
41
|
yield
|
42
42
|
rescue AppendFeaturesFalseError
|
43
|
+
warn "DEBUG: Library #{library} didn't load due to append_features" if Runner.debug
|
43
44
|
rescue LoaderError=>e
|
44
45
|
FileLibrary.reset_file_cache(library.to_s)
|
45
46
|
failed_libraries << library
|
46
47
|
$stderr.puts "Unable to #{load_method} library #{library}. Reason: #{e.message}"
|
47
|
-
rescue StandardError=>e
|
48
|
+
rescue StandardError, SyntaxError, LoadError =>e
|
48
49
|
FileLibrary.reset_file_cache(library.to_s)
|
49
50
|
failed_libraries << library
|
50
51
|
message = "Unable to #{load_method} library #{library}. Reason: #{$!}"
|
51
|
-
|
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
|
52
57
|
$stderr.puts message
|
53
58
|
ensure
|
54
59
|
Inspector.disable if Inspector.enabled
|
@@ -143,7 +148,7 @@ module Boson
|
|
143
148
|
end
|
144
149
|
|
145
150
|
def create_class_aliases(mod, class_commands)
|
146
|
-
class_commands.each {|k,v|
|
151
|
+
class_commands.dup.each {|k,v|
|
147
152
|
if v.is_a?(Array)
|
148
153
|
class_commands.delete(k).each {|e| class_commands[e] = "#{k}.#{e}"}
|
149
154
|
end
|
data/lib/boson/pipes.rb
CHANGED
@@ -43,7 +43,11 @@ module Boson
|
|
43
43
|
def sort_pipe(object, sort)
|
44
44
|
sort_lambda = lambda {}
|
45
45
|
if object[0].is_a?(Hash)
|
46
|
-
|
46
|
+
if sort.to_s[/^\d+$/]
|
47
|
+
sort = sort.to_i
|
48
|
+
elsif object[0].keys.all? {|e| e.is_a?(Symbol) }
|
49
|
+
sort = sort.to_sym
|
50
|
+
end
|
47
51
|
sort_lambda = untouched_sort?(object.map {|e| e[sort] }) ? lambda {|e| e[sort] } : lambda {|e| e[sort].to_s }
|
48
52
|
else
|
49
53
|
sort_lambda = untouched_sort?(object.map {|e| e.send(sort) }) ? lambda {|e| e.send(sort) || ''} :
|
data/lib/boson/runner.rb
CHANGED
@@ -45,7 +45,10 @@ module Boson
|
|
45
45
|
:unload=>{:type=>:string, :desc=>"Acts as a regular expression to unload default libraries"},
|
46
46
|
:render=>{:type=>:boolean, :desc=>"Renders a Hirb view from result of command without options"},
|
47
47
|
:pager_toggle=>{:type=>:boolean, :desc=>"Toggles Hirb's pager"},
|
48
|
-
:option_commands=>{:type=>:boolean, :desc=>"Toggles on all commands to be defined as option commands" }
|
48
|
+
:option_commands=>{:type=>:boolean, :desc=>"Toggles on all commands to be defined as option commands" },
|
49
|
+
:ruby_debug=>{:type=>:boolean, :desc=>"Sets $DEBUG", :alias=>'D'},
|
50
|
+
:debug=>{:type=>:boolean, :desc=>"Prints debug info for boson"},
|
51
|
+
:load_path=>{:type=>:string, :desc=>"Add to front of $LOAD_PATH", :alias=>'I'}
|
49
52
|
} #:nodoc:
|
50
53
|
|
51
54
|
PIPE = '+'
|
@@ -58,7 +61,10 @@ module Boson
|
|
58
61
|
@command, @options, @args = parse_args(args)
|
59
62
|
return puts("boson #{Boson::VERSION}") if @options[:version]
|
60
63
|
return print_usage if args.empty? || (@command.nil? && !@options[:console] && !@options[:execute])
|
64
|
+
$:.unshift(*options[:load_path].split(":")) if options[:load_path]
|
65
|
+
Runner.debug = true if @options[:debug]
|
61
66
|
return ConsoleRunner.bin_start(@options[:console], @options[:load]) if @options[:console]
|
67
|
+
$DEBUG = true if options[:ruby_debug]
|
62
68
|
init
|
63
69
|
|
64
70
|
if @options[:help]
|
@@ -71,9 +77,9 @@ module Boson
|
|
71
77
|
execute_command
|
72
78
|
end
|
73
79
|
rescue NoMethodError
|
74
|
-
|
80
|
+
abort_with no_method_error_message
|
75
81
|
rescue
|
76
|
-
|
82
|
+
abort_with default_error_message
|
77
83
|
end
|
78
84
|
|
79
85
|
def no_method_error_message #:nodoc:
|
@@ -114,10 +120,11 @@ module Boson
|
|
114
120
|
def commands
|
115
121
|
@commands ||= @all_args.map {|e| e[0]}
|
116
122
|
end
|
123
|
+
|
117
124
|
#:stopdoc:
|
118
|
-
def
|
125
|
+
def abort_with(message)
|
119
126
|
message += "\nOriginal error: #{$!}\n" + $!.backtrace.slice(0,10).map {|e| " " + e }.join("\n") if options[:verbose]
|
120
|
-
|
127
|
+
abort message
|
121
128
|
end
|
122
129
|
|
123
130
|
def default_error_message
|
@@ -149,9 +156,7 @@ module Boson
|
|
149
156
|
rescue ArgumentError
|
150
157
|
if $!.class == OptionCommand::CommandArgumentError || ($!.message[/wrong number of arguments/] &&
|
151
158
|
(cmd_obj = Command.find(cmd)) && cmd_obj.arg_size != args.size)
|
152
|
-
|
153
|
-
Boson.invoke(:usage, cmd, :one_line=>true)
|
154
|
-
return
|
159
|
+
abort_with "'#{cmd}' was called incorrectly.\n" + Command.usage(cmd)
|
155
160
|
else
|
156
161
|
raise
|
157
162
|
end
|
@@ -24,10 +24,16 @@ module Boson
|
|
24
24
|
repl = Boson.repo.config[:console] if Boson.repo.config[:console]
|
25
25
|
repl = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb' unless repl.is_a?(String)
|
26
26
|
unless repl.index('/') == 0 || (repl = Util.which(repl))
|
27
|
-
|
28
|
-
|
27
|
+
abort "Console not found. Please specify full path in config[:console]."
|
28
|
+
else
|
29
|
+
load_repl(repl)
|
29
30
|
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def load_repl(repl) #:nodoc:
|
30
34
|
ARGV.replace ['-f']
|
35
|
+
$progname = $0
|
36
|
+
alias $0 $progname
|
31
37
|
Kernel.load $0 = repl
|
32
38
|
end
|
33
39
|
|
data/lib/boson/scientist.rb
CHANGED
@@ -147,7 +147,7 @@ module Boson
|
|
147
147
|
def run_help_option
|
148
148
|
opts = @global_options[:verbose] ? ['--verbose'] : []
|
149
149
|
opts << "--render_options=#{@global_options[:usage_options]}" if @global_options[:usage_options]
|
150
|
-
Boson.invoke :usage, @command.
|
150
|
+
Boson.invoke :usage, @command.full_name + " " + opts.join(' ')
|
151
151
|
end
|
152
152
|
|
153
153
|
def run_pretend_option(args)
|
data/lib/boson/version.rb
CHANGED
data/test/bin_runner_test.rb
CHANGED
@@ -19,7 +19,7 @@ describe "BinRunner" do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
it "invalid option value prints error" do
|
22
|
-
|
22
|
+
aborts_with(/Error: no value/) { start("-l") }
|
23
23
|
end
|
24
24
|
|
25
25
|
it "help option but no arguments prints usage" do
|
@@ -36,17 +36,18 @@ describe "BinRunner" do
|
|
36
36
|
start('-l', 'blah', 'libraries')
|
37
37
|
end
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
39
|
+
it "console option starts irb" do
|
40
|
+
ConsoleRunner.expects(:start)
|
41
|
+
Util.expects(:which).returns("/usr/bin/irb")
|
42
|
+
ConsoleRunner.expects(:load_repl).with("/usr/bin/irb")
|
43
|
+
start("--console")
|
44
|
+
end
|
45
45
|
|
46
46
|
it "console option but no irb found prints error" do
|
47
47
|
ConsoleRunner.expects(:start)
|
48
48
|
Util.expects(:which).returns(nil)
|
49
|
-
|
49
|
+
ConsoleRunner.expects(:abort).with {|arg| arg[/Console not found/] }
|
50
|
+
start '--console'
|
50
51
|
end
|
51
52
|
|
52
53
|
it "execute option executes string" do
|
@@ -59,34 +60,48 @@ describe "BinRunner" do
|
|
59
60
|
start('commands', '-f', 'f1, f2')
|
60
61
|
end
|
61
62
|
|
63
|
+
it "debug option sets Runner.debug" do
|
64
|
+
View.expects(:render)
|
65
|
+
start('-d', 'commands')
|
66
|
+
Runner.debug.should == true
|
67
|
+
Runner.debug = nil
|
68
|
+
end
|
69
|
+
|
70
|
+
it "ruby_debug option sets $DEBUG" do
|
71
|
+
View.expects(:render)
|
72
|
+
start('-D', 'commands')
|
73
|
+
$DEBUG.should == true
|
74
|
+
$DEBUG = nil
|
75
|
+
end
|
76
|
+
|
62
77
|
it "execute option errors are caught" do
|
63
|
-
|
78
|
+
aborts_with(/^Error:/) { start("-e", "raise 'blah'") }
|
64
79
|
end
|
65
80
|
|
66
81
|
it "option command and too many arguments prints error" do
|
67
82
|
capture_stdout {
|
68
|
-
|
83
|
+
aborts_with(/'commands'.*incorrect/) { start('commands','1','2','3') }
|
69
84
|
}
|
70
85
|
end
|
71
86
|
|
72
87
|
it "normal command and too many arguments prints error" do
|
73
88
|
capture_stdout {
|
74
|
-
|
89
|
+
aborts_with(/'render'.*incorrect/) { start('render') }
|
75
90
|
}
|
76
91
|
end
|
77
92
|
|
78
93
|
it "failed subcommand prints error and not command not found" do
|
79
94
|
BinRunner.expects(:execute_command).raises("bling")
|
80
|
-
|
95
|
+
aborts_with(/Error: bling/) { start("commands.to_s") }
|
81
96
|
end
|
82
97
|
|
83
98
|
it "nonexistant subcommand prints command not found" do
|
84
|
-
|
99
|
+
aborts_with(/'to_s.bling' not found/) { start("to_s.bling") }
|
85
100
|
end
|
86
101
|
|
87
102
|
it "undiscovered command prints error" do
|
88
|
-
|
89
|
-
|
103
|
+
BinRunner.expects(:autoload_command).returns(false)
|
104
|
+
aborts_with(/Error.*not found/) { start 'blah' }
|
90
105
|
end
|
91
106
|
|
92
107
|
it "basic command executes" do
|
@@ -108,7 +123,7 @@ describe "BinRunner" do
|
|
108
123
|
defaults = Runner.default_libraries + ['yo']
|
109
124
|
with_config(:bin_defaults=>['yo']) do
|
110
125
|
Manager.expects(:load).with {|*args| args[0] == defaults }
|
111
|
-
|
126
|
+
aborts_with(/blah/) { start 'blah' }
|
112
127
|
end
|
113
128
|
end
|
114
129
|
end
|
@@ -151,7 +166,7 @@ describe "BinRunner" do
|
|
151
166
|
Index.expects(:find_library).returns(nil, 'sweet_lib')
|
152
167
|
Manager.expects(:load).with {|*args| args[0].is_a?(String) ? args[0] == 'sweet_lib' : true}.at_least(1)
|
153
168
|
Index.indexes[0].expects(:update).returns(true)
|
154
|
-
|
169
|
+
aborts_with(/sweet/) { start 'sweet' }
|
155
170
|
end
|
156
171
|
end
|
157
172
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
describe "Command" do
|
4
|
+
describe ".find" do
|
5
|
+
before_all {
|
6
|
+
reset_boson
|
7
|
+
Boson.libraries << Library.new(:name=>'bling', :namespace=>true)
|
8
|
+
@namespace_command = Command.new(:name=>'blah', :lib=>'bling', :namespace=>'bling')
|
9
|
+
@top_level_command = Command.new(:name=>'blah', :lib=>'bling')
|
10
|
+
Boson.commands << @namespace_command
|
11
|
+
Boson.commands << @top_level_command
|
12
|
+
}
|
13
|
+
|
14
|
+
it 'finds correct command when a subcommand of the same name exists' do
|
15
|
+
Command.find('blah').should == @top_level_command
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'finds correct command when a top level command of the same name exists' do
|
19
|
+
Command.find('bling.blah').should == @namespace_command
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -47,39 +47,67 @@ describe "CommentInspector" do
|
|
47
47
|
}
|
48
48
|
def options(opts={})
|
49
49
|
@lines[1] = opts[:value] if opts[:value]
|
50
|
-
args = [@lines.join("\n"), 3, Optional]
|
50
|
+
args = [@lines.join("\n"), opts[:line] || 3, Optional]
|
51
51
|
CommentInspector.scrape(*args)[:options]
|
52
52
|
end
|
53
53
|
|
54
|
-
it "that are basic
|
54
|
+
it "that are basic" do
|
55
55
|
options.should == {:a=>true}
|
56
56
|
end
|
57
57
|
|
58
|
-
it "that are hash-like
|
58
|
+
it "that are hash-like" do
|
59
59
|
options(:value=>'#@options :a => 2').should == {:a=>2}
|
60
60
|
end
|
61
61
|
|
62
|
-
it "that are whitespaced
|
62
|
+
it "that are whitespaced" do
|
63
63
|
options(:value=>"\t"+ '# @options {:a=>1}').should == {:a=>1}
|
64
64
|
end
|
65
65
|
|
66
|
-
it "that have a local value
|
66
|
+
it "that have a local value" do
|
67
67
|
options(:value=>'#@options bling').should == {:a=>'bling'}
|
68
68
|
end
|
69
69
|
|
70
|
-
it "that are multi-line
|
70
|
+
it "that are multi-line" do
|
71
71
|
@lines.delete_at(1)
|
72
72
|
@lines.insert(1, '#@options {:a =>', " # 1}", "# some comments")
|
73
|
-
|
73
|
+
options(:line=>5).should == {:a=>1}
|
74
74
|
end
|
75
75
|
|
76
|
-
it "with failed eval
|
76
|
+
it "with failed eval and returns nil" do
|
77
77
|
options(:value=>'#@options !--').should == nil
|
78
78
|
end
|
79
79
|
|
80
|
-
it "that are empty
|
80
|
+
it "that are empty and returns nil" do
|
81
81
|
options(:value=>"# nada").should == nil
|
82
82
|
end
|
83
|
+
|
84
|
+
it "when @option overwrites @options" do
|
85
|
+
@lines.insert(1, ' #@option :a, :boolean')
|
86
|
+
options(:line=>4).should == {:a=>:boolean}
|
87
|
+
end
|
88
|
+
|
89
|
+
it "when set by @option and @options" do
|
90
|
+
@lines.insert(1, ' #@option :b, :boolean')
|
91
|
+
options(:line=>4).should == {:b=>:boolean, :a=>true}
|
92
|
+
end
|
93
|
+
|
94
|
+
it "when set by @option" do
|
95
|
+
@lines.delete_at(1)
|
96
|
+
@lines.insert(1, ' #@option :b, :string', ' #@option :a, 4')
|
97
|
+
options(:line=>4).should == {:b=>:string, :a=>4}
|
98
|
+
end
|
99
|
+
|
100
|
+
it "when set by multi-line @option" do
|
101
|
+
@lines.delete_at(1)
|
102
|
+
@lines.insert(1, ' #@option :b, :type=>:string,', ' # :values=>%w{one two}', '# some comments')
|
103
|
+
options(:line=>5).should == {:b=>{:type=>:string, :values=>%w{one two}}}
|
104
|
+
end
|
105
|
+
|
106
|
+
it "and ignores invalid @option's" do
|
107
|
+
@lines.delete_at(1)
|
108
|
+
@lines.insert(1, ' #@option :b=>:string', ' #@option :a, :string')
|
109
|
+
options(:line=>4).should == {:a=>:string}
|
110
|
+
end
|
83
111
|
end
|
84
112
|
|
85
113
|
it "scrapes all comment types with implicit desc" do
|
data/test/deps.rip
ADDED
data/test/file_library_test.rb
CHANGED
@@ -2,7 +2,7 @@ require File.join(File.dirname(__FILE__), 'test_helper')
|
|
2
2
|
|
3
3
|
describe "file library" do
|
4
4
|
before { reset; FileLibrary.reset_file_cache }
|
5
|
-
before { Gem.stubs(:loaded_specs).returns({}) } if RUBY_VERSION >= '1.9.2'
|
5
|
+
before { Gem.stubs(:loaded_specs).returns({}) } if RUBY_VERSION >= '1.9.2' && defined? Gem
|
6
6
|
|
7
7
|
it "loads" do
|
8
8
|
load :blah, :file_string=>"module Blah; def blah; end; end"
|
data/test/loader_test.rb
CHANGED
@@ -5,7 +5,7 @@ describe "Loader" do
|
|
5
5
|
Manager.load([Boson::Commands::Namespace])
|
6
6
|
end
|
7
7
|
|
8
|
-
before { Gem.stubs(:loaded_specs).returns({}) } if RUBY_VERSION >= '1.9.2'
|
8
|
+
before { Gem.stubs(:loaded_specs).returns({}) } if RUBY_VERSION >= '1.9.2' && defined? Gem
|
9
9
|
describe "config" do
|
10
10
|
before { reset }
|
11
11
|
it "from callback overridden by user's config" do
|
data/test/manager_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
2
|
|
3
3
|
describe "Manager" do
|
4
|
-
describe "after_load" do
|
4
|
+
describe ".after_load" do
|
5
5
|
def load_library(hash)
|
6
6
|
new_attributes = {:name=>hash[:name], :commands=>[], :created_dependencies=>[], :loaded=>true}
|
7
7
|
[:module, :commands].each {|e| new_attributes[e] = hash.delete(e) if hash[e] }
|
@@ -23,6 +23,20 @@ describe "Manager" do
|
|
23
23
|
command_exists?('meatwad')
|
24
24
|
end
|
25
25
|
|
26
|
+
it "prints error for library with SyntaxError" do
|
27
|
+
Manager.expects(:loader_create).raises(SyntaxError)
|
28
|
+
capture_stderr {
|
29
|
+
Manager.load 'blah'
|
30
|
+
}.should =~ /Unable to load library blah. Reason: SyntaxError/
|
31
|
+
end
|
32
|
+
|
33
|
+
it "prints error for library with LoadError" do
|
34
|
+
Manager.expects(:loader_create).raises(LoadError)
|
35
|
+
capture_stderr {
|
36
|
+
Manager.load 'blah'
|
37
|
+
}.should =~ /Unable to load library blah. Reason: LoadError/
|
38
|
+
end
|
39
|
+
|
26
40
|
describe "command aliases" do
|
27
41
|
before { eval %[module ::Aquateen; def frylock; end; end] }
|
28
42
|
after { Object.send(:remove_const, "Aquateen") }
|
@@ -84,7 +98,7 @@ describe "Manager" do
|
|
84
98
|
end
|
85
99
|
end
|
86
100
|
|
87
|
-
describe "loaded" do
|
101
|
+
describe ".loaded?" do
|
88
102
|
before { reset_libraries }
|
89
103
|
|
90
104
|
it "returns false when library isn't loaded" do
|
@@ -31,6 +31,21 @@ describe "MethodInspector" do
|
|
31
31
|
parse("options :z=>'b'; def zee; end")[:options].should == {"zee"=>{:z=>'b'}}
|
32
32
|
end
|
33
33
|
|
34
|
+
it "option sets options" do
|
35
|
+
parse("option :z, 'b'; option :y, :boolean; def zee; end")[:options].should ==
|
36
|
+
{"zee"=>{:z=>'b', :y=>:boolean}}
|
37
|
+
end
|
38
|
+
|
39
|
+
it "option(s) sets options" do
|
40
|
+
parse("options :z=>'b'; option :y, :string; def zee; end")[:options].should ==
|
41
|
+
{"zee"=>{:z=>'b', :y=>:string}}
|
42
|
+
end
|
43
|
+
|
44
|
+
it "option(s) option overrides options" do
|
45
|
+
parse("options :z=>'b'; option :z, :string; def zee; end")[:options].should ==
|
46
|
+
{"zee"=>{:z=>:string}}
|
47
|
+
end
|
48
|
+
|
34
49
|
it "render_options sets render_options" do
|
35
50
|
parse("render_options :z=>true; def zee; end")[:render_options].should == {"zee"=>{:z=>true}}
|
36
51
|
end
|
@@ -42,7 +57,7 @@ describe "MethodInspector" do
|
|
42
57
|
it "not all method attributes set causes method_locations to be set" do
|
43
58
|
MethodInspector.stubs(:find_method_locations).returns(["/some/path", 10])
|
44
59
|
parsed = parse "desc 'yo'; def yo; end; options :yep=>1; def yep; end; " +
|
45
|
-
"render_options :a=>1; config :a=>1; desc 'z'; options :a=>1; def az; end"
|
60
|
+
"option :b, :boolean; render_options :a=>1; config :a=>1; desc 'z'; options :a=>1; def az; end"
|
46
61
|
parsed[:method_locations].key?('yo').should == true
|
47
62
|
parsed[:method_locations].key?('yep').should == true
|
48
63
|
parsed[:method_locations].key?('az').should == false
|
data/test/pipes_test.rb
CHANGED
@@ -49,6 +49,15 @@ describe "Pipes" do
|
|
49
49
|
Pipes.sort_pipe(hashes, :a).should == hashes.reverse
|
50
50
|
end
|
51
51
|
|
52
|
+
it "sorts numeric hash keys by string" do
|
53
|
+
hashes = [{2=>'thing'}, {2=>'some'}]
|
54
|
+
Pipes.sort_pipe(hashes, '2').should == hashes.reverse
|
55
|
+
end
|
56
|
+
|
57
|
+
it "sorts numeric hash keys by string" do
|
58
|
+
Pipes.sort_pipe(@hashes, 'a').should == @hashes.reverse
|
59
|
+
end
|
60
|
+
|
52
61
|
it "prints error for invalid sort field" do
|
53
62
|
capture_stderr { Pipes.sort_pipe(@objects, :blah)}.should =~ /failed.*'blah'/
|
54
63
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
require 'mocha'
|
2
1
|
require 'bacon'
|
3
|
-
require
|
2
|
+
require 'bacon/bits'
|
4
3
|
require 'mocha'
|
5
4
|
require 'mocha-on-bacon'
|
6
5
|
require 'boson'
|
@@ -119,9 +118,13 @@ module TestHelpers
|
|
119
118
|
Manager.add_library(lib); lib
|
120
119
|
}
|
121
120
|
end
|
121
|
+
|
122
|
+
def aborts_with(regex)
|
123
|
+
BinRunner.expects(:abort).with {|e| e[regex] }
|
124
|
+
yield
|
125
|
+
end
|
122
126
|
end
|
123
127
|
|
124
128
|
class Bacon::Context
|
125
129
|
include TestHelpers
|
126
|
-
|
127
|
-
end
|
130
|
+
end
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: boson
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 19
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 0.3.0
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Gabriel Horner
|
@@ -14,7 +15,7 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2010-
|
18
|
+
date: 2010-08-13 00:00:00 -04:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
@@ -25,6 +26,7 @@ dependencies:
|
|
25
26
|
requirements:
|
26
27
|
- - ">="
|
27
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 23
|
28
30
|
segments:
|
29
31
|
- 0
|
30
32
|
- 3
|
@@ -40,14 +42,73 @@ dependencies:
|
|
40
42
|
requirements:
|
41
43
|
- - ">="
|
42
44
|
- !ruby/object:Gem::Version
|
45
|
+
hash: 19
|
43
46
|
segments:
|
44
47
|
- 0
|
45
48
|
- 2
|
46
|
-
-
|
47
|
-
version: 0.2.
|
49
|
+
- 2
|
50
|
+
version: 0.2.2
|
48
51
|
type: :runtime
|
49
52
|
version_requirements: *id002
|
50
|
-
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: mocha
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 3
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
type: :development
|
66
|
+
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: bacon
|
69
|
+
prerelease: false
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 19
|
76
|
+
segments:
|
77
|
+
- 1
|
78
|
+
- 1
|
79
|
+
- 0
|
80
|
+
version: 1.1.0
|
81
|
+
type: :development
|
82
|
+
version_requirements: *id004
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: mocha-on-bacon
|
85
|
+
prerelease: false
|
86
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 3
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
version: "0"
|
95
|
+
type: :development
|
96
|
+
version_requirements: *id005
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: bacon-bits
|
99
|
+
prerelease: false
|
100
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
hash: 3
|
106
|
+
segments:
|
107
|
+
- 0
|
108
|
+
version: "0"
|
109
|
+
type: :development
|
110
|
+
version_requirements: *id006
|
111
|
+
description: Boson is a command/task framework with the power to turn any ruby method into a full-fledged executable with options. Some unique features that differentiate it from rake and thor include being usable from irb and the commandline, optional automated views generated by hirb and allowing libraries to be written as plain ruby. For my libraries that use this, see irbfiles. Works with all major ruby versions.
|
51
112
|
email: gabriel.horner@gmail.com
|
52
113
|
executables:
|
53
114
|
- boson
|
@@ -91,8 +152,8 @@ files:
|
|
91
152
|
- lib/boson/view.rb
|
92
153
|
- lib/boson.rb
|
93
154
|
- test/argument_inspector_test.rb
|
94
|
-
- test/bacon_extensions.rb
|
95
155
|
- test/bin_runner_test.rb
|
156
|
+
- test/command_test.rb
|
96
157
|
- test/comment_inspector_test.rb
|
97
158
|
- test/file_library_test.rb
|
98
159
|
- test/loader_test.rb
|
@@ -111,12 +172,14 @@ files:
|
|
111
172
|
- LICENSE.txt
|
112
173
|
- CHANGELOG.rdoc
|
113
174
|
- README.rdoc
|
175
|
+
- deps.rip
|
176
|
+
- test/deps.rip
|
114
177
|
- Rakefile
|
115
|
-
- gemspec
|
178
|
+
- .gemspec
|
116
179
|
has_rdoc: true
|
117
180
|
homepage: http://tagaholic.me/boson/
|
118
|
-
licenses:
|
119
|
-
|
181
|
+
licenses:
|
182
|
+
- MIT
|
120
183
|
post_install_message:
|
121
184
|
rdoc_options: []
|
122
185
|
|
@@ -127,6 +190,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
127
190
|
requirements:
|
128
191
|
- - ">="
|
129
192
|
- !ruby/object:Gem::Version
|
193
|
+
hash: 3
|
130
194
|
segments:
|
131
195
|
- 0
|
132
196
|
version: "0"
|
@@ -135,6 +199,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
199
|
requirements:
|
136
200
|
- - ">="
|
137
201
|
- !ruby/object:Gem::Version
|
202
|
+
hash: 23
|
138
203
|
segments:
|
139
204
|
- 1
|
140
205
|
- 3
|
data/test/bacon_extensions.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
module BaconExtensions
|
2
|
-
def self.included(mod)
|
3
|
-
mod.module_eval do
|
4
|
-
# nested context methods automatically inherit methods from parent contexts
|
5
|
-
def describe(*args, &block)
|
6
|
-
context = Bacon::Context.new(args.join(' '), &block)
|
7
|
-
(parent_context = self).methods(false).each {|e|
|
8
|
-
class<<context; self end.send(:define_method, e) {|*args| parent_context.send(e, *args)}
|
9
|
-
}
|
10
|
-
@before.each { |b| context.before(&b) }
|
11
|
-
@after.each { |b| context.after(&b) }
|
12
|
-
context.run
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def xit(*args); end
|
18
|
-
def xdescribe(*args); end
|
19
|
-
def before_all; yield; end
|
20
|
-
def after_all; yield; end
|
21
|
-
def assert(description, &block)
|
22
|
-
it(description) do
|
23
|
-
block.call.should == true
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|