bosonson 0.304.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/CHANGELOG.rdoc +108 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.rdoc +181 -0
  4. data/bin/bss +6 -0
  5. data/bosonson.gemspec +24 -0
  6. data/deps.rip +2 -0
  7. data/lib/boson.rb +96 -0
  8. data/lib/boson/command.rb +196 -0
  9. data/lib/boson/commands.rb +7 -0
  10. data/lib/boson/commands/core.rb +77 -0
  11. data/lib/boson/commands/web_core.rb +153 -0
  12. data/lib/boson/index.rb +48 -0
  13. data/lib/boson/inspector.rb +120 -0
  14. data/lib/boson/inspectors/argument_inspector.rb +97 -0
  15. data/lib/boson/inspectors/comment_inspector.rb +100 -0
  16. data/lib/boson/inspectors/method_inspector.rb +98 -0
  17. data/lib/boson/libraries/file_library.rb +144 -0
  18. data/lib/boson/libraries/gem_library.rb +30 -0
  19. data/lib/boson/libraries/local_file_library.rb +30 -0
  20. data/lib/boson/libraries/module_library.rb +37 -0
  21. data/lib/boson/libraries/require_library.rb +23 -0
  22. data/lib/boson/library.rb +179 -0
  23. data/lib/boson/loader.rb +118 -0
  24. data/lib/boson/manager.rb +169 -0
  25. data/lib/boson/namespace.rb +31 -0
  26. data/lib/boson/option_command.rb +222 -0
  27. data/lib/boson/option_parser.rb +475 -0
  28. data/lib/boson/options.rb +146 -0
  29. data/lib/boson/pipe.rb +147 -0
  30. data/lib/boson/pipes.rb +75 -0
  31. data/lib/boson/repo.rb +107 -0
  32. data/lib/boson/repo_index.rb +124 -0
  33. data/lib/boson/runner.rb +81 -0
  34. data/lib/boson/runners/bin_runner.rb +208 -0
  35. data/lib/boson/runners/console_runner.rb +58 -0
  36. data/lib/boson/scientist.rb +182 -0
  37. data/lib/boson/util.rb +129 -0
  38. data/lib/boson/version.rb +3 -0
  39. data/lib/boson/view.rb +95 -0
  40. data/test/argument_inspector_test.rb +62 -0
  41. data/test/bin_runner_test.rb +223 -0
  42. data/test/command_test.rb +22 -0
  43. data/test/commands_test.rb +22 -0
  44. data/test/comment_inspector_test.rb +126 -0
  45. data/test/deps.rip +4 -0
  46. data/test/file_library_test.rb +42 -0
  47. data/test/loader_test.rb +235 -0
  48. data/test/manager_test.rb +114 -0
  49. data/test/method_inspector_test.rb +90 -0
  50. data/test/option_parser_test.rb +367 -0
  51. data/test/options_test.rb +189 -0
  52. data/test/pipes_test.rb +65 -0
  53. data/test/repo_index_test.rb +122 -0
  54. data/test/repo_test.rb +23 -0
  55. data/test/runner_test.rb +40 -0
  56. data/test/scientist_test.rb +341 -0
  57. data/test/test_helper.rb +130 -0
  58. data/test/util_test.rb +56 -0
  59. data/vendor/bundle/gems/bacon-bits-0.1.0/deps.rip +1 -0
  60. data/vendor/bundle/gems/hirb-0.6.0/test/deps.rip +4 -0
  61. metadata +217 -0
