boson-more 0.1.0

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.
Files changed (67) hide show
  1. data/.gemspec +22 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +97 -0
  4. data/Rakefile +35 -0
  5. data/deps.rip +1 -0
  6. data/lib/boson/alias.rb +75 -0
  7. data/lib/boson/argument_inspector.rb +90 -0
  8. data/lib/boson/commands/core.rb +67 -0
  9. data/lib/boson/commands/view_core.rb +19 -0
  10. data/lib/boson/commands/web_core.rb +153 -0
  11. data/lib/boson/comment_inspector.rb +100 -0
  12. data/lib/boson/console.rb +40 -0
  13. data/lib/boson/console_runner.rb +60 -0
  14. data/lib/boson/index.rb +48 -0
  15. data/lib/boson/libraries/file_library.rb +144 -0
  16. data/lib/boson/libraries/gem_library.rb +30 -0
  17. data/lib/boson/libraries/local_file_library.rb +30 -0
  18. data/lib/boson/libraries/module_library.rb +37 -0
  19. data/lib/boson/libraries/require_library.rb +23 -0
  20. data/lib/boson/libraries.rb +183 -0
  21. data/lib/boson/more/version.rb +5 -0
  22. data/lib/boson/more.rb +18 -0
  23. data/lib/boson/more_commands.rb +14 -0
  24. data/lib/boson/more_inspector.rb +42 -0
  25. data/lib/boson/more_manager.rb +34 -0
  26. data/lib/boson/more_method_inspector.rb +74 -0
  27. data/lib/boson/more_option_parser.rb +28 -0
  28. data/lib/boson/more_scientist.rb +68 -0
  29. data/lib/boson/more_util.rb +30 -0
  30. data/lib/boson/namespace.rb +31 -0
  31. data/lib/boson/namespacer.rb +117 -0
  32. data/lib/boson/pipe.rb +156 -0
  33. data/lib/boson/pipe_runner.rb +44 -0
  34. data/lib/boson/pipes.rb +75 -0
  35. data/lib/boson/repo.rb +96 -0
  36. data/lib/boson/repo_index.rb +135 -0
  37. data/lib/boson/runner_options.rb +88 -0
  38. data/lib/boson/save.rb +198 -0
  39. data/lib/boson/science.rb +273 -0
  40. data/lib/boson/view.rb +98 -0
  41. data/lib/boson/viewable.rb +48 -0
  42. data/test/alias_test.rb +55 -0
  43. data/test/argument_inspector_test.rb +40 -0
  44. data/test/command_test.rb +22 -0
  45. data/test/commands_test.rb +53 -0
  46. data/test/comment_inspector_test.rb +126 -0
  47. data/test/console_runner_test.rb +58 -0
  48. data/test/deps.rip +4 -0
  49. data/test/file_library_test.rb +41 -0
  50. data/test/gem_library_test.rb +40 -0
  51. data/test/libraries_test.rb +55 -0
  52. data/test/loader_test.rb +38 -0
  53. data/test/module_library_test.rb +30 -0
  54. data/test/more_manager_test.rb +29 -0
  55. data/test/more_method_inspector_test.rb +42 -0
  56. data/test/more_scientist_test.rb +10 -0
  57. data/test/namespacer_test.rb +61 -0
  58. data/test/pipes_test.rb +65 -0
  59. data/test/repo_index_test.rb +123 -0
  60. data/test/repo_test.rb +23 -0
  61. data/test/runner_options_test.rb +29 -0
  62. data/test/save_test.rb +86 -0
  63. data/test/science_test.rb +58 -0
  64. data/test/scientist_test.rb +195 -0
  65. data/test/test_helper.rb +165 -0
  66. data/test/web_test.rb +22 -0
  67. metadata +169 -0
