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,182 @@
|
|
1
|
+
module Boson
|
2
|
+
# Scientist wraps around and redefines an object's method to give it the following features:
|
3
|
+
# * Methods can take shell command input with options or receive its normal arguments. See the Commandification
|
4
|
+
# section.
|
5
|
+
# * Methods have a slew of global options available. See OptionCommand for an explanation of basic global options.
|
6
|
+
# * Before a method returns its value, it pipes its return value through pipe commands if pipe options are specified. See Pipe.
|
7
|
+
# * Methods can have any number of optional views associated with them via global render options (see View). Views can be toggled
|
8
|
+
# on/off with the global option --render (see OptionCommand).
|
9
|
+
#
|
10
|
+
# The main methods Scientist provides are redefine_command() for redefining an object's method with a Command object
|
11
|
+
# and commandify() for redefining with a hash of method attributes. Note that for an object's method to be redefined correctly,
|
12
|
+
# its last argument _must_ expect a hash.
|
13
|
+
#
|
14
|
+
# === Commandification
|
15
|
+
# Take for example this basic method/command with an options definition:
|
16
|
+
# options :level=>:numeric, :verbose=>:boolean
|
17
|
+
# def foo(*args)
|
18
|
+
# args
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# When Scientist wraps around foo(), it can take arguments normally or as a shell command:
|
22
|
+
# foo 'one', 'two', :verbose=>true # normal call
|
23
|
+
# foo 'one two -v' # commandline call
|
24
|
+
#
|
25
|
+
# Both calls return: ['one', 'two', {:verbose=>true}]
|
26
|
+
#
|
27
|
+
# Non-string arguments can be passed as well:
|
28
|
+
# foo Object, 'two', :level=>1
|
29
|
+
# foo Object, 'two -l1'
|
30
|
+
#
|
31
|
+
# Both calls return: [Object, 'two', {:level=>1}]
|
32
|
+
module Scientist
|
33
|
+
extend self
|
34
|
+
# Handles all Scientist errors.
|
35
|
+
class Error < StandardError; end
|
36
|
+
|
37
|
+
attr_accessor :global_options, :rendered, :render
|
38
|
+
@no_option_commands ||= []
|
39
|
+
@option_commands ||= {}
|
40
|
+
@object_methods = {}
|
41
|
+
|
42
|
+
# Redefines an object's method with a Command of the same name.
|
43
|
+
def redefine_command(obj, command)
|
44
|
+
cmd_block = redefine_command_block(obj, command)
|
45
|
+
@no_option_commands << command if command.options.nil?
|
46
|
+
[command.name, command.alias].compact.each {|e|
|
47
|
+
obj.instance_eval("class<<self;self;end").send(:define_method, e, cmd_block)
|
48
|
+
}
|
49
|
+
rescue Error
|
50
|
+
$stderr.puts "Error: #{$!.message}"
|
51
|
+
end
|
52
|
+
|
53
|
+
# A wrapper around redefine_command that doesn't depend on a Command object. Rather you
|
54
|
+
# simply pass a hash of command attributes (see Command.new) or command methods and let OpenStruct mock a command.
|
55
|
+
# The only required attribute is :name, though to get any real use you should define :options and
|
56
|
+
# :arg_size (default is '*'). Example:
|
57
|
+
# >> def checkit(*args); args; end
|
58
|
+
# => nil
|
59
|
+
# >> Boson::Scientist.commandify(self, :name=>'checkit', :options=>{:verbose=>:boolean, :num=>:numeric})
|
60
|
+
# => ['checkit']
|
61
|
+
# # regular ruby method
|
62
|
+
# >> checkit 'one', 'two', :num=>13, :verbose=>true
|
63
|
+
# => ["one", "two", {:num=>13, :verbose=>true}]
|
64
|
+
# # commandline ruby method
|
65
|
+
# >> checkit 'one two -v -n=13'
|
66
|
+
# => ["one", "two", {:num=>13, :verbose=>true}]
|
67
|
+
def commandify(obj, hash)
|
68
|
+
raise ArgumentError, ":name required" unless hash[:name]
|
69
|
+
hash[:arg_size] ||= '*'
|
70
|
+
hash[:has_splat_args?] = true if hash[:arg_size] == '*'
|
71
|
+
fake_cmd = OpenStruct.new(hash)
|
72
|
+
fake_cmd.option_parser ||= OptionParser.new(fake_cmd.options || {})
|
73
|
+
redefine_command(obj, fake_cmd)
|
74
|
+
end
|
75
|
+
|
76
|
+
# The actual method which redefines a command's original method
|
77
|
+
def redefine_command_block(obj, command)
|
78
|
+
object_methods(obj)[command.name] ||= begin
|
79
|
+
obj.method(command.name)
|
80
|
+
rescue NameError
|
81
|
+
raise Error, "No method exists to redefine command '#{command.name}'."
|
82
|
+
end
|
83
|
+
lambda {|*args|
|
84
|
+
Scientist.translate_and_render(obj, command, args) {|args|
|
85
|
+
Scientist.object_methods(obj)[command.name].call(*args)
|
86
|
+
}
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
#:stopdoc:
|
91
|
+
def object_methods(obj)
|
92
|
+
@object_methods[obj] ||= {}
|
93
|
+
end
|
94
|
+
|
95
|
+
def option_command(cmd=@command)
|
96
|
+
@option_commands[cmd] ||= OptionCommand.new(cmd)
|
97
|
+
end
|
98
|
+
|
99
|
+
def call_original_command(args, &block)
|
100
|
+
block.call(args)
|
101
|
+
end
|
102
|
+
|
103
|
+
def translate_and_render(obj, command, args, &block)
|
104
|
+
@global_options, @command, original_args = {}, command, args.dup
|
105
|
+
@args = translate_args(obj, args)
|
106
|
+
return run_help_option if @global_options[:help]
|
107
|
+
run_pretend_option(@args)
|
108
|
+
render_or_raw call_original_command(@args, &block) unless @global_options[:pretend]
|
109
|
+
rescue OptionCommand::CommandArgumentError
|
110
|
+
run_pretend_option(@args ||= [])
|
111
|
+
return if !@global_options[:pretend] && run_verbose_help(option_command, original_args)
|
112
|
+
raise unless @global_options[:pretend]
|
113
|
+
rescue OptionParser::Error, Error
|
114
|
+
raise if Runner.in_shell?
|
115
|
+
message = @global_options[:verbose] ? "#{$!}\n#{$!.backtrace.inspect}" : $!.message
|
116
|
+
$stderr.puts "Error: " + message
|
117
|
+
end
|
118
|
+
|
119
|
+
def translate_args(obj, args)
|
120
|
+
option_command.modify_args(args)
|
121
|
+
@global_options, @current_options, args = option_command.parse(args)
|
122
|
+
return if @global_options[:help]
|
123
|
+
|
124
|
+
(@global_options[:delete_options] || []).map {|e|
|
125
|
+
@global_options.keys.map {|k| k.to_s }.grep(/^#{e}/)
|
126
|
+
}.flatten.each {|e| @global_options.delete(e.to_sym) }
|
127
|
+
|
128
|
+
if @current_options
|
129
|
+
option_command.add_default_args(args, obj)
|
130
|
+
return args if @no_option_commands.include?(@command)
|
131
|
+
args << @current_options
|
132
|
+
option_command.check_argument_size(args)
|
133
|
+
end
|
134
|
+
args
|
135
|
+
end
|
136
|
+
|
137
|
+
def run_verbose_help(option_command, original_args)
|
138
|
+
global_opts = option_command.parse_global_options(original_args)
|
139
|
+
if global_opts[:help] && global_opts[:verbose]
|
140
|
+
@global_options = global_opts
|
141
|
+
run_help_option
|
142
|
+
return true
|
143
|
+
end
|
144
|
+
false
|
145
|
+
end
|
146
|
+
|
147
|
+
def run_help_option
|
148
|
+
opts = @global_options[:verbose] ? ['--verbose'] : []
|
149
|
+
opts << "--render_options=#{@global_options[:usage_options]}" if @global_options[:usage_options]
|
150
|
+
Boson.invoke :usage, @command.full_name + " " + opts.join(' ')
|
151
|
+
end
|
152
|
+
|
153
|
+
def run_pretend_option(args)
|
154
|
+
if @global_options[:verbose] || @global_options[:pretend]
|
155
|
+
puts "Arguments: #{args.inspect}", "Global options: #{@global_options.inspect}"
|
156
|
+
end
|
157
|
+
@rendered = true if @global_options[:pretend]
|
158
|
+
end
|
159
|
+
|
160
|
+
def render_or_raw(result)
|
161
|
+
if (@rendered = can_render?)
|
162
|
+
if @global_options.key?(:class) || @global_options.key?(:method)
|
163
|
+
result = Pipe.scientist_process(result, @global_options, :config=>@command.config, :args=>@args, :options=>@current_options)
|
164
|
+
end
|
165
|
+
View.render(result, OptionCommand.delete_non_render_options(@global_options.dup), false)
|
166
|
+
else
|
167
|
+
Pipe.scientist_process(result, @global_options, :config=>@command.config, :args=>@args, :options=>@current_options)
|
168
|
+
end
|
169
|
+
rescue StandardError
|
170
|
+
raise Error, $!.message, $!.backtrace
|
171
|
+
end
|
172
|
+
|
173
|
+
def can_render?
|
174
|
+
render.nil? ? command_renders? : render
|
175
|
+
end
|
176
|
+
|
177
|
+
def command_renders?
|
178
|
+
(!!@command.render_options ^ @global_options[:render]) && !Pipe.any_no_render_pipes?(@global_options)
|
179
|
+
end
|
180
|
+
#:startdoc:
|
181
|
+
end
|
182
|
+
end
|
data/lib/boson/util.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
module Boson
|
2
|
+
# Collection of utility methods used throughout Boson.
|
3
|
+
module Util
|
4
|
+
extend self
|
5
|
+
# From Rails ActiveSupport, converts a camelcased string to an underscored string:
|
6
|
+
# 'Boson::MethodInspector' -> 'boson/method_inspector'
|
7
|
+
def underscore(camel_cased_word)
|
8
|
+
camel_cased_word.to_s.gsub(/::/, '/').
|
9
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
10
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
11
|
+
tr("-", "_").
|
12
|
+
downcase
|
13
|
+
end
|
14
|
+
|
15
|
+
# From Rails ActiveSupport, does the reverse of underscore:
|
16
|
+
# 'boson/method_inspector' -> 'Boson::MethodInspector'
|
17
|
+
def camelize(string)
|
18
|
+
Hirb::Util.camelize(string)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Converts a module/class string to the actual constant.
|
22
|
+
# Returns nil if not found.
|
23
|
+
def constantize(string)
|
24
|
+
any_const_get(camelize(string))
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns a constant like const_get() no matter what namespace it's nested in.
|
28
|
+
# Returns nil if the constant is not found.
|
29
|
+
def any_const_get(name)
|
30
|
+
Hirb::Util.any_const_get(name)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Detects new object/kernel methods, gems and modules created within a block.
|
34
|
+
# Returns a hash of what's detected.
|
35
|
+
# Valid options and possible returned keys are :methods, :object_methods, :modules, :gems.
|
36
|
+
def detect(options={}, &block)
|
37
|
+
options = {:methods=>true, :object_methods=>true}.merge!(options)
|
38
|
+
original_gems = Object.const_defined?(:Gem) ? Gem.loaded_specs.keys : []
|
39
|
+
original_object_methods = Object.instance_methods
|
40
|
+
original_instance_methods = class << Boson.main_object; instance_methods end
|
41
|
+
original_modules = modules if options[:modules]
|
42
|
+
block.call
|
43
|
+
detected = {}
|
44
|
+
detected[:methods] = options[:methods] ? (class << Boson.main_object; instance_methods end -
|
45
|
+
original_instance_methods) : []
|
46
|
+
detected[:methods] -= (Object.instance_methods - original_object_methods) unless options[:object_methods]
|
47
|
+
detected[:gems] = Gem.loaded_specs.keys - original_gems if Object.const_defined? :Gem
|
48
|
+
detected[:modules] = modules - original_modules if options[:modules]
|
49
|
+
detected
|
50
|
+
end
|
51
|
+
|
52
|
+
# Safely calls require, returning false if LoadError occurs.
|
53
|
+
def safe_require(lib)
|
54
|
+
begin
|
55
|
+
require lib
|
56
|
+
true
|
57
|
+
rescue LoadError
|
58
|
+
false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns all modules that currently exist.
|
63
|
+
def modules
|
64
|
+
all_modules = []
|
65
|
+
ObjectSpace.each_object(Module) {|e| all_modules << e}
|
66
|
+
all_modules
|
67
|
+
end
|
68
|
+
|
69
|
+
# Creates a module under a given base module and possible name. If the module already exists or conflicts
|
70
|
+
# per top_level_class_conflict, it attempts to create one with a number appended to the name.
|
71
|
+
def create_module(base_module, name)
|
72
|
+
desired_class = camelize(name)
|
73
|
+
possible_suffixes = [''] + %w{1 2 3 4 5 6 7 8 9 10}
|
74
|
+
if (suffix = possible_suffixes.find {|e| !base_module.const_defined?(desired_class+e) &&
|
75
|
+
!top_level_class_conflict(base_module, "#{base_module}::#{desired_class}#{e}") })
|
76
|
+
base_module.const_set(desired_class+suffix, Module.new)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Behaves just like the unix which command, returning the full path to an executable based on ENV['PATH'].
|
81
|
+
def which(command)
|
82
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).map {|e| File.join(e, command) }.find {|e| File.exists?(e) }
|
83
|
+
end
|
84
|
+
|
85
|
+
# Deep copies any object if it can be marshaled. Useful for deep hashes.
|
86
|
+
def deep_copy(obj)
|
87
|
+
Marshal::load(Marshal::dump(obj))
|
88
|
+
end
|
89
|
+
|
90
|
+
# Recursively merge hash1 with hash2.
|
91
|
+
def recursive_hash_merge(hash1, hash2)
|
92
|
+
hash1.merge(hash2) {|k,o,n| (o.is_a?(Hash)) ? recursive_hash_merge(o,n) : n}
|
93
|
+
end
|
94
|
+
|
95
|
+
# From Rubygems, determine a user's home.
|
96
|
+
def find_home
|
97
|
+
Hirb::Util.find_home
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns name of top level class that conflicts if it exists. For example, for base module Boson::Commands,
|
101
|
+
# Boson::Commands::Alias conflicts with Alias if Alias exists.
|
102
|
+
def top_level_class_conflict(base_module, conflicting_module)
|
103
|
+
(conflicting_module =~ /^#{base_module}.*::([^:]+)/) && Object.const_defined?($1) && $1
|
104
|
+
end
|
105
|
+
|
106
|
+
# Splits array into array of arrays with given element
|
107
|
+
def split_array_by(arr, divider)
|
108
|
+
arr.inject([[]]) {|results, element|
|
109
|
+
(divider == element) ? (results << []) : (results.last << element)
|
110
|
+
results
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
# Regular expression search of a list with underscore anchoring of words.
|
115
|
+
# For example 'some_dang_long_word' can be specified as 's_d_l_w'.
|
116
|
+
def underscore_search(input, list, first_match=false)
|
117
|
+
meth = first_match ? :find : :select
|
118
|
+
return (first_match ? input : [input]) if list.include?(input)
|
119
|
+
input = input.to_s
|
120
|
+
if input.include?("_")
|
121
|
+
underscore_regex = input.split('_').map {|e| Regexp.escape(e) }.join("([^_]+)?_")
|
122
|
+
list.send(meth) {|e| e.to_s =~ /^#{underscore_regex}/ }
|
123
|
+
else
|
124
|
+
escaped_input = Regexp.escape(input)
|
125
|
+
list.send(meth) {|e| e.to_s =~ /^#{escaped_input}/ }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
data/lib/boson/view.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
module Boson
|
2
|
+
# This module generates views for a command by handing it to {Hirb}[http://tagaholic.me/hirb/]. Since Hirb can be customized
|
3
|
+
# to generate any view, commands can have any views associated with them!
|
4
|
+
#
|
5
|
+
# === Views with Render Options
|
6
|
+
# To pass rendering options to a Hirb helper as command options, a command has to define the options with
|
7
|
+
# the render_options method attribute:
|
8
|
+
#
|
9
|
+
# # @render_options :fields=>[:a,:b]
|
10
|
+
# def list(options={})
|
11
|
+
# [{:a=>1, :b=>2}, {:a=>10,:b=>11}]
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# # To see that the render_options method attribute actually passes the :fields option by default:
|
15
|
+
# >> list '-p' # or list '--pretend'
|
16
|
+
# Arguments: []
|
17
|
+
# Global options: {:pretend=>true, :fields=>[:a, :b]}
|
18
|
+
#
|
19
|
+
# >> list
|
20
|
+
# +----+----+
|
21
|
+
# | a | b |
|
22
|
+
# +----+----+
|
23
|
+
# | 1 | 2 |
|
24
|
+
# | 10 | 11 |
|
25
|
+
# +----+----+
|
26
|
+
# 2 rows in set
|
27
|
+
#
|
28
|
+
# # To create a vertical table, we can pass --vertical, one of the default global render options.
|
29
|
+
# >> list '-V' # or list '--vertical'
|
30
|
+
# *** 1. row ***
|
31
|
+
# a: 1
|
32
|
+
# b: 2
|
33
|
+
# ...
|
34
|
+
#
|
35
|
+
# # To get the original return value use the global option --render
|
36
|
+
# >> list '-r' # or list '--render'
|
37
|
+
# => [{:a=>1, :b=>2}, {:a=>10,:b=>11}]
|
38
|
+
#
|
39
|
+
# === Boson and Hirb
|
40
|
+
# Since Boson uses {Hirb's auto table helper}[http://tagaholic.me/hirb/doc/classes/Hirb/Helpers/AutoTable.html]
|
41
|
+
# by default, you may want to read up on its many options. To use any of them in commands, define them locally
|
42
|
+
# with render_options or globally by adding them under the :render_options key of the main config.
|
43
|
+
# What if you want to use your own helper class? No problem. Simply pass it with the global :class option.
|
44
|
+
#
|
45
|
+
# When using the default helper, one of the most important options to define is :fields. Aside from controlling what fields
|
46
|
+
# are displayed, it's used to set :values option attributes for related options i.e. :sort and :query. This provides handy option
|
47
|
+
# value aliasing via OptionParser. If you don't set :fields, Boson will try to set its :values with field-related options i.e.
|
48
|
+
# :change_fields, :filters and :headers.
|
49
|
+
module View
|
50
|
+
extend self
|
51
|
+
|
52
|
+
# Enables hirb and reads a config file from the main repo's config/hirb.yml.
|
53
|
+
def enable
|
54
|
+
unless @enabled
|
55
|
+
Hirb::View.enable(:config_file=>File.join(Boson.repo.config_dir, 'hirb.yml'))
|
56
|
+
Hirb::Helpers::Table.filter_any = true
|
57
|
+
end
|
58
|
+
@enabled = true
|
59
|
+
end
|
60
|
+
|
61
|
+
# Renders any object via Hirb. Options are passed directly to
|
62
|
+
# {Hirb::Console.render_output}[http://tagaholic.me/hirb/doc/classes/Hirb/Console.html#M000011].
|
63
|
+
def render(object, options={}, return_obj=false)
|
64
|
+
if options[:inspect]
|
65
|
+
puts(object.inspect)
|
66
|
+
else
|
67
|
+
render_object(object, options, return_obj) unless silent_object?(object)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
#:stopdoc:
|
72
|
+
def class_config(klass)
|
73
|
+
opts = (Hirb::View.formatter_config[klass] || {}).dup
|
74
|
+
opts.delete(:ancestor)
|
75
|
+
opts.merge!((opts.delete(:options) || {}).dup)
|
76
|
+
OptionParser.make_mergeable!(opts)
|
77
|
+
opts
|
78
|
+
end
|
79
|
+
|
80
|
+
def toggle_pager
|
81
|
+
Hirb::View.toggle_pager
|
82
|
+
end
|
83
|
+
|
84
|
+
def silent_object?(obj)
|
85
|
+
[nil,false,true].include?(obj)
|
86
|
+
end
|
87
|
+
|
88
|
+
def render_object(object, options={}, return_obj=false)
|
89
|
+
options[:class] ||= :auto_table
|
90
|
+
render_result = Hirb::Console.render_output(object, options)
|
91
|
+
return_obj ? object : render_result
|
92
|
+
end
|
93
|
+
#:startdoc:
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
describe "scrape_with_text" do
|
4
|
+
def args_from(file_string)
|
5
|
+
ArgumentInspector.scrape_with_text(file_string, "blah")
|
6
|
+
end
|
7
|
+
|
8
|
+
it "parses arguments of class method" do
|
9
|
+
args_from(" def YAML.blah( filepath )\n").should == [['filepath']]
|
10
|
+
end
|
11
|
+
|
12
|
+
it "parses arguments with no spacing" do
|
13
|
+
args_from("def bong; end\ndef blah(arg1,arg2='val2')\nend").should == [["arg1"], ['arg2', "'val2'"]]
|
14
|
+
end
|
15
|
+
|
16
|
+
it "parses arguments with spacing" do
|
17
|
+
args_from("\t def blah( arg1=val1, arg2 = val2)").should == [["arg1","val1"], ["arg2", "val2"]]
|
18
|
+
end
|
19
|
+
|
20
|
+
it "parses arguments without parenthesis" do
|
21
|
+
args_from(" def blah arg1, arg2, arg3={}").should == [['arg1'], ['arg2'], ['arg3','{}']]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "scrape_with_eval" do
|
26
|
+
def args_from(string)
|
27
|
+
# methods need options to have their args parsed with ArgumentInspector
|
28
|
+
string.gsub!(/(def blah)/, 'options :a=>1; \1')
|
29
|
+
Inspector.enable
|
30
|
+
::Boson::Commands::Aaa.module_eval(string)
|
31
|
+
Inspector.disable
|
32
|
+
MethodInspector.store[:args]['blah']
|
33
|
+
end
|
34
|
+
|
35
|
+
before_all { eval "module ::Boson::Commands::Aaa; end"; }
|
36
|
+
before { MethodInspector.mod_store[::Boson::Commands::Aaa] = {} }
|
37
|
+
|
38
|
+
it "determines arguments with literal defaults" do
|
39
|
+
args_from("def blah(arg1,arg2='val2'); end").should == [['arg1'], ['arg2','val2']]
|
40
|
+
end
|
41
|
+
|
42
|
+
it "determines splat arguments" do
|
43
|
+
args_from("def blah(arg1, *args); end").should == [['arg1'], ["*args"]]
|
44
|
+
end
|
45
|
+
|
46
|
+
it "determines arguments with local values before a method" do
|
47
|
+
body = "AWESOME='awesome'; def sweet; 'ok'; end; def blah(arg1=AWESOME, arg2=sweet); end"
|
48
|
+
args_from(body).should == [['arg1', 'awesome'], ['arg2', 'ok']]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "doesn't get arguments with local values after a method" do
|
52
|
+
args_from("def blah(arg1=nope) end; def nope; 'nope'; end").should == nil
|
53
|
+
end
|
54
|
+
|
55
|
+
it "doesn't determine arguments of a private method" do
|
56
|
+
args_from("private; def blah(arg1,arg2); end").should == nil
|
57
|
+
end
|
58
|
+
|
59
|
+
it "doesn't determine arguments if an error occurs" do
|
60
|
+
args_from("def blah(arg1,arg2=raise); end").should == nil
|
61
|
+
end
|
62
|
+
end
|