@@ -0,0 +1,108 @@
1
+ == 0.3.4
2
+ * Handle rubygems deprecation (#28)
3
+ * 1.9 Fixes
4
+
5
+ == 0.3.3
6
+ * Fix install command for https (#22)
7
+
8
+ == 0.3.2
9
+ * Add commandline backtrace option (#18)
10
+
11
+ == 0.3.1
12
+ * Fixed MethodInspector handling anonymous classes on 1.9.2 (#16)
13
+ * Fixed get and install commands on 1.9.2 (#17)
14
+ * Fixed failed loading of Bosonfile
15
+ * Fixed RequireLibrary indicating correct load status
16
+
17
+ == 0.3.0
18
+ * Added --debug to executable with multiple debug hooks
19
+ * Added --ruby_debug and -I to executable to change $LOAD_PATH and $DEBUG
20
+ * Added @option method attribute as a more readable complement to @options
21
+ * Added proper exit code for failed commands (#12)
22
+ * Added friendlier errors for libraries with SyntaxError or LoaderError
23
+ * Added validation to method attributes
24
+ * Improved RequireLibrary to more robustly handle gems like httparty
25
+ * Fixed 1.9.2-rc2 bugs including #14
26
+ * Fixed finding commands with same names
27
+ * Fixed --console for ruby >= 1.8.7
28
+ * Fixed --help for namespaced commands
29
+
30
+ == 0.2.5
31
+ * Fixed critical gemspec error
32
+
33
+ == 0.2.4
34
+ * Tests use bacon and pass on all major ruby versions
35
+ * Fixed bug for 1.8.7 and super (#10)
36
+ * Added commandline pipes with '+'
37
+ * Fixed bug when requiring rubygems in a library
38
+ * Fixed bug in sort pipe for 1.9.2
39
+ * Got rid of jeweler in Rakefile and $LOAD_PATH meddling
40
+ * Refactored BinRunner's error handling
41
+
42
+ == 0.2.3
43
+ * Added improved support and additional attributes for user pipe options
44
+ * Added :pipes global command option
45
+ * Added json + yaml parsing to get()
46
+ * Added underscore searching to option values
47
+ * Added build_install() command
48
+ * Added :usage_options commandline option
49
+
50
+ == 0.2.2
51
+ * Renamed Boson::Command#description to #desc. Delete your index at ~/.boson/config/index.marshal.
52
+ * Renamed Boson::Command#global_options to #option_command. Update your configs.
53
+ * Bug fix for Windows and indexing (#4)
54
+ * Added system wide Boson commands at /etc/boson (#2)
55
+ * Added Boson::Command#config for plugins to set/get via @config
56
+ * Added option_command and unload options to BinRunner
57
+ * Added special option parsing characters: - and --
58
+ * Added special :output_class key for global render_options
59
+ * Added :delete_options global option
60
+ * Fixed --no variant for single letter booleans
61
+ * Fixed MethodInspector parsing arguments with special characters
62
+ * Allow global -p to work even in failures
63
+ * Allow -hv to default to verbose help
64
+ * Boson::OptionParser tweaks
65
+
66
+ == 0.2.1
67
+ * Added local libraries: Bosonfile and under local repositories
68
+ * Added config method attribute.
69
+ * Added default_option and global_options command attributes.
70
+ * Added OptionParser.parse and OptionParser.usage for scripting use.
71
+ * Improved auto-rendering from commandline.
72
+ * Removed library reload.
73
+ * Better docs.
74
+
75
+ == 0.2.0
76
+ * Command options
77
+ ** Added custom global and render options for commands.
78
+ ** Added pipe and filter option commands.
79
+ ** Add global query option.
80
+ * Options
81
+ ** Users can define custom option types.
82
+ ** Added hash option type.
83
+ ** Any option can be a boolean with :bool_default attribute.
84
+ ** Adding * aliasing to relevant options.
85
+ * Made Boson::Scientist.commandify for use outside Boson.
86
+ * Any command can have a default option.
87
+ * Directories are namespaced automatically.
88
+ * Solidified library module callback methods.
89
+ * Added support for Windows home.
90
+ * Improved ModuleLibrary to handle class or module class methods.
91
+ * Better search and sort integration with Hirb.
92
+ * Better docs.
93
+ * Fixed number of bugs.
94
+ * query_fields option for searching libraries and commands is deprecated. Specifying query
95
+ fields is now done by prefixing a query with ':'. For example:
96
+ bash> boson commands library_type:gem
97
+ # instead of
98
+ bash> boson commands gem --query_fields=library_type
99
+
100
+ == 0.1.0
101
+ * First real release
102
+ * Plenty of fixes to make it ruby 1.9 ready.
103
+ * Added more documentation
104
+ * BinRunner tweaks and bug fixes
105
+ * Other miscellaneous bug fixes
106
+
107
+ == 0.0.1
108
+ * An initial release for others to play with.
@@ -0,0 +1,22 @@
1
+ The MIT LICENSE
2
+
3
+ Copyright (c) 2010 Gabriel Horner
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,181 @@
1
+ To read a linkable version of this README, {see here}[http://tagaholic.me/boson/doc/].
2
+
3
+ == Description
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.
9
+
10
+ == UPDATE
11
+ Boson 0.4.x will be the last 1.8 compatible version.
12
+ Boson 0.5 will be a rewrite compatible with only 1.9. Work is going on in {boson2
13
+ branch}[https://github.com/cldwalker/boson/tree/boson2]. The goal of boson2 is to have a slimmer
14
+ core, move everything else {to plugins}[https://github.com/cldwalker/boson-all]
15
+ and to allow gems to use boson to make executables like thor.
16
+
17
+ == Features
18
+ * Simple organization: Commands are just methods on an object (default is main) and command libraries are just modules.
19
+ * Commands are accessible from the commandline (Boson::BinRunner) or irb (Boson::ConsoleRunner).
20
+ * Libraries
21
+ * can be written in plain ruby which allows for easy testing and use independent of boson (Boson::FileLibrary).
22
+ * can exist locally as a Bosonfile (Boson::LocalFileLibrary) and under lib/boson/commands or .boson/commands.
23
+ * can be made from gems (Boson::GemLibrary) or any require-able file (Boson::RequireLibrary).
24
+ * are encouraged to be shared. Libraries can be installed with a given url. Users can customize any aspect of a third-party
25
+ library without modifying it (Boson::Library).
26
+ * Commands
27
+ * can have any number of local and global options (Boson::OptionCommand). Options are defined with Boson::OptionParser.
28
+ * can have any view associated to it (via Hirb) without adding view code to the command's method.
29
+ These views can be toggled on and manipulated via global render options (Boson::View and Boson::OptionCommand).
30
+ * can pipe their return value into custom pipe options (Boson::Pipe).
31
+ * has default pipe options to search and sort an array of any objects (Boson::Pipes).
32
+ * Option parser (Boson::OptionParser)
33
+ * provides option types that map to objects i.e. :array type creates Array objects.
34
+ * come with 5 default option types: boolean, array, string, hash and numeric.
35
+ * can have have custom option types defined by users (Boson::Options).
36
+ * Comes with default commands to load, search, list and install commands and libraries (Boson::Commands::Core).
37
+ * Namespaces are optional and when used are methods which allow for method_missing magic.
38
+
39
+ == Creating Command Libraries
40
+ See Boson::FileLibrary or here[http://tagaholic.me/boson/doc/classes/Boson/FileLibrary.html].
41
+
42
+ == Irb Example
43
+
44
+ To use in irb, drop this in your ~/.irbrc:
45
+ require 'boson'
46
+ Boson.start
47
+
48
+ Having done that, let's start up irb:
49
+
50
+ bash> irb
51
+ Loaded library core
52
+ Loaded library web_core
53
+
54
+ # List default libraries
55
+ >> libraries
56
+ +----------+----------+------+--------------+
57
+ | name | commands | gems | library_type |
58
+ +----------+----------+------+--------------+
59
+ | core | 6 | | module |
60
+ | web_core | 3 | | module |
61
+ +----------+----------+------+--------------+
62
+ 2 rows in set
63
+
64
+ # List default commands
65
+ >> commands
66
+ +--------------+----------+-------+--------------------------------------------+-----------------------------------------------------------------------------+
67
+ | full_name | lib | alias | usage | description |
68
+ +--------------+----------+-------+--------------------------------------------+-----------------------------------------------------------------------------+
69
+ | usage | core | | [name][--verbose] | Print a command's usage |
70
+ | libraries | core | | [query=''][--index] [--query_fields=A,B,C] | List or search libraries |
71
+ | render | core | | [object] [options={}] | Render any object using Hirb |
72
+ | load_library | core | | [library][--verbose] [--reload] | Load/reload a library |
73
+ | commands | core | | [query=''][--index] [--query_fields=A,B,C] | List or search commands |
74
+ | menu | core | | [output] [options={}] [&block] | Provide a menu to multi-select elements from a given array |
75
+ | get | web_core | | [url] | Gets the body of a url |
76
+ | install | web_core | | [url][--force] [--name=NAME] | Installs a library by url. Library should then be loaded with load_library. |
77
+ | browser | web_core | | [*urls] | Opens urls in a browser |
78
+ +--------------+----------+-------+--------------------------------------------+-----------------------------------------------------------------------------+
79
+ 9 rows in set
80
+
81
+ # Boson commands can behave like shell commands:
82
+
83
+ # Basic help
84
+ >> commands '-h'
85
+ commands [query=''][--index] [--query_fields=A,B,C]
86
+
87
+ # Search the lib column for web
88
+ >> commands 'web -q=lib' # or 'web --query_fields=lib'
89
+ +-----------+----------+-------+------------------------------+-----------------------------------------------------------------------------+
90
+ | full_name | lib | alias | usage | description |
91
+ +-----------+----------+-------+------------------------------+-----------------------------------------------------------------------------+
92
+ | get | web_core | | [url] | Gets the body of a url |
93
+ | install | web_core | | [url][--force] [--name=NAME] | Installs a library by url. Library should then be loaded with load_library. |
94
+ | browser | web_core | | [*urls] | Opens urls in a browser |
95
+ +-----------+----------+-------+------------------------------+-----------------------------------------------------------------------------+
96
+ 3 rows in set
97
+
98
+ == Commandline Example
99
+
100
+ # Just like in irb
101
+ bash> boson libraries
102
+ +----------+----------+------+--------------+
103
+ | name | commands | gems | library_type |
104
+ +----------+----------+------+--------------+
105
+ | core | 6 | | module |
106
+ | web_core | 3 | | module |
107
+ +----------+----------+------+--------------+
108
+ 2 rows in set
109
+
110
+ # Let's install another library
111
+ bash> boson install https://github.com/cldwalker/irbfiles/raw/master/boson/commands/public/irb_core.rb
112
+ Saved to /Users/bozo/.boson/commands/irb_core.rb
113
+
114
+ # Let's start irb ...
115
+ bash> irb
116
+
117
+ >> commands
118
+ +-------------------------------+----------+------------+--------------------------------------------+-----------------------------------------------------------------------------+
119
+ | full_name | lib | alias | usage | description |
120
+ +-------------------------------+----------+------------+--------------------------------------------+-----------------------------------------------------------------------------+
121
+ | usage | core | | [name][--verbose] | Print a command's usage |
122
+ | libraries | core | | [query=''][--index] [--query_fields=name] | List or search libraries |
123
+ | render | core | | [object] [options={}] | Render any object using Hirb |
124
+ | load_library | core | | [library][--verbose] [--reload] | Load/reload a library |
125
+ | commands | core | | [query=''][--index] [--query_fields=A,B,C] | List or search commands |
126
+ | menu | core | | [output] [options={}] [&block] | Provide a menu to multi-select elements from a given array |
127
+ | get | web_core | | [url] | Gets the body of a url |
128
+ | install | web_core | | [url][--force] [--name=NAME] | Installs a library by url. Library should then be loaded with load_library. |
129
+ | browser | web_core | | [*urls] | Opens urls in a browser |
130
+ | irb_pop_workspace | irb_core | popws | | Pops current workspace and changes to next workspace in context |
131
+ | irb_require | irb_core | | | Evals file like require line by line |
132
+ | public | irb_core | | | Works same as module#public |
133
+ | private | irb_core | | | Works same as module#private |
134
+ | irb | irb_core | | | Starts a new workspace/subsession |
135
+ | irb_push_workspace | irb_core | pushws | | Creates a workspace for given object and pushes it into the current context |
136
+ | irb_load | irb_core | | | Evals file like load line by line |
137
+ | irb_change_workspace | irb_core | cws | | Changes current workspace to given object |
138
+ | irb_source | irb_core | source | | Evals full path file line by line |
139
+ | irb_jobs | irb_core | jobs | | List workspaces/subsessions |
140
+ | irb_fg | irb_core | fg | | Switch to a workspace/subsession |
141
+ | irb_help | irb_core | help | | Ri based help |
142
+ | irb_kill | irb_core | kill | | Kills a given workspace/subsession |
143
+ | include | irb_core | | | Works same as module#include |
144
+ | irb_exit | irb_core | exit | | Kills the current workspace/subsession |
145
+ | irb_workspaces | irb_core | workspaces | | Array of workspaces for current context |
146
+ | irb_context | irb_core | conf | | Displays configuration for current workspace/subsession |
147
+ | install_alias_method | irb_core | | | Aliases given method, allows lazy loading of dependent file |
148
+ | irb_current_working_workspace | irb_core | cwws | | Prints current workspace |
149
+ +-------------------------------+----------+------------+--------------------------------------------+-----------------------------------------------------------------------------+
150
+ 28 rows in set
151
+
152
+ # Sweet! Now we have a list and description of commands that come with irb.
153
+
154
+ == Todo
155
+ * More tests
156
+ * Making commands out of existing gems easier and more powerful
157
+ * Features based on commands and their argument types i.e. completing and piping
158
+ * Consider dropping alias gem dependency if not using its full potential
159
+
160
+ == Bugs/Issues
161
+ Please report them {on github}[http://github.com/cldwalker/boson/issues].
162
+
163
+ == Contributing
164
+ {See here}[http://tagaholic.me/contributing.html]
165
+
166
+ == Motivation
167
+ My {tagging obsession}[http://github.com/cldwalker/tag-tree] from the ruby console.
168
+
169
+ == Links
170
+ * http://tagaholic.me/2009/10/14/boson-command-your-ruby-universe.html
171
+ * http://tagaholic.me/2009/10/15/boson-and-hirb-interactions.html
172
+ * http://tagaholic.me/2009/10/19/how-boson-enhances-your-irb-experience.html
173
+
174
+ == Credits
175
+ Boson stands on the shoulders of these people and their ideas:
176
+ * Yehuda Katz for inspiring me with Thor and its awesome option parser (Boson::OptionParser).
177
+ * Daniel Berger for his original work on thor's awesome option parser.
178
+ * Dave Thomas for scraping a method's comments (Boson::CommentInspector)
179
+ * Mauricio Fernandez for scraping a method's arguments (Boson::ArgumentInspector)
180
+ * Chris Wanstrath for inspiring Boson's libraries with Rip's packages.
181
+ * And its contributors: @mirell
data/bin/bss ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.dirname(__FILE__), "..","lib","boson"))
4
+ require 'boson/runners/bin_runner'
5
+
6
+ Boson::BinRunner.start
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'rubygems' unless Object.const_defined?(:Gem)
3
+ require File.dirname(__FILE__) + "/lib/boson/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "bosonson"
7
+ s.version = Boson::VERSION
8
+ s.authors = ["Tom Bombadil", "Gabriel Horner"]
9
+ s.email = "amanibhavam@destructuring.org"
10
+ s.homepage = "https://HeSYINUvSBZfxqA.github.com/bosonson"
11
+ s.summary = "A command/task framework similar to rake and thor that opens your ruby universe to the commandline and irb, forked from boson"
12
+ s.description = "bosonson 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. Forked from boson"
13
+ s.required_rubygems_version = ">= 1.3.6"
14
+ s.executables = ['bss']
15
+ s.add_dependency 'hirb', '>= 0.5.0'
16
+ s.add_dependency 'alias', '>= 0.2.2'
17
+ s.add_development_dependency 'mocha'
18
+ s.add_development_dependency 'bacon', '>= 1.1.0'
19
+ s.add_development_dependency 'mocha-on-bacon'
20
+ s.add_development_dependency 'bacon-bits'
21
+ s.files = Dir.glob(%w[{lib,test}/**/*.rb bin/* [A-Z]*.{txt,rdoc} ext/**/*.{rb,c} **/deps.rip]) + %w{bosonson.gemspec}
22
+ s.extra_rdoc_files = ["README.rdoc", "LICENSE.txt"]
23
+ s.license = 'MIT'
24
+ end
@@ -0,0 +1,2 @@
1
+ hirb >=0.5.0
2
+ alias >=0.2.2
@@ -0,0 +1,96 @@
1
+ %w{hirb alias}.each {|e| require e }
2
+ %w{runner runners/console_runner repo manager loader inspector library}.each {|e| require "boson/#{e}" }
3
+ %w{argument method comment}.each {|e| require "boson/inspectors/#{e}_inspector" }
4
+ # order of library subclasses matters
5
+ %w{module file gem require local_file}.each {|e| require "boson/libraries/#{e}_library" }
6
+ (%w{namespace view command util commands option_parser options} +
7
+ %w{index repo_index scientist option_command pipe pipes version}).each {|e| require "boson/#{e}" }
8
+
9
+ # This module stores the libraries, commands, repos and main object used throughout Boson.
10
+ #
11
+ # Useful documentation links:
12
+ # * Boson::BinRunner - Runs the boson executable
13
+ # * Boson::ConsoleRunner - Runs Boson from the ruby console
14
+ # * Boson::Repo.config - Explains main config file
15
+ # * Boson::Library - All about libraries
16
+ # * Boson::FileLibrary - Explains creating libraries as files
17
+ # * Boson::Loader - Explains library module callbacks
18
+ # * Boson::OptionParser - All about options
19
+ module Boson
20
+ # Module which is extended by Boson.main_object to give it command functionality.
21
+ module Universe; include Commands::Namespace; end
22
+ NAMESPACE = '.' # Delimits namespace from command
23
+ extend self
24
+ # The object which holds and executes all command functionality
25
+ attr_accessor :main_object
26
+ attr_accessor :commands, :libraries
27
+ alias_method :higgs, :main_object
28
+
29
+ # Array of loaded Boson::Library objects.
30
+ def libraries
31
+ @libraries ||= Array.new
32
+ end
33
+
34
+ # Array of loaded Boson::Command objects.
35
+ def commands
36
+ @commands ||= Array.new
37
+ end
38
+
39
+ # The main required repository which defaults to ~/.boson.
40
+ def repo
41
+ @repo ||= Repo.new("#{Util.find_home}/.boson")
42
+ end
43
+
44
+ # An optional local repository which defaults to ./lib/boson or ./.boson.
45
+ def local_repo
46
+ @local_repo ||= begin
47
+ ignored_dirs = (repo.config[:ignore_directories] || []).map {|e| File.expand_path(e) }
48
+ dir = ["lib/boson", ".boson"].find {|e| File.directory?(e) &&
49
+ File.expand_path(e) != repo.dir && !ignored_dirs.include?(File.expand_path('.')) }
50
+ Repo.new(dir) if dir
51
+ end
52
+ end
53
+
54
+ # The array of loaded repositories containing the main repo and possible local and global repos
55
+ def repos
56
+ @repos ||= [repo, local_repo, global_repo].compact
57
+ end
58
+
59
+ # Optional global repository at /etc/boson
60
+ def global_repo
61
+ File.exists?('/etc/boson') ? Repo.new('/etc/boson') : nil
62
+ end
63
+
64
+ def main_object=(value) #:nodoc:
65
+ @main_object = value.extend(Universe)
66
+ end
67
+
68
+ def library(query, attribute='name') #:nodoc:
69
+ libraries.find {|e| e.send(attribute) == query }
70
+ end
71
+
72
+ # Start Boson by loading repositories and their configured libraries.
73
+ # See ConsoleRunner.start for its options.
74
+ def start(options={})
75
+ ConsoleRunner.start(options)
76
+ end
77
+
78
+ # Invoke an action on the main object.
79
+ def invoke(*args, &block)
80
+ main_object.send(*args, &block)
81
+ end
82
+
83
+ # Invoke command string even with namespaces
84
+ def full_invoke(cmd, args) #:nodoc:
85
+ command, subcommand = cmd.include?(NAMESPACE) ? cmd.split(NAMESPACE, 2) : [cmd, nil]
86
+ dispatcher = subcommand ? Boson.invoke(command) : Boson.main_object
87
+ dispatcher.send(subcommand || command, *args)
88
+ end
89
+
90
+ # Boolean indicating if the main object can invoke the given method/command.
91
+ def can_invoke?(meth, priv=true)
92
+ Boson.main_object.respond_to? meth, priv
93
+ end
94
+ end
95
+
96
+ Boson.main_object = self
@@ -0,0 +1,196 @@
1
+ module Boson
2
+ # A command starts with the functionality of a ruby method and adds benefits with options, render_options, etc.
3
+ class Command
4
+ class <<self; attr_accessor :all_option_commands ; end
5
+
6
+ # Creates a command given its name and a library.
7
+ def self.create(name, library)
8
+ obj = new(new_attributes(name, library))
9
+ if @all_option_commands && !%w{get method_missing}.include?(name)
10
+ obj.make_option_command(library)
11
+ end
12
+ obj
13
+ end
14
+
15
+ # Used to generate a command's initial attributes when creating a command object
16
+ def self.new_attributes(name, library)
17
+ (library.commands_hash[name] || {}).merge({:name=>name, :lib=>library.name, :namespace=>library.namespace})
18
+ end
19
+
20
+ # Finds a command, namespaced or not and aliased or not. If found returns the
21
+ # command object, otherwise returns nil.
22
+ def self.find(command, commands=Boson.commands)
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"
37
+ end
38
+
39
+ ATTRIBUTES = [:name, :lib, :alias, :desc, :options, :args, :config]
40
+ attr_accessor *(ATTRIBUTES + [:render_options, :namespace, :default_option])
41
+ # A hash of attributes which map to instance variables and values. :name
42
+ # and :lib are required keys.
43
+ #
44
+ # Attributes that can be configured:
45
+ # [*:desc*] Description that shows up in command listings
46
+ # [*:alias*] Alternative name for command
47
+ # [*:options*] Hash of options passed to OptionParser
48
+ # [*:render_options*] Hash of rendering options to pass to OptionParser. If the key :output_class is passed,
49
+ # that class's Hirb config will serve as defaults for this rendering hash.
50
+ # [*:option_command*] Boolean to wrap a command with an OptionCommand object i.e. allow commands to have options.
51
+ # [*:args*] Should only be set if not automatically set. This attribute is only
52
+ # important for commands that have options/render_options. Its value can be an array
53
+ # (as ArgumentInspector.scrape_with_eval produces), a number representing
54
+ # the number of arguments or '*' if the command has a variable number of arguments.
55
+ # [*:default_option*] Only for an option command that has one or zero arguments. This treats the given
56
+ # option as an optional first argument. Example:
57
+ # # For a command with default option 'query' and options --query and -v
58
+ # 'some -v' -> '--query=some -v'
59
+ # '-v' -> '-v'
60
+ # [*:config*] A hash for third party libraries to get and set custom command attributes.
61
+ def initialize(attributes)
62
+ hash = attributes.dup
63
+ @name = hash.delete(:name) or raise ArgumentError
64
+ @lib = hash.delete(:lib) or raise ArgumentError
65
+ [:alias, :desc, :options, :namespace, :default_option, :option_command].each do |e|
66
+ instance_variable_set("@#{e}", hash.delete(e)) if hash.key?(e)
67
+ end
68
+
69
+ if hash[:render_options] && (@render_options = hash.delete(:render_options))[:output_class]
70
+ @render_options = Util.recursive_hash_merge View.class_config(@render_options[:output_class]), @render_options
71
+ end
72
+
73
+ if (args = hash.delete(:args))
74
+ if args.is_a?(Array)
75
+ @args = args
76
+ elsif args.to_s[/^\d+/]
77
+ @arg_size = args.to_i
78
+ elsif args == '*'
79
+ @args = [['*args']]
80
+ end
81
+ end
82
+ @config = Util.recursive_hash_merge hash, hash.delete(:config) || {}
83
+ end
84
+
85
+ # Library object a command belongs to.
86
+ def library
87
+ @library ||= Boson.library(@lib)
88
+ end
89
+
90
+ # Array of array args with optional defaults. Scraped with ArgumentInspector.
91
+ def args(lib=library)
92
+ @args = !@args.nil? ? @args : begin
93
+ if lib
94
+ file_string, meth = file_string_and_method_for_args(lib)
95
+ (file_string && meth && (@file_parsed_args = true) &&
96
+ ArgumentInspector.scrape_with_text(file_string, meth))
97
+ end || false
98
+ end
99
+ end
100
+
101
+ # Option parser for command as defined by @options.
102
+ def option_parser
103
+ @option_parser ||= OptionParser.new(@options || {})
104
+ end
105
+
106
+ # Option parser for command as defined by @render_options.
107
+ def render_option_parser
108
+ option_command? ? Boson::Scientist.option_command(self).option_parser : nil
109
+ end
110
+
111
+ # Help string for options if a command has it.
112
+ def option_help
113
+ @options ? option_parser.to_s : ''
114
+ end
115
+
116
+ # Usage string for command, created from options and args.
117
+ def usage
118
+ return '' if options.nil? && args.nil?
119
+ usage_args = args && @options && !has_splat_args? ?
120
+ (@default_option ? [[@default_option.to_s, @file_parsed_args ? ''.inspect : '']] + args[0..-2] :
121
+ args[0..-2]) : args
122
+ str = args ? usage_args.map {|e|
123
+ (e.size < 2) ? "[#{e[0]}]" : "[#{e[0]}=#{@file_parsed_args ? e[1] : e[1].inspect}]"
124
+ }.join(' ') : '[*unknown]'
125
+ str + option_help
126
+ end
127
+
128
+ # Full name is only different than name if a command has a namespace.
129
+ # The full name should be what you would type to execute the command.
130
+ def full_name
131
+ @namespace ? "#{@namespace}.#{@name}" : @name
132
+ end
133
+
134
+ #:stopdoc:
135
+ # until @config is consistent in index + actual loading
136
+ def config
137
+ @config ||= {}
138
+ end
139
+
140
+ def file_string_and_method_for_args(lib)
141
+ if !lib.is_a?(ModuleLibrary) && (klass_method = (lib.class_commands || {})[@name])
142
+ if RUBY_VERSION >= '1.9'
143
+ klass, meth = klass_method.split(NAMESPACE, 2)
144
+ if (meth_locations = MethodInspector.find_method_locations_for_19(klass, meth))
145
+ file_string = File.read meth_locations[0]
146
+ end
147
+ end
148
+ elsif File.exists?(lib.library_file || '')
149
+ file_string, meth = FileLibrary.read_library_file(lib.library_file), @name
150
+ end
151
+ [file_string, meth]
152
+ end
153
+
154
+ def has_splat_args?
155
+ !!(args && @args[-1] && @args[-1][0][/^\*/])
156
+ end
157
+
158
+ def make_option_command(lib=library)
159
+ @option_command = true
160
+ @args = [['*args']] unless args(lib) || arg_size
161
+ end
162
+
163
+ def option_command?
164
+ options || render_options || @option_command
165
+ end
166
+
167
+ def arg_size
168
+ @arg_size = args ? args.size : nil unless instance_variable_defined?("@arg_size")
169
+ @arg_size
170
+ end
171
+
172
+ def file_parsed_args?
173
+ @file_parsed_args
174
+ end
175
+
176
+ # Deprecated method
177
+ def description
178
+ puts "@command.description has been changed to @command.desc. Delete your old " +
179
+ "Boson index at ~/.boson/command/index.marshal for Boson to work from the commandline."
180
+ Kernel.exit
181
+ end
182
+
183
+ def marshal_dump
184
+ if @args && @args.any? {|e| e[1].is_a?(Module) }
185
+ @args.map! {|e| e.size == 2 ? [e[0], e[1].inspect] : e }
186
+ @file_parsed_args = true
187
+ end
188
+ [@name, @alias, @lib, @desc, @options, @render_options, @args, @default_option]
189
+ end
190
+
191
+ def marshal_load(ary)
192
+ @name, @alias, @lib, @desc, @options, @render_options, @args, @default_option = ary
193
+ end
194
+ #:startdoc:
195
+ end
196
+ end