boson 0.2.3 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +76 -0
- data/README.rdoc +6 -6
- data/Rakefile +24 -41
- data/gemspec +19 -0
- data/lib/boson.rb +4 -4
- data/lib/boson/command.rb +2 -2
- data/lib/boson/commands/core.rb +1 -1
- data/lib/boson/commands/web_core.rb +16 -12
- data/lib/boson/manager.rb +1 -1
- data/lib/boson/pipes.rb +6 -2
- data/lib/boson/repo_index.rb +1 -1
- data/lib/boson/runner.rb +2 -2
- data/lib/boson/runners/bin_runner.rb +72 -29
- data/lib/boson/scientist.rb +22 -4
- data/lib/boson/util.rb +9 -1
- data/lib/boson/version.rb +3 -0
- data/test/argument_inspector_test.rb +47 -51
- data/test/bacon_extensions.rb +26 -0
- data/test/bin_runner_test.rb +160 -160
- data/test/comment_inspector_test.rb +87 -89
- data/test/file_library_test.rb +32 -34
- data/test/loader_test.rb +181 -182
- data/test/manager_test.rb +76 -78
- data/test/method_inspector_test.rb +51 -53
- data/test/option_parser_test.rb +49 -42
- data/test/options_test.rb +168 -168
- data/test/pipes_test.rb +48 -46
- data/test/repo_index_test.rb +117 -113
- data/test/repo_test.rb +17 -17
- data/test/runner_test.rb +31 -34
- data/test/scientist_test.rb +258 -254
- data/test/test_helper.rb +21 -38
- data/test/util_test.rb +40 -42
- metadata +55 -46
- data/VERSION.yml +0 -5
data/CHANGELOG.rdoc
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
== 0.2.4
|
2
|
+
* Tests use bacon and pass on all major ruby versions
|
3
|
+
* Fixed bug for 1.8.7 and super (#10)
|
4
|
+
* Added commandline pipes with '+'
|
5
|
+
* Fixed bug when requiring rubygems in a library
|
6
|
+
* Fixed bug in sort pipe for 1.9.2
|
7
|
+
* Got rid of jeweler in Rakefile and $LOAD_PATH meddling
|
8
|
+
* Refactored BinRunner's error handling
|
9
|
+
|
10
|
+
== 0.2.3
|
11
|
+
* Added improved support and additional attributes for user pipe options
|
12
|
+
* Added :pipes global command option
|
13
|
+
* Added json + yaml parsing to get()
|
14
|
+
* Added underscore searching to option values
|
15
|
+
* Added build_install() command
|
16
|
+
* Added :usage_options commandline option
|
17
|
+
|
18
|
+
== 0.2.2
|
19
|
+
* Renamed Boson::Command#description to #desc. Delete your index at ~/.boson/config/index.marshal.
|
20
|
+
* Renamed Boson::Command#global_options to #option_command. Update your configs.
|
21
|
+
* Bug fix for Windows and indexing (#4)
|
22
|
+
* Added system wide Boson commands at /etc/boson (#2)
|
23
|
+
* Added Boson::Command#config for plugins to set/get via @config
|
24
|
+
* Added option_command and unload options to BinRunner
|
25
|
+
* Added special option parsing characters: - and --
|
26
|
+
* Added special :output_class key for global render_options
|
27
|
+
* Added :delete_options global option
|
28
|
+
* Fixed --no variant for single letter booleans
|
29
|
+
* Fixed MethodInspector parsing arguments with special characters
|
30
|
+
* Allow global -p to work even in failures
|
31
|
+
* Allow -hv to default to verbose help
|
32
|
+
* Boson::OptionParser tweaks
|
33
|
+
|
34
|
+
== 0.2.1
|
35
|
+
* Added local libraries: Bosonfile and under local repositories
|
36
|
+
* Added config method attribute.
|
37
|
+
* Added default_option and global_options command attributes.
|
38
|
+
* Added OptionParser.parse and OptionParser.usage for scripting use.
|
39
|
+
* Improved auto-rendering from commandline.
|
40
|
+
* Removed library reload.
|
41
|
+
* Better docs.
|
42
|
+
|
43
|
+
== 0.2.0
|
44
|
+
* Command options
|
45
|
+
** Added custom global and render options for commands.
|
46
|
+
** Added pipe and filter option commands.
|
47
|
+
** Add global query option.
|
48
|
+
* Options
|
49
|
+
** Users can define custom option types.
|
50
|
+
** Added hash option type.
|
51
|
+
** Any option can be a boolean with :bool_default attribute.
|
52
|
+
** Adding * aliasing to relevant options.
|
53
|
+
* Made Boson::Scientist.commandify for use outside Boson.
|
54
|
+
* Any command can have a default option.
|
55
|
+
* Directories are namespaced automatically.
|
56
|
+
* Solidified library module callback methods.
|
57
|
+
* Added support for Windows home.
|
58
|
+
* Improved ModuleLibrary to handle class or module class methods.
|
59
|
+
* Better search and sort integration with Hirb.
|
60
|
+
* Better docs.
|
61
|
+
* Fixed number of bugs.
|
62
|
+
* query_fields option for searching libraries and commands is deprecated. Specifying query
|
63
|
+
fields is now done by prefixing a query with ':'. For example:
|
64
|
+
bash> boson commands library_type:gem
|
65
|
+
# instead of
|
66
|
+
bash> boson commands gem --query_fields=library_type
|
67
|
+
|
68
|
+
== 0.1.0
|
69
|
+
* First real release
|
70
|
+
* Plenty of fixes to make it ruby 1.9 ready.
|
71
|
+
* Added more documentation
|
72
|
+
* BinRunner tweaks and bug fixes
|
73
|
+
* Other miscellaneous bug fixes
|
74
|
+
|
75
|
+
== 0.0.1
|
76
|
+
* An initial release for others to play with.
|
data/README.rdoc
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
+
To read a linkable version of this README, {see here}[http://tagaholic.me/boson/doc/].
|
2
|
+
|
1
3
|
== Description
|
2
4
|
A command/task framework similar to rake and thor that opens your ruby universe to the commandline
|
3
5
|
and irb. For my libraries that use this, see {irbfiles}[http://github.com/cldwalker/irbfiles].
|
4
|
-
Works with
|
5
|
-
|
6
|
-
Note: To read a linkable version of this README, {see here}[http://tagaholic.me/boson/doc/].
|
6
|
+
Works with all major ruby versions.
|
7
7
|
|
8
8
|
== Features
|
9
9
|
* Simple organization: Commands are just methods on an object (default is main) and command libraries are just modules.
|
@@ -161,8 +161,8 @@ My {tagging obsession}[http://github.com/cldwalker/tag-tree] from the ruby conso
|
|
161
161
|
|
162
162
|
== Acknowledgements
|
163
163
|
Boson stands on the shoulders of these people and their ideas:
|
164
|
-
* Yehuda Katz for inspiring me with Thor
|
165
|
-
*
|
164
|
+
* Yehuda Katz for inspiring me with Thor and its awesome option parser (Boson::OptionParser).
|
165
|
+
* Daniel Berger for his original work on thor's awesome option parser.
|
166
166
|
* Dave Thomas for scraping a method's comments (Boson::CommentInspector)
|
167
167
|
* Mauricio Fernandez for scraping a method's arguments (Boson::ArgumentInspector)
|
168
|
-
* Chris Wanstrath for inspiring Boson's libraries with Rip's packages.
|
168
|
+
* Chris Wanstrath for inspiring Boson's libraries with Rip's packages.
|
data/Rakefile
CHANGED
@@ -1,52 +1,35 @@
|
|
1
1
|
require 'rake'
|
2
|
-
require '
|
3
|
-
require 'rake/rdoctask'
|
4
|
-
begin
|
5
|
-
require 'rcov/rcovtask'
|
2
|
+
require 'fileutils'
|
6
3
|
|
7
|
-
|
8
|
-
|
9
|
-
t.test_files = FileList['test/**/*_test.rb']
|
10
|
-
t.rcov_opts = ["-T -x '/Library/Ruby/*'"]
|
11
|
-
t.verbose = true
|
12
|
-
end
|
13
|
-
rescue LoadError
|
14
|
-
puts "Rcov not available. Install it for rcov-related tasks with: sudo gem install rcov"
|
4
|
+
def gemspec
|
5
|
+
@gemspec ||= eval(File.read('gemspec'), binding, 'gemspec')
|
15
6
|
end
|
16
7
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
s.add_dependency 'hirb', '>= 0.2.10'
|
29
|
-
s.add_dependency 'alias', '>= 0.2.1'
|
30
|
-
s.extra_rdoc_files = ["README.rdoc", "LICENSE.txt"]
|
31
|
-
s.files = FileList["Rakefile", "VERSION.yml", "README.rdoc", "LICENSE.txt", "{bin,lib,test}/**/*"]
|
32
|
-
end
|
8
|
+
desc "Build the gem"
|
9
|
+
task :gem=>:gemspec do
|
10
|
+
sh "gem build gemspec"
|
11
|
+
FileUtils.mkdir_p 'pkg'
|
12
|
+
FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", 'pkg'
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Install the gem locally"
|
16
|
+
task :install => :gem do
|
17
|
+
sh %{gem install pkg/#{gemspec.name}-#{gemspec.version}}
|
18
|
+
end
|
33
19
|
|
34
|
-
|
35
|
-
|
20
|
+
desc "Generate the gemspec"
|
21
|
+
task :generate do
|
22
|
+
puts gemspec.to_ruby
|
36
23
|
end
|
37
24
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
t.verbose = false
|
25
|
+
desc "Validate the gemspec"
|
26
|
+
task :gemspec do
|
27
|
+
gemspec.validate
|
42
28
|
end
|
43
29
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
rdoc.options << '--line-numbers' << '--inline-source'
|
48
|
-
rdoc.rdoc_files.include('README*')
|
49
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
30
|
+
desc 'Run tests'
|
31
|
+
task :test do |t|
|
32
|
+
sh 'bacon -q -Ilib -I. test/*_test.rb'
|
50
33
|
end
|
51
34
|
|
52
|
-
task :default => :test
|
35
|
+
task :default => :test
|
data/gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
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 = "boson"
|
7
|
+
s.version = Boson::VERSION
|
8
|
+
s.authors = ["Gabriel Horner"]
|
9
|
+
s.email = "gabriel.horner@gmail.com"
|
10
|
+
s.homepage = "http://tagaholic.me/boson/"
|
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 provides users with the power to turn any ruby method into a full-fledged commandline tool. Boson achieves this with powerful options (borrowed from thor) and views (thanks to hirb). Some other unique features that differentiate it from rake and thor include being accessible from irb and the commandline, being able to write boson commands in non-dsl ruby and toggling a pretty view of a command's output without additional view code."
|
13
|
+
s.required_rubygems_version = ">= 1.3.6"
|
14
|
+
s.rubyforge_project = 'tagaholic'
|
15
|
+
s.add_dependency 'hirb', '>= 0.2.10'
|
16
|
+
s.add_dependency 'alias', '>= 0.2.1'
|
17
|
+
s.files = Dir.glob(%w[{lib,test}/**/*.rb bin/* [A-Z]*.{txt,rdoc} ext/**/*.{rb,c}]) + %w{Rakefile gemspec}
|
18
|
+
s.extra_rdoc_files = ["README.rdoc", "LICENSE.txt"]
|
19
|
+
end
|
data/lib/boson.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
-
$:.unshift File.dirname(__FILE__) unless $:.include? File.expand_path(File.dirname(__FILE__))
|
2
1
|
%w{hirb alias}.each {|e| require e }
|
3
2
|
%w{runner runners/console_runner repo manager loader inspector library}.each {|e| require "boson/#{e}" }
|
4
3
|
%w{argument method comment}.each {|e| require "boson/inspectors/#{e}_inspector" }
|
5
4
|
# order of library subclasses matters
|
6
5
|
%w{module file gem require local_file}.each {|e| require "boson/libraries/#{e}_library" }
|
7
6
|
(%w{namespace view command util commands option_parser options} +
|
8
|
-
%w{index repo_index scientist option_command pipe pipes}).each {|e| require "boson/#{e}" }
|
7
|
+
%w{index repo_index scientist option_command pipe pipes version}).each {|e| require "boson/#{e}" }
|
9
8
|
|
10
9
|
# This module stores the libraries, commands, repos and main object used throughout Boson.
|
11
10
|
#
|
@@ -20,6 +19,7 @@ $:.unshift File.dirname(__FILE__) unless $:.include? File.expand_path(File.dirna
|
|
20
19
|
module Boson
|
21
20
|
# Module which is extended by Boson.main_object to give it command functionality.
|
22
21
|
module Universe; include Commands::Namespace; end
|
22
|
+
NAMESPACE = '.' # Delimits namespace from command
|
23
23
|
extend self
|
24
24
|
# The object which holds and executes all command functionality
|
25
25
|
attr_accessor :main_object
|
@@ -82,7 +82,7 @@ module Boson
|
|
82
82
|
|
83
83
|
# Invoke command string even with namespaces
|
84
84
|
def full_invoke(cmd, args) #:nodoc:
|
85
|
-
command, subcommand = cmd.include?(
|
85
|
+
command, subcommand = cmd.include?(NAMESPACE) ? cmd.split(NAMESPACE, 2) : [cmd, nil]
|
86
86
|
dispatcher = subcommand ? Boson.invoke(command) : Boson.main_object
|
87
87
|
dispatcher.send(subcommand || command, *args)
|
88
88
|
end
|
@@ -93,4 +93,4 @@ module Boson
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
Boson.main_object = self
|
96
|
+
Boson.main_object = self
|
data/lib/boson/command.rb
CHANGED
@@ -20,7 +20,7 @@ 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
|
-
command, subcommand = command.to_s.split(
|
23
|
+
command, subcommand = command.to_s.split(NAMESPACE, 2)
|
24
24
|
is_namespace_command = lambda {|current_command|
|
25
25
|
[current_command.name, current_command.alias].include?(subcommand) &&
|
26
26
|
current_command.library && (current_command.library.namespace == command)
|
@@ -133,7 +133,7 @@ module Boson
|
|
133
133
|
def file_string_and_method_for_args(lib)
|
134
134
|
if !lib.is_a?(ModuleLibrary) && (klass_method = (lib.class_commands || {})[@name])
|
135
135
|
if RUBY_VERSION >= '1.9'
|
136
|
-
klass, meth = klass_method.split(
|
136
|
+
klass, meth = klass_method.split(NAMESPACE, 2)
|
137
137
|
if (meth_locations = MethodInspector.find_method_locations_for_19(klass, meth))
|
138
138
|
file_string = File.read meth_locations[0]
|
139
139
|
end
|
data/lib/boson/commands/core.rb
CHANGED
@@ -69,7 +69,7 @@ module Boson::Commands::Core #:nodoc:
|
|
69
69
|
puts "\nLOCAL OPTIONS"
|
70
70
|
cmd.option_parser.print_usage_table options[:render_options].dup.merge(:local=>true)
|
71
71
|
end
|
72
|
-
if options[:verbose]
|
72
|
+
if options[:verbose] && cmd.render_option_parser
|
73
73
|
puts "\nGLOBAL OPTIONS"
|
74
74
|
cmd.render_option_parser.print_usage_table options[:render_options].dup
|
75
75
|
end
|
@@ -2,18 +2,21 @@ module Boson::Commands::WebCore
|
|
2
2
|
extend self
|
3
3
|
|
4
4
|
def config #:nodoc:
|
5
|
-
|
6
|
-
:
|
7
|
-
|
8
|
-
|
5
|
+
commands = {
|
6
|
+
'get'=>{ :desc=>"Gets the body of a url", :args=>[['url'],['options', {}]]},
|
7
|
+
'post'=>{ :desc=>'Posts to a url', :args=>[['url'],['options', {}]]},
|
8
|
+
'build_url'=>{ :desc=>"Builds a url, escaping the given params", :args=>[['url'],['params']]},
|
9
|
+
'browser'=>{ :desc=>"Opens urls in a browser on a Mac"},
|
10
|
+
'install'=>{ :desc=>"Installs a library by url. Library should then be loaded with load_library.",
|
11
|
+
:args=>[['url'],['options', {}]],
|
12
|
+
:options=> { :name=>{:type=>:string, :desc=>"Library name to save to"},
|
13
|
+
:force=>{:type=>:boolean, :desc=>'Overwrites an existing library'},
|
14
|
+
:default=>{:type=>:boolean, :desc=>'Adds library as a default library to main config file'},
|
15
|
+
:module_wrap=>{:type=>:boolean, :desc=>"Wraps a module around install using library name"},
|
16
|
+
:method_wrap=>{:type=>:boolean, :desc=>"Wraps a method and module around installed library using library name"}}
|
17
|
+
}
|
9
18
|
}
|
10
|
-
|
11
|
-
commands['install'][:options] = {:name=>{:type=>:string, :desc=>"Library name to save to"},
|
12
|
-
:force=>{:type=>:boolean, :desc=>'Overwrites an existing library'},
|
13
|
-
:default=>{:type=>:boolean, :desc=>'Adds library as a default library to main config file'},
|
14
|
-
:module_wrap=>{:type=>:boolean, :desc=>"Wraps a module around install using library name"},
|
15
|
-
:method_wrap=>{:type=>:boolean, :desc=>"Wraps a method and module around installed library using library name"}}
|
16
|
-
commands['install'][:args] = [['url'],['options', {}]]
|
19
|
+
|
17
20
|
{:library_file=>File.expand_path(__FILE__), :commands=>commands, :namespace=>false}
|
18
21
|
end
|
19
22
|
|
@@ -39,7 +42,8 @@ module Boson::Commands::WebCore
|
|
39
42
|
end
|
40
43
|
|
41
44
|
def_which_requires(:post, 'uri', 'net/http') do |url, options|
|
42
|
-
|
45
|
+
options ||= {}
|
46
|
+
(res = Net::HTTP.post_form(URI.parse(url), options)) && res.body
|
43
47
|
end
|
44
48
|
|
45
49
|
def install(url, options={}) #:nodoc:
|
data/lib/boson/manager.rb
CHANGED
@@ -77,7 +77,7 @@ module Boson
|
|
77
77
|
end
|
78
78
|
|
79
79
|
def load_dependencies(lib, options={})
|
80
|
-
lib_dependencies[lib] = (lib.dependencies
|
80
|
+
lib_dependencies[lib] = Array(lib.dependencies).map do |e|
|
81
81
|
next if loaded?(e)
|
82
82
|
load_once(e, options.merge(:dependency=>true)) ||
|
83
83
|
raise(LoaderError, "Can't load dependency #{e}")
|
data/lib/boson/pipes.rb
CHANGED
@@ -44,9 +44,9 @@ module Boson
|
|
44
44
|
sort_lambda = lambda {}
|
45
45
|
if object[0].is_a?(Hash)
|
46
46
|
sort = sort.to_i if sort.to_s[/^\d+$/]
|
47
|
-
sort_lambda = (object.
|
47
|
+
sort_lambda = untouched_sort?(object.map {|e| e[sort] }) ? lambda {|e| e[sort] } : lambda {|e| e[sort].to_s }
|
48
48
|
else
|
49
|
-
sort_lambda = object.
|
49
|
+
sort_lambda = untouched_sort?(object.map {|e| e.send(sort) }) ? lambda {|e| e.send(sort) || ''} :
|
50
50
|
lambda {|e| e.send(sort).to_s }
|
51
51
|
end
|
52
52
|
object.sort_by &sort_lambda
|
@@ -54,6 +54,10 @@ module Boson
|
|
54
54
|
$stderr.puts "Sort failed with nonexistant method '#{sort}'"
|
55
55
|
end
|
56
56
|
|
57
|
+
def untouched_sort?(values) #:nodoc:
|
58
|
+
values.all? {|e| e.respond_to?(:<=>) } && values.map {|e| e.class }.uniq.size == 1
|
59
|
+
end
|
60
|
+
|
57
61
|
# Reverse an object
|
58
62
|
def reverse_sort_pipe(object, extra=nil)
|
59
63
|
object.reverse
|
data/lib/boson/repo_index.rb
CHANGED
@@ -99,7 +99,7 @@ module Boson
|
|
99
99
|
|
100
100
|
def find_library(command, object=false)
|
101
101
|
read
|
102
|
-
namespace_command = command.split(
|
102
|
+
namespace_command = command.split(NAMESPACE)[0]
|
103
103
|
if (lib = @libraries.find {|e| e.namespace == namespace_command })
|
104
104
|
object ? lib : lib.name
|
105
105
|
elsif (cmd = Command.find(command, @commands))
|
data/lib/boson/runner.rb
CHANGED
@@ -56,9 +56,9 @@ module Boson
|
|
56
56
|
{:verbose=>@options[:verbose]}
|
57
57
|
end
|
58
58
|
|
59
|
-
def autoload_command(cmd)
|
59
|
+
def autoload_command(cmd, opts={:verbose=>verbose?})
|
60
60
|
Index.read
|
61
|
-
(lib = Index.find_library(cmd)) && Manager.load(lib,
|
61
|
+
(lib = Index.find_library(cmd)) && Manager.load(lib, opts)
|
62
62
|
lib
|
63
63
|
end
|
64
64
|
|
@@ -34,6 +34,7 @@ module Boson
|
|
34
34
|
class BinRunner < Runner
|
35
35
|
GLOBAL_OPTIONS = {
|
36
36
|
:verbose=>{:type=>:boolean, :desc=>"Verbose description of loading libraries, errors or help"},
|
37
|
+
:version=>{:type=>:boolean, :desc=>"Prints the current version"},
|
37
38
|
:index=>{:type=>:array, :desc=>"Libraries to index. Libraries must be passed with '='.",
|
38
39
|
:bool_default=>nil, :values=>all_libraries, :regexp=>true, :enum=>false},
|
39
40
|
:execute=>{:type=>:string, :desc=>"Executes given arguments as a one line script"},
|
@@ -47,44 +48,61 @@ module Boson
|
|
47
48
|
:option_commands=>{:type=>:boolean, :desc=>"Toggles on all commands to be defined as option commands" }
|
48
49
|
} #:nodoc:
|
49
50
|
|
51
|
+
PIPE = '+'
|
52
|
+
|
50
53
|
class <<self
|
51
54
|
attr_accessor :command
|
52
55
|
|
53
56
|
# Starts, processes and ends a commandline request.
|
54
57
|
def start(args=ARGV)
|
55
58
|
@command, @options, @args = parse_args(args)
|
59
|
+
return puts("boson #{Boson::VERSION}") if @options[:version]
|
56
60
|
return print_usage if args.empty? || (@command.nil? && !@options[:console] && !@options[:execute])
|
57
61
|
return ConsoleRunner.bin_start(@options[:console], @options[:load]) if @options[:console]
|
58
62
|
init
|
59
|
-
View.toggle_pager if @options[:pager_toggle]
|
60
63
|
|
61
64
|
if @options[:help]
|
65
|
+
autoload_command @command
|
62
66
|
Boson.invoke(:usage, @command, :verbose=>@options[:verbose])
|
63
67
|
elsif @options[:execute]
|
68
|
+
define_autoloader
|
64
69
|
Boson.main_object.instance_eval @options[:execute]
|
65
70
|
else
|
66
71
|
execute_command
|
67
72
|
end
|
73
|
+
rescue NoMethodError
|
74
|
+
print_error_message no_method_error_message
|
68
75
|
rescue
|
69
|
-
|
70
|
-
(Boson.can_invoke?(command[/\w+/]) && command.include?('.') && $!.is_a?(NoMethodError)) }
|
71
|
-
print_error_message @command.to_s[/\w+/] && is_invalid_command.call(@command) ?
|
72
|
-
"Error: Command '#{@command}' not found" : "Error: #{$!.message}"
|
76
|
+
print_error_message default_error_message
|
73
77
|
end
|
74
78
|
|
75
|
-
|
79
|
+
def no_method_error_message #:nodoc:
|
80
|
+
@command = @command.to_s
|
81
|
+
if $!.backtrace.grep(/`(invoke|full_invoke)'$/).empty? ||
|
82
|
+
!$!.message[/undefined method `(\w+\.)?#{@command.split(NAMESPACE)[-1]}'/]
|
83
|
+
default_error_message
|
84
|
+
else
|
85
|
+
@command.to_s[/\w+/] &&
|
86
|
+
(!(Index.read && Index.find_command(@command[/\w+/])) || @command.include?(NAMESPACE)) ?
|
87
|
+
"Error: Command '#{@command}' not found" : default_error_message
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Loads libraries and handles non-critical options
|
76
92
|
def init
|
77
93
|
Runner.in_shell = true
|
78
94
|
Command.all_option_commands = true if @options[:option_commands]
|
79
95
|
super
|
80
|
-
|
81
|
-
if @options
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
96
|
+
|
97
|
+
if @options.key?(:index)
|
98
|
+
Index.update(:verbose=>true, :libraries=>@options[:index])
|
99
|
+
@index_updated = true
|
100
|
+
elsif !@options[:help] && @command && Boson.can_invoke?(@command)
|
101
|
+
Index.update(:verbose=>@options[:verbose])
|
102
|
+
@index_updated = true
|
87
103
|
end
|
104
|
+
Manager.load @options[:load], load_options if @options[:load]
|
105
|
+
View.toggle_pager if @options[:pager_toggle]
|
88
106
|
end
|
89
107
|
|
90
108
|
# Hash of global options passed in from commandline
|
@@ -92,17 +110,27 @@ module Boson
|
|
92
110
|
@options ||= {}
|
93
111
|
end
|
94
112
|
|
113
|
+
# Commands to executed, in order given by user
|
114
|
+
def commands
|
115
|
+
@commands ||= @all_args.map {|e| e[0]}
|
116
|
+
end
|
95
117
|
#:stopdoc:
|
96
118
|
def print_error_message(message)
|
97
119
|
message += "\nOriginal error: #{$!}\n" + $!.backtrace.slice(0,10).map {|e| " " + e }.join("\n") if options[:verbose]
|
98
120
|
$stderr.puts message
|
99
121
|
end
|
100
122
|
|
101
|
-
def
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
123
|
+
def default_error_message
|
124
|
+
"Error: #{$!.message}"
|
125
|
+
end
|
126
|
+
|
127
|
+
def autoload_command(cmd)
|
128
|
+
if !Boson.can_invoke?(cmd, false)
|
129
|
+
unless @index_updated
|
130
|
+
Index.update(:verbose=>@options[:verbose])
|
131
|
+
@index_updated = true
|
132
|
+
end
|
133
|
+
super(cmd, load_options)
|
106
134
|
end
|
107
135
|
end
|
108
136
|
|
@@ -112,24 +140,39 @@ module Boson
|
|
112
140
|
end
|
113
141
|
|
114
142
|
def execute_command
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
(
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
143
|
+
output = @all_args.inject(nil) {|acc, (cmd,*args)|
|
144
|
+
begin
|
145
|
+
@command = cmd # for external errors
|
146
|
+
autoload_command cmd
|
147
|
+
args = translate_args(args, acc)
|
148
|
+
Boson.full_invoke(cmd, args)
|
149
|
+
rescue ArgumentError
|
150
|
+
if $!.class == OptionCommand::CommandArgumentError || ($!.message[/wrong number of arguments/] &&
|
151
|
+
(cmd_obj = Command.find(cmd)) && cmd_obj.arg_size != args.size)
|
152
|
+
print_error_message "'#{cmd}' was called incorrectly."
|
153
|
+
Boson.invoke(:usage, cmd, :one_line=>true)
|
154
|
+
return
|
155
|
+
else
|
156
|
+
raise
|
157
|
+
end
|
158
|
+
end
|
159
|
+
}
|
125
160
|
render_output output
|
126
161
|
end
|
127
162
|
|
163
|
+
def translate_args(args, piped)
|
164
|
+
args.unshift piped if piped
|
165
|
+
args
|
166
|
+
end
|
167
|
+
|
128
168
|
def parse_args(args)
|
169
|
+
@all_args = Util.split_array_by(args, PIPE)
|
170
|
+
args = @all_args[0]
|
129
171
|
@option_parser = OptionParser.new(GLOBAL_OPTIONS)
|
130
172
|
options = @option_parser.parse(args.dup, :opts_before_args=>true)
|
131
173
|
new_args = @option_parser.non_opts
|
132
|
-
[
|
174
|
+
@all_args[0] = new_args
|
175
|
+
[new_args[0], options, new_args[1..-1]]
|
133
176
|
end
|
134
177
|
|
135
178
|
def render_output(output)
|