data/lib/boson/save.rb ADDED
@@ -0,0 +1,198 @@
1
+ require 'boson/namespacer'
2
+ require 'boson/repo'
3
+ require 'boson/index'
4
+ require 'boson/repo_index'
5
+
6
+ module Boson
7
+ module Save
8
+ def config
9
+ repo.config
10
+ end
11
+
12
+ def config=(val)
13
+ repo.config = val
14
+ end
15
+
16
+ # The main required repository which defaults to ~/.boson.
17
+ def repo
18
+ @repo ||= Repo.new("#{ENV['BOSON_HOME'] || Dir.home}/.boson")
19
+ end
20
+
21
+ # An optional local repository which defaults to ./lib/boson or ./.boson.
22
+ def local_repo
23
+ @local_repo ||= begin
24
+ ignored_dirs = (config[:ignore_directories] || []).map {|e| File.expand_path(e) }
25
+ dir = ["lib/boson", ".boson"].find {|e| File.directory?(e) &&
26
+ File.expand_path(e) != repo.dir && !ignored_dirs.include?(File.expand_path('.')) }
27
+ Repo.new(dir) if dir
28
+ end
29
+ end
30
+
31
+ # The array of loaded repositories containing the main repo and possible local and global repos
32
+ def repos
33
+ @repos ||= [repo, local_repo, global_repo].compact
34
+ end
35
+
36
+ # Optional global repository at /etc/boson
37
+ def global_repo
38
+ File.exists?('/etc/boson') ? Repo.new('/etc/boson') : nil
39
+ end
40
+ end
41
+ extend Save
42
+
43
+ class BareRunner
44
+ module Save
45
+ def init
46
+ add_load_path
47
+ super
48
+ end
49
+
50
+ def autoload_command(cmd, opts={verbose: Boson.verbose})
51
+ Index.read
52
+ (lib = Index.find_library(cmd)) && Manager.load(lib, opts)
53
+ lib
54
+ end
55
+
56
+ def define_autoloader
57
+ class << ::Boson.main_object
58
+ def method_missing(method, *args, &block)
59
+ if BareRunner.autoload_command(method.to_s)
60
+ send(method, *args, &block) if respond_to?(method)
61
+ else
62
+ super
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ def default_libraries
69
+ Boson.repos.map {|e| e.config[:defaults] || [] }.flatten + super
70
+ end
71
+
72
+ # Libraries detected in repositories
73
+ def detected_libraries
74
+ Boson.repos.map {|e| e.detected_libraries }.flatten.uniq
75
+ end
76
+
77
+ # Libraries specified in config files and detected_libraries
78
+ def all_libraries
79
+ Boson.repos.map {|e| e.all_libraries }.flatten.uniq
80
+ end
81
+
82
+ def add_load_path
83
+ Boson.repos.each {|repo|
84
+ if repo.config[:add_load_path] || File.exists?(File.join(repo.dir, 'lib'))
85
+ $: << File.join(repo.dir, 'lib') unless $:.include? File.expand_path(File.join(repo.dir, 'lib'))
86
+ end
87
+ }
88
+ end
89
+ end
90
+ extend Save
91
+ end
92
+
93
+ # * All libraries can be configured by passing a hash of {library attributes}[link:classes/Boson/Library.html#M000077] under
94
+ # {the :libraries key}[link:classes/Boson/Repo.html#M000070] to the main config file ~/.boson/config/boson.yml.
95
+ # For most libraries this may be the only way to configure a library's commands.
96
+ # An example of a GemLibrary config:
97
+ # :libraries:
98
+ # httparty:
99
+ # :class_commands:
100
+ # delete: HTTParty.delete
101
+ # :commands:
102
+ # delete:
103
+ # :alias: d
104
+ # :desc: Http delete a given url
105
+ #
106
+ # When installing a third-party library, use the config file as a way to override default library and command attributes
107
+ # without modifying the library.
108
+ class Library
109
+ module Save
110
+ attr_accessor :repo_dir
111
+
112
+ def before_initialize
113
+ @repo_dir = set_repo.dir
114
+ end
115
+
116
+ def config
117
+ set_repo.config
118
+ end
119
+
120
+ def set_repo
121
+ Boson.repo
122
+ end
123
+
124
+ def marshal_dump
125
+ [@name, @commands, @gems, @module.to_s, @repo_dir, @indexed_namespace]
126
+ end
127
+
128
+ def marshal_load(ary)
129
+ @name, @commands, @gems, @module, @repo_dir, @indexed_namespace = ary
130
+ end
131
+ end
132
+ include Save
133
+ end
134
+
135
+ class Command
136
+ module Save
137
+ def marshal_dump
138
+ if @args && @args.any? {|e| e[1].is_a?(Module) }
139
+ @args.map! {|e| e.size == 2 ? [e[0], e[1].inspect] : e }
140
+ @file_parsed_args = true
141
+ end
142
+ [@name, @alias, @lib, @desc, @options, @render_options, @args, @default_option]
143
+ end
144
+
145
+ def marshal_load(ary)
146
+ @name, @alias, @lib, @desc, @options, @render_options, @args, @default_option = ary
147
+ end
148
+ end
149
+ include Save
150
+ end
151
+
152
+ if defined? BinRunner
153
+ # Any changes to your commands are immediately available from
154
+ # the commandline except for changes to the main config file. For those
155
+ # changes to take effect you need to explicitly load and index the libraries
156
+ # with --index. See RepoIndex to understand how Boson can immediately detect
157
+ # the latest commands.
158
+ class BinRunner
159
+ module Save
160
+ def autoload_command(cmd)
161
+ if !Boson.can_invoke?(cmd, false)
162
+ update_index
163
+ super(cmd, load_options)
164
+ end
165
+ end
166
+
167
+ def update_index
168
+ Index.update(verbose: verbose)
169
+ end
170
+
171
+ def execute_command(cmd, args)
172
+ @command = cmd # for external errors
173
+ autoload_command cmd
174
+ super
175
+ end
176
+
177
+ def command_not_found?(cmd)
178
+ super && (!(Index.read && Index.find_command(cmd[/\w+/])) || cmd.include?(NAMESPACE))
179
+ end
180
+
181
+ def command_name(cmd)
182
+ cmd.split(Boson::NAMESPACE)[-1]
183
+ end
184
+
185
+ def eval_execute_option(str)
186
+ define_autoloader
187
+ super
188
+ end
189
+
190
+ def default_libraries
191
+ super + Boson.repos.map {|e| e.config[:bin_defaults] || [] }.flatten +
192
+ Dir.glob('Bosonfile')
193
+ end
194
+ end
195
+ extend Save
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,273 @@
1
+ require 'boson/view'
2
+ require 'boson/pipe'
3
+ require 'boson/pipes'
4
+ require 'boson/more_scientist'
5
+
6
+ module Boson
7
+ class OptionCommand
8
+ BASIC_OPTIONS.update(
9
+ :delete_options=>{:type=>:array, :desc=>'Deletes global options starting with given strings' },
10
+ :usage_options=>{:type=>:string, :desc=>"Render options to pass to usage/help"},
11
+ :render=> {:type=>:boolean, :desc=>"Toggle a command's default rendering behavior"})
12
+ PIPE_OPTIONS = {
13
+ :sort=>{:type=>:string, :desc=>"Sort by given field"},
14
+ :reverse_sort=>{:type=>:boolean, :desc=>"Reverse a given sort"},
15
+ :query=>{:type=>:hash, :desc=>"Queries fields given field:search pairs"},
16
+ :pipes=>{:alias=>'P', :type=>:array, :desc=>"Pipe to commands sequentially"}
17
+ } #:nodoc:
18
+
19
+ RENDER_OPTIONS = {
20
+ :fields=>{:type=>:array, :desc=>"Displays fields in the order given"},
21
+ :class=>{:type=>:string, :desc=>"Hirb helper class which renders"},
22
+ :max_width=>{:type=>:numeric, :desc=>"Max width of a table"},
23
+ :vertical=>{:type=>:boolean, :desc=>"Display a vertical table"},
24
+ } #:nodoc:
25
+
26
+ # Adds render and pipe global options
27
+ # For more about pipe and render options see Pipe and View respectively.
28
+ # === Toggling Views With the Basic Global Option --render
29
+ # One of the more important global options is --render. This option toggles the rendering of a command's
30
+ # output done with View and Hirb[http://github.com/cldwalker/hirb].
31
+ #
32
+ # Here's a simple example of toggling Hirb's table view:
33
+ # # Defined in a library file:
34
+ # #@options {}
35
+ # def list(options={})
36
+ # [1,2,3]
37
+ # end
38
+ #
39
+ # Using it in irb:
40
+ # >> list
41
+ # => [1,2,3]
42
+ # >> list '-r' # or list --render
43
+ # +-------+
44
+ # | value |
45
+ # +-------+
46
+ # | 1 |
47
+ # | 2 |
48
+ # | 3 |
49
+ # +-------+
50
+ # 3 rows in set
51
+ # => true
52
+ # == Additional config keys for the main repo config
53
+ # [:render_options] Hash of render options available to all option commands to be passed to a Hirb view (see View). Since
54
+ # this merges with default render options, it's possible to override default render options.
55
+ # [:no_auto_render] When set, turns off commandline auto-rendering of a command's output. Default is false.
56
+ module ClassRender
57
+
58
+ def default_options
59
+ default_pipe_options.merge(default_render_options.merge(BASIC_OPTIONS))
60
+ end
61
+
62
+ def default_pipe_options
63
+ @default_pipe_options ||= PIPE_OPTIONS.merge Pipe.pipe_options
64
+ end
65
+
66
+ def default_render_options
67
+ @default_render_options ||= RENDER_OPTIONS.merge Boson.repo.config[:render_options] || {}
68
+ end
69
+
70
+ def delete_non_render_options(opt)
71
+ opt.delete_if {|k,v| BASIC_OPTIONS.keys.include?(k) }
72
+ end
73
+ end
74
+ extend ClassRender
75
+
76
+ module Render
77
+ def option_parser
78
+ @option_parser ||= @command.render_options ? OptionParser.new(all_global_options) :
79
+ self.class.default_option_parser
80
+ end
81
+
82
+ def all_global_options
83
+ OptionParser.make_mergeable! @command.render_options
84
+ render_opts = Util.recursive_hash_merge(@command.render_options, Util.deep_copy(self.class.default_render_options))
85
+ merged_opts = Util.recursive_hash_merge Util.deep_copy(self.class.default_pipe_options), render_opts
86
+ opts = Util.recursive_hash_merge merged_opts, Util.deep_copy(BASIC_OPTIONS)
87
+ set_global_option_defaults opts
88
+ end
89
+
90
+ def set_global_option_defaults(opts)
91
+ if !opts[:fields].key?(:values)
92
+ if opts[:fields][:default]
93
+ opts[:fields][:values] = opts[:fields][:default]
94
+ else
95
+ if opts[:change_fields] && (changed = opts[:change_fields][:default])
96
+ opts[:fields][:values] = changed.is_a?(Array) ? changed : changed.values
97
+ end
98
+ opts[:fields][:values] ||= opts[:headers][:default].keys if opts[:headers] && opts[:headers][:default]
99
+ end
100
+ opts[:fields][:enum] = false if opts[:fields][:values] && !opts[:fields].key?(:enum)
101
+ end
102
+ if opts[:fields][:values]
103
+ opts[:sort][:values] ||= opts[:fields][:values]
104
+ opts[:query][:keys] ||= opts[:fields][:values]
105
+ opts[:query][:default_keys] ||= "*"
106
+ end
107
+ opts
108
+ end
109
+ end
110
+ include Render
111
+ end
112
+
113
+ module Scientist
114
+ # * Before a method returns its value, it pipes its return value through pipe commands if pipe options are specified. See Pipe.
115
+ # * Methods can have any number of optional views associated with them via global render options (see View). Views can be toggled
116
+ # on/off with the global option --render (see OptionCommand).
117
+ module Render
118
+ attr_accessor :rendered, :render
119
+
120
+ def after_parse
121
+ (@global_options[:delete_options] || []).map {|e|
122
+ @global_options.keys.map {|k| k.to_s }.grep(/^#{e}/)
123
+ }.flatten.each {|e| @global_options.delete(e.to_sym) }
124
+ end
125
+
126
+ def process_result(result)
127
+ if (@rendered = can_render?)
128
+ if @global_options.key?(:class) || @global_options.key?(:method)
129
+ result = Pipe.scientist_process(result, @global_options, :config=>@command.config, :args=>@args, :options=>@current_options)
130
+ end
131
+ View.render(result, OptionCommand.delete_non_render_options(@global_options.dup), false)
132
+ else
133
+ Pipe.scientist_process(result, @global_options, :config=>@command.config, :args=>@args, :options=>@current_options)
134
+ end
135
+ rescue StandardError
136
+ raise Scientist::Error, $!.message, $!.backtrace
137
+ end
138
+
139
+ def can_render?
140
+ render.nil? ? command_renders? : render
141
+ end
142
+
143
+ def command_renders?
144
+ (!!@command.render_options ^ @global_options[:render]) && !Pipe.any_no_render_pipes?(@global_options)
145
+ end
146
+
147
+ def run_pretend_option(args)
148
+ super
149
+ @rendered = true if @global_options[:pretend]
150
+ end
151
+
152
+ def help_options
153
+ super.tap do |opts|
154
+ if @global_options[:usage_options]
155
+ opts << "--render_options=#{@global_options[:usage_options]}"
156
+ end
157
+ opts
158
+ end
159
+ end
160
+ end
161
+ extend Render
162
+ end
163
+
164
+ class Command
165
+ module ScienceClassMethods
166
+ attr_accessor :all_option_commands
167
+
168
+ def create(name, library)
169
+ super.tap do |obj|
170
+ if @all_option_commands && !%w{get method_missing}.include?(name)
171
+ obj.make_option_command(library)
172
+ end
173
+ end
174
+ end
175
+ end
176
+ extend ScienceClassMethods
177
+
178
+ module Science
179
+ # Option parser for command as defined by @render_options.
180
+ def render_option_parser
181
+ option_command? ? Boson::Scientist.option_command(self).option_parser : nil
182
+ end
183
+
184
+ def make_option_command(lib=library)
185
+ @option_command = true
186
+ @args = [['*args']] unless args(lib) || arg_size
187
+ end
188
+
189
+ def option_command?
190
+ super || render_options
191
+ end
192
+ end
193
+ include Science
194
+ end
195
+
196
+ # [*:render_options*] Hash of rendering options to pass to OptionParser. If the key :output_class is passed,
197
+ # that class's Hirb config will serve as defaults for this rendering hash.
198
+ class Command
199
+ attr_accessor :render_options
200
+
201
+ module Science
202
+ def after_initialize(hash)
203
+ if hash[:render_options] && (@render_options = hash.delete(:render_options))[:output_class]
204
+ @render_options = Util.recursive_hash_merge View.class_config(@render_options[:output_class]), @render_options
205
+ end
206
+ super
207
+ end
208
+ end
209
+ end
210
+
211
+ if defined? BinRunner
212
+ class BinRunner < BareRunner
213
+ GLOBAL_OPTIONS.update(
214
+ option_commands: {
215
+ :type=>:boolean,
216
+ :desc=>"Toggles on all commands to be defined as option commands"
217
+ },
218
+ render: {:type=>:boolean,
219
+ :desc=>"Renders a Hirb view from result of command without options"}
220
+ )
221
+
222
+ # [:render] Toggles the auto-rendering done for commands that don't have views. Doesn't affect commands that already have views.
223
+ # Default is false. Also see Auto Rendering section below.
224
+ #
225
+ # ==== Auto Rendering
226
+ # Commands that don't have views (defined via render_options) have their return value auto-rendered as a view as follows:
227
+ # * nil,false and true aren't rendered
228
+ # * arrays are rendered with Hirb's tables
229
+ # * non-arrays are printed with inspect()
230
+ # * Any of these cases can be toggled to render/not render with the global option :render
231
+ # To turn off auto-rendering by default, add a :no_auto_render: true entry to the main config.
232
+ module Science
233
+ def init
234
+ Command.all_option_commands = true if @options[:option_commands]
235
+ super
236
+ end
237
+
238
+ def render_output(output)
239
+ if (!Scientist.rendered && !View.silent_object?(output)) ^ @options[:render] ^
240
+ Boson.repo.config[:no_auto_render]
241
+ opts = output.is_a?(String) ? {:method=>'puts'} :
242
+ {:inspect=>!output.is_a?(Array) || (Scientist.global_options || {})[:render] }
243
+ View.render output, opts
244
+ end
245
+ end
246
+
247
+ def allowed_argument_error?(err, cmd, args)
248
+ err.class == OptionCommand::CommandArgumentError || super
249
+ end
250
+
251
+ def execute_command(cmd, args)
252
+ render_output super
253
+ end
254
+ end
255
+
256
+ class <<self
257
+ include Science
258
+ end
259
+ end
260
+ end
261
+
262
+ # Additional method attributes:
263
+ # * render_options: Hash to define an OptionParser object for a command's local/global render options (see View).
264
+ class MethodInspector
265
+ METHODS << :render_options
266
+ METHOD_CLASSES[:render_options] = Hash
267
+ SCRAPEABLE_METHODS << :render_options
268
+ end
269
+
270
+ module CommentInspector
271
+ EVAL_ATTRIBUTES << :render_options
272
+ end
273
+ end
data/lib/boson/view.rb ADDED
@@ -0,0 +1,98 @@
1
+ require 'hirb'
2
+ require 'boson/more_option_parser'
3
+
4
+ module Boson
5
+ # This module generates views for a command by handing it to {Hirb}[http://tagaholic.me/hirb/]. Since Hirb can be customized
6
+ # to generate any view, commands can have any views associated with them!
7
+ #
8
+ # === Views with Render Options
9
+ # To pass rendering options to a Hirb helper as command options, a command has to define the options with
10
+ # the render_options method attribute:
11
+ #
12
+ # # @render_options :fields=>[:a,:b]
13
+ # def list(options={})
14
+ # [{:a=>1, :b=>2}, {:a=>10,:b=>11}]
15
+ # end
16
+ #
17
+ # # To see that the render_options method attribute actually passes the :fields option by default:
18
+ # >> list '-p' # or list '--pretend'
19
+ # Arguments: []
20
+ # Global options: {:pretend=>true, :fields=>[:a, :b]}
21
+ #
22
+ # >> list
23
+ # +----+----+
24
+ # | a | b |
25
+ # +----+----+
26
+ # | 1 | 2 |
27
+ # | 10 | 11 |
28
+ # +----+----+
29
+ # 2 rows in set
30
+ #
31
+ # # To create a vertical table, we can pass --vertical, one of the default global render options.
32
+ # >> list '-V' # or list '--vertical'
33
+ # *** 1. row ***
34
+ # a: 1
35
+ # b: 2
36
+ # ...
37
+ #
38
+ # # To get the original return value use the global option --render
39
+ # >> list '-r' # or list '--render'
40
+ # => [{:a=>1, :b=>2}, {:a=>10,:b=>11}]
41
+ #
42
+ # === Boson and Hirb
43
+ # Since Boson uses {Hirb's auto table helper}[http://tagaholic.me/hirb/doc/classes/Hirb/Helpers/AutoTable.html]
44
+ # by default, you may want to read up on its many options. To use any of them in commands, define them locally
45
+ # with render_options or globally by adding them under the :render_options key of the main config.
46
+ # What if you want to use your own helper class? No problem. Simply pass it with the global :class option.
47
+ #
48
+ # When using the default helper, one of the most important options to define is :fields. Aside from controlling what fields
49
+ # are displayed, it's used to set :values option attributes for related options i.e. :sort and :query. This provides handy option
50
+ # value aliasing via OptionParser. If you don't set :fields, Boson will try to set its :values with field-related options i.e.
51
+ # :change_fields, :filters and :headers.
52
+ module View
53
+ extend self
54
+
55
+ # Enables hirb and reads a config file from the main repo's config/hirb.yml.
56
+ def enable
57
+ unless @enabled
58
+ Hirb::View.enable(:config_file=>File.join(Boson.repo.config_dir, 'hirb.yml'))
59
+ Hirb::Helpers::Table.filter_any = true
60
+ end
61
+ @enabled = true
62
+ end
63
+
64
+ # Renders any object via Hirb. Options are passed directly to
65
+ # {Hirb::Console.render_output}[http://tagaholic.me/hirb/doc/classes/Hirb/Console.html#M000011].
66
+ def render(object, options={}, return_obj=false)
67
+ if options[:inspect]
68
+ puts(object.inspect)
69
+ else
70
+ render_object(object, options, return_obj) unless silent_object?(object)
71
+ end
72
+ end
73
+
74
+ #:stopdoc:
75
+ def class_config(klass)
76
+ opts = (Hirb::View.formatter_config[klass] || {}).dup
77
+ opts.delete(:ancestor)
78
+ opts.merge!((opts.delete(:options) || {}).dup)
79
+ OptionParser.make_mergeable!(opts)
80
+ opts
81
+ end
82
+
83
+ def toggle_pager
84
+ Hirb::View.toggle_pager
85
+ end
86
+
87
+ def silent_object?(obj)
88
+ [nil,false,true].include?(obj)
89
+ end
90
+
91
+ def render_object(object, options={}, return_obj=false)
92
+ options[:class] ||= :auto_table
93
+ render_result = Hirb::Console.render_output(object, options)
94
+ return_obj ? object : render_result
95
+ end
96
+ #:startdoc:
97
+ end
98
+ end
@@ -0,0 +1,48 @@
1
+ require 'boson/view'
2
+
3
+ module Boson
4
+ if defined? BinRunner
5
+ class BinRunner
6
+ module Viewable
7
+ def print_usage_header
8
+ super
9
+ puts "GLOBAL OPTIONS"
10
+ View.enable
11
+ end
12
+ end
13
+ extend Viewable
14
+ end
15
+ end
16
+
17
+ class BareRunner
18
+ module Viewable
19
+ def init
20
+ View.enable
21
+ super
22
+ end
23
+ end
24
+ extend Viewable
25
+ end
26
+
27
+ class OptionParser
28
+ module Viewable
29
+ def get_fields_and_options(fields, options)
30
+ (fields << :default).uniq! if options.delete(:local) || options[:fields] == '*'
31
+ fields, opts = super(fields, options)
32
+ fields.delete(:default) if fields.include?(:default) && opts.all? {|e| e[:default].nil? }
33
+ [fields, opts]
34
+ end
35
+
36
+ def default_render_options #:nodoc:
37
+ {:header_filter=>:capitalize, :description=>false, :filter_any=>true,
38
+ :filter_classes=>{Array=>[:join, ',']}, :hide_empty=>true}
39
+ end
40
+
41
+ def render_table(fields, arr, options)
42
+ options = default_render_options.merge(:fields=>fields).merge(options)
43
+ View.render arr, options
44
+ end
45
+ end
46
+ include Viewable
47
+ end
48
+ end
@@ -0,0 +1,55 @@
1
+ # Add library_loaded? and with_config
2
+ describe "Manager" do
3
+ def load_library(hash)
4
+ new_attributes = {:name=>hash[:name], :commands=>[], :created_dependencies=>[], :loaded=>true}
5
+ [:module, :commands].each {|e| new_attributes[e] = hash.delete(e) if hash[e] }
6
+ Manager.expects(:call_load_action).returns(Library.new(new_attributes))
7
+ Manager.load([hash[:name]])
8
+ end
9
+
10
+ before { reset_boson }
11
+
12
+ describe "command aliases" do
13
+ before { eval %[module ::Aquateen; def frylock; end; end] }
14
+ after { Object.send(:remove_const, "Aquateen") }
15
+
16
+ it "created with command specific config" do
17
+ with_config(:command_aliases=>{'frylock'=>'fr'}) do
18
+ Manager.expects(:create_instance_aliases).with({"Aquateen"=>{"frylock"=>"fr"}})
19
+ load_library :name=>'aquateen', :commands=>['frylock'], :module=>Aquateen
20
+ library_loaded? 'aquateen'
21
+ end
22
+ end
23
+
24
+ it "created with config command_aliases" do
25
+ with_config(:command_aliases=>{"frylock"=>"fr"}) do
26
+ Manager.expects(:create_instance_aliases).with({"Aquateen"=>{"frylock"=>"fr"}})
27
+ load_library :name=>'aquateen', :commands=>['frylock'], :module=>Aquateen
28
+ library_loaded? 'aquateen'
29
+ end
30
+ end
31
+
32
+ it "not created and warns for commands with no module" do
33
+ with_config(:command_aliases=>{'frylock'=>'fr'}) do
34
+ capture_stderr {
35
+ load_library(:name=>'aquateen', :commands=>['frylock'])
36
+ }.should =~ /No aliases/
37
+ library_loaded? 'aquateen'
38
+ Aquateen.method_defined?(:fr).should == false
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "Loader" do
45
+ describe "load" do
46
+ before { reset }
47
+ it "loads a library and creates its class commands" do
48
+ with_config(:libraries=>{"blah"=>{:class_commands=>{"bling"=>"Blah.bling", "Blah"=>['hmm']}}}) do
49
+ load :blah, :file_string=>"module Blah; def self.bling; end; def self.hmm; end; end"
50
+ command_exists? 'bling'
51
+ command_exists? 'hmm'
52
+ end
53
+ end
54
+ end
55
+ end