rubikon 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/core_ext/enumerable.rb +31 -0
- data/lib/rubikon/application/dsl_methods.rb +7 -0
- data/lib/rubikon/application/instance_methods.rb +64 -27
- data/lib/rubikon/command.rb +62 -0
- data/lib/rubikon/exceptions.rb +14 -0
- data/lib/rubikon/flag.rb +2 -2
- data/lib/rubikon/has_arguments.rb +1 -0
- data/lib/rubikon/option.rb +2 -1
- data/lib/rubikon/parameter.rb +2 -0
- data/lib/rubikon/progress_bar.rb +1 -1
- data/lib/rubikon/throbber.rb +1 -1
- data/lib/rubikon.rb +1 -1
- data/test/test_application.rb +1 -1
- data/test/testapps.rb +2 -1
- metadata +5 -4
@@ -0,0 +1,31 @@
|
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2010, Sebastian Staudt
|
5
|
+
|
6
|
+
unless Enumerable.method_defined?(:max_by)
|
7
|
+
|
8
|
+
# Extends Ruby's own Enumrable module with method #max_by? for Ruby < 1.8.7
|
9
|
+
#
|
10
|
+
# @author Sebastian Staudt
|
11
|
+
# @since 0.5.0
|
12
|
+
module Enumerable
|
13
|
+
|
14
|
+
def find_index(obj)
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the object in enum that gives the maximum value from the given
|
19
|
+
# block.
|
20
|
+
#
|
21
|
+
# @yield [obj] The block to call on each element in the enum
|
22
|
+
# @yieldparam [Object] obj A single object in the enum
|
23
|
+
# @yieldreturn [Comparable] A value that can be compared (+<=>+) with the
|
24
|
+
# values of the other objects in the enum
|
25
|
+
def max_by(&block)
|
26
|
+
max { |a , b| block.call(a) <=> block.call(b) }
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -32,6 +32,7 @@ module Rubikon
|
|
32
32
|
# user on the command-line.
|
33
33
|
#
|
34
34
|
# @param [#to_sym] name The name of the parameter to check
|
35
|
+
# @see Parameter
|
35
36
|
# @since 0.2.0
|
36
37
|
#
|
37
38
|
# @example
|
@@ -73,6 +74,8 @@ module Rubikon
|
|
73
74
|
# is called with the associated parameter
|
74
75
|
#
|
75
76
|
# @return [Command]
|
77
|
+
# @see default
|
78
|
+
# @see Command
|
76
79
|
# @since 0.2.0
|
77
80
|
def command(name, arg_count = nil, description = nil, &block)
|
78
81
|
command = nil
|
@@ -127,6 +130,8 @@ module Rubikon
|
|
127
130
|
# parameter is given to the application
|
128
131
|
#
|
129
132
|
# @return [Command] The default Command object
|
133
|
+
# @see Command
|
134
|
+
# @see command
|
130
135
|
# @since 0.2.0
|
131
136
|
def default(arg_count = nil, description = nil, &block)
|
132
137
|
if arg_count.is_a? Symbol
|
@@ -275,6 +280,7 @@ module Rubikon
|
|
275
280
|
# arbitrary number of arguments
|
276
281
|
# @param [Proc] block An optional code block that should be executed if
|
277
282
|
# this option is used
|
283
|
+
# @see Option
|
278
284
|
# @since 0.2.0
|
279
285
|
#
|
280
286
|
# @example
|
@@ -439,6 +445,7 @@ module Rubikon
|
|
439
445
|
#
|
440
446
|
# @param [Proc] block The block to execute while the throbber is
|
441
447
|
# displayed
|
448
|
+
# @see Throbber
|
442
449
|
# @since 0.2.0
|
443
450
|
# @yield While the block is executed a throbber is displayed
|
444
451
|
#
|
@@ -51,6 +51,7 @@ module Rubikon
|
|
51
51
|
@parameters = []
|
52
52
|
@sandbox = Sandbox.new(self)
|
53
53
|
@settings = {
|
54
|
+
:autohelp => true,
|
54
55
|
:autorun => true,
|
55
56
|
:colors => true,
|
56
57
|
:config_file => "#{self.class.to_s.downcase}.yml",
|
@@ -109,9 +110,14 @@ module Rubikon
|
|
109
110
|
rescue
|
110
111
|
raise $! if @settings[:raise_errors]
|
111
112
|
|
112
|
-
|
113
|
-
|
114
|
-
|
113
|
+
if @settings[:autohelp] && @commands.key?(:help) &&
|
114
|
+
$!.is_a?(UnknownCommandError)
|
115
|
+
call :help, $!.command
|
116
|
+
else
|
117
|
+
puts "r{Error:}\n #{$!.message}"
|
118
|
+
debug " at #{$!.backtrace.join("\n at ")}"
|
119
|
+
exit 1
|
120
|
+
end
|
115
121
|
ensure
|
116
122
|
InstanceMethods.instance_method(:reset).bind(self).call
|
117
123
|
end
|
@@ -149,6 +155,38 @@ module Rubikon
|
|
149
155
|
global_flag :d => :debug
|
150
156
|
end
|
151
157
|
|
158
|
+
# Prints a help screen for this application
|
159
|
+
#
|
160
|
+
# @param [String] info A additional information string to be displayed
|
161
|
+
# right after usage information
|
162
|
+
# @since 0.6.0
|
163
|
+
def help(info = nil)
|
164
|
+
help = {}
|
165
|
+
@commands.each_value do |command|
|
166
|
+
help[command.name.to_s] = command.description
|
167
|
+
end
|
168
|
+
help.delete('__default')
|
169
|
+
|
170
|
+
if @commands.key? :__default
|
171
|
+
puts " [command] [args]\n\n"
|
172
|
+
else
|
173
|
+
puts " command [args]\n\n"
|
174
|
+
end
|
175
|
+
|
176
|
+
puts "#{info}\n\n" unless info.nil?
|
177
|
+
|
178
|
+
puts 'Commands:'
|
179
|
+
max_command_length = help.keys.max_by { |a| a.size }.size
|
180
|
+
help.sort_by { |name, description| name }.each do |name, description|
|
181
|
+
puts " #{name.ljust(max_command_length)} #{description}"
|
182
|
+
end
|
183
|
+
|
184
|
+
if @commands.key?(:__default) && @commands[:__default].description != :hidden
|
185
|
+
put "\nYou can also call this application without a command:"
|
186
|
+
puts @commands[:__default].help(false) + "\n"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
152
190
|
# Defines a command for displaying a help screen
|
153
191
|
#
|
154
192
|
# This takes any defined commands and it's corresponding options and
|
@@ -158,16 +196,11 @@ module Rubikon
|
|
158
196
|
global_parameters = @global_parameters
|
159
197
|
settings = @settings
|
160
198
|
|
161
|
-
command :help,
|
199
|
+
command :help, 0..1, 'Show help for the application or a single command' do
|
162
200
|
put settings[:help_banner]
|
163
201
|
|
164
|
-
help = {}
|
165
|
-
commands.each_value do |command|
|
166
|
-
help[command.name.to_s] = command.description
|
167
|
-
end
|
168
|
-
|
169
202
|
global_params = ''
|
170
|
-
global_parameters.values.uniq.
|
203
|
+
global_parameters.values.uniq.sort_by { |a| a.name.to_s }.each do |param|
|
171
204
|
global_params << ' ['
|
172
205
|
([param.name] + param.aliases).each_with_index do |name, index|
|
173
206
|
name = name.to_s
|
@@ -178,19 +211,19 @@ module Rubikon
|
|
178
211
|
global_params << ' ...' if param.is_a?(Option)
|
179
212
|
global_params << ']'
|
180
213
|
end
|
214
|
+
put global_params
|
181
215
|
|
182
|
-
|
183
|
-
if default_description.nil?
|
184
|
-
puts "#{global_params} command [args]\n\n"
|
185
|
-
else
|
186
|
-
puts "#{global_params} [command] [args]\n\n"
|
187
|
-
puts "Without command: #{default_description}\n\n"
|
188
|
-
end
|
216
|
+
app_help = lambda { |info| @__app__.instance_eval { help(info) } }
|
189
217
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
218
|
+
unless args.first.nil?
|
219
|
+
command = args.first.to_sym
|
220
|
+
if commands.keys.include?(command)
|
221
|
+
puts commands[command].help
|
222
|
+
else
|
223
|
+
app_help.call("The command \"#{command}\" is undefined. The following commands are available:")
|
224
|
+
end
|
225
|
+
else
|
226
|
+
app_help.call(nil)
|
194
227
|
end
|
195
228
|
end
|
196
229
|
end
|
@@ -240,7 +273,8 @@ module Rubikon
|
|
240
273
|
InstanceMethods.instance_method(:help_command).bind(self).call
|
241
274
|
InstanceMethods.instance_method(:verbose_flag).bind(self).call
|
242
275
|
|
243
|
-
if @settings[:help_as_default] &&
|
276
|
+
if @settings[:help_as_default] && @commands.key?(:help) &&
|
277
|
+
!@commands.key?(:__default)
|
244
278
|
default :help
|
245
279
|
end
|
246
280
|
|
@@ -299,19 +333,22 @@ module Rubikon
|
|
299
333
|
# parameters of this command that have been supplied and any
|
300
334
|
# additional command-line arguments supplied
|
301
335
|
def parse_arguments(args)
|
302
|
-
command_arg = args.
|
303
|
-
if command_arg
|
336
|
+
command_arg = args.find { |arg| arg == '--' || !arg.start_with?('-') }
|
337
|
+
command_arg = nil if command_arg == '--'
|
338
|
+
|
339
|
+
if command_arg.nil?
|
304
340
|
command = @commands[:__default]
|
305
|
-
args.unshift(command_arg) unless command_arg.nil?
|
306
341
|
raise NoDefaultCommandError if command.nil?
|
307
342
|
else
|
308
343
|
command = @commands[command_arg.to_sym]
|
344
|
+
args.delete_at args.index(command_arg)
|
309
345
|
raise UnknownCommandError.new(command_arg) if command.nil?
|
310
346
|
end
|
311
347
|
|
348
|
+
args.delete '--'
|
312
349
|
args = args.map do |arg|
|
313
350
|
if !arg.start_with?('--') && arg.start_with?('-') && arg.size > 2
|
314
|
-
arg[1..-1].split('').map { |a| "-#{a}"}
|
351
|
+
arg[1..-1].split('').map { |a| "-#{a}" }
|
315
352
|
else
|
316
353
|
arg
|
317
354
|
end
|
@@ -354,7 +391,7 @@ module Rubikon
|
|
354
391
|
# @see Parameter#reset
|
355
392
|
# @since 0.4.0
|
356
393
|
def reset
|
357
|
-
ostream.rewind
|
394
|
+
ostream.rewind if ostream.is_a? StringIO || !ostream.stat.chardev?
|
358
395
|
ColoredIO.remove_color_filter(ostream)
|
359
396
|
(@commands.values + @global_parameters.values).uniq.each do |param|
|
360
397
|
param.send :reset
|
data/lib/rubikon/command.rb
CHANGED
@@ -14,6 +14,8 @@ module Rubikon
|
|
14
14
|
# be executed when running the Application.
|
15
15
|
#
|
16
16
|
# @author Sebastian Staudt
|
17
|
+
# @see Application::DSLMethods#command
|
18
|
+
# @see Application::DSLMethods#default
|
17
19
|
# @since 0.3.0
|
18
20
|
class Command
|
19
21
|
|
@@ -56,6 +58,66 @@ module Rubikon
|
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
61
|
+
# Generate help for this command
|
62
|
+
#
|
63
|
+
# @param [Boolean] show_usage If +true+, the returned String will also
|
64
|
+
# include usage information
|
65
|
+
# @return [String] The contents of the help screen for this command
|
66
|
+
# @since 0.6.0
|
67
|
+
def help(show_usage = true)
|
68
|
+
help = ''
|
69
|
+
|
70
|
+
if show_usage
|
71
|
+
help << " #{name}" if name != :__default
|
72
|
+
|
73
|
+
@params.values.uniq.sort_by {|a| a.name.to_s }.each do |param|
|
74
|
+
help << ' ['
|
75
|
+
([param.name] + param.aliases).each_with_index do |name, index|
|
76
|
+
name = name.to_s
|
77
|
+
help << '|' if index > 0
|
78
|
+
help << '-' if name.size > 1
|
79
|
+
help << "-#{name}"
|
80
|
+
end
|
81
|
+
help << ' ...' if param.is_a?(Option)
|
82
|
+
help << ']'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
help << "\n\n#{description}" unless description.nil?
|
87
|
+
|
88
|
+
help_flags = {}
|
89
|
+
help_options = {}
|
90
|
+
params.each_value do |param|
|
91
|
+
if param.is_a? Flag
|
92
|
+
help_flags[param.name.to_s] = param
|
93
|
+
else
|
94
|
+
help_options[param.name.to_s] = param
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
param_name = lambda { |name| "#{name.size > 1 ? '-' : ' '}-#{name}" }
|
99
|
+
unless help_flags.empty? && help_options.empty?
|
100
|
+
max_param_length = (help_flags.keys + help_options.keys).
|
101
|
+
max_by { |a| a.size }.size + 2
|
102
|
+
end
|
103
|
+
|
104
|
+
unless help_flags.empty?
|
105
|
+
help << "\n\nFlags:"
|
106
|
+
help_flags.sort_by { |name, param| name }.each do |name, param|
|
107
|
+
help << "\n #{param_name.call(name).ljust(max_param_length)}"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
unless help_options.empty?
|
112
|
+
help << "\n\nOptions:\n"
|
113
|
+
help_options.sort_by { |name, param| name }.each do |name, param|
|
114
|
+
help << " #{param_name.call(name).ljust(max_param_length)} ...\n"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
help
|
119
|
+
end
|
120
|
+
|
59
121
|
private
|
60
122
|
|
61
123
|
# Add a new parameter for this command
|
data/lib/rubikon/exceptions.rb
CHANGED
@@ -45,6 +45,7 @@ module Rubikon
|
|
45
45
|
# Raised if the user did not specify a command and no default command exists
|
46
46
|
#
|
47
47
|
# @author Sebastian Staudt
|
48
|
+
# @see Application::DSLMethods#default
|
48
49
|
# @since 0.3.0
|
49
50
|
class NoDefaultCommandError < ArgumentError
|
50
51
|
|
@@ -57,11 +58,20 @@ module Rubikon
|
|
57
58
|
# Raised if a command has been supplied that does not exist
|
58
59
|
#
|
59
60
|
# @author Sebastian Staudt
|
61
|
+
# @see Application::DSLMethods#command
|
60
62
|
# @since 0.3.0
|
61
63
|
class UnknownCommandError < ArgumentError
|
62
64
|
|
65
|
+
# @return [Symbol] The name of the command that has been tried to access
|
66
|
+
attr_reader :command
|
67
|
+
|
68
|
+
# Creates a new error and stores the name of the command that could not be
|
69
|
+
# found
|
70
|
+
#
|
71
|
+
# @param [Symbol] name The name of the unknown command
|
63
72
|
def initialize(name)
|
64
73
|
super "Unknown command: #{name}"
|
74
|
+
@command = name
|
65
75
|
end
|
66
76
|
|
67
77
|
end
|
@@ -69,6 +79,10 @@ module Rubikon
|
|
69
79
|
# Raised if a parameter has been supplied that does not exist
|
70
80
|
#
|
71
81
|
# @author Sebastian Staudt
|
82
|
+
# @see Application::DSLMethods#flag
|
83
|
+
# @see Application::DSLMethods#option
|
84
|
+
# @see Application::DSLMethods#global_flag
|
85
|
+
# @see Application::DSLMethods#global_option
|
72
86
|
# @since 0.3.0
|
73
87
|
class UnknownParameterError < ArgumentError
|
74
88
|
|
data/lib/rubikon/flag.rb
CHANGED
@@ -10,8 +10,8 @@ module Rubikon
|
|
10
10
|
# A flag is an application parameter without arguments
|
11
11
|
#
|
12
12
|
# @author Sebastian Staudt
|
13
|
-
# @see Application::
|
14
|
-
# @see Application::
|
13
|
+
# @see Application::DSLMethods#flag
|
14
|
+
# @see Application::DSLMethods#global_flag
|
15
15
|
# @see Parameter
|
16
16
|
# @since 0.3.0
|
17
17
|
class Flag
|
@@ -72,6 +72,7 @@ module Rubikon
|
|
72
72
|
# indices can be used always while symbolic arguments are only
|
73
73
|
# available for named arguments.
|
74
74
|
# @return The argument with the specified index
|
75
|
+
# @see #args
|
75
76
|
# @since 0.4.0
|
76
77
|
def [](arg)
|
77
78
|
arg = @arg_names.index(arg) if arg.is_a? Symbol
|
data/lib/rubikon/option.rb
CHANGED
data/lib/rubikon/parameter.rb
CHANGED
data/lib/rubikon/progress_bar.rb
CHANGED
data/lib/rubikon/throbber.rb
CHANGED
data/lib/rubikon.rb
CHANGED
data/test/test_application.rb
CHANGED
@@ -120,7 +120,7 @@ class TestApplication < Test::Unit::TestCase
|
|
120
120
|
|
121
121
|
should 'have a working help command' do
|
122
122
|
@app.run(%w{help})
|
123
|
-
assert_match /Usage: [^ ]* \[--debug\|-d\] \[--gflag\|--gf1\|--gf2\] \[--gopt\|--go1\|--go2 \.\.\.\] \[--verbose\|-v\] command \[args\]\n\nCommands:\n arguments \n globalopt \n help
|
123
|
+
assert_match /Usage: [^ ]* \[--debug\|-d\] \[--gflag\|--gf1\|--gf2\] \[--gopt\|--go1\|--go2 \.\.\.\] \[--verbose\|-v\] \[command\] \[args\]\n\nCommands:\n arguments \n globalopt \n help Show help for the application or a single command\n input \n object_id \n parameters \n progressbar \n sandbox \n throbber \n/, @ostream.string
|
124
124
|
end
|
125
125
|
|
126
126
|
should 'have a working DSL for command parameters' do
|
data/test/testapps.rb
CHANGED
@@ -13,6 +13,7 @@ end
|
|
13
13
|
|
14
14
|
class TestApp < Application::Base
|
15
15
|
|
16
|
+
set :autohelp, false
|
16
17
|
set :autorun, false
|
17
18
|
set :name, 'Rubikon test application'
|
18
19
|
set :raise_errors, true
|
@@ -29,7 +30,7 @@ class TestApp < Application::Base
|
|
29
30
|
end
|
30
31
|
global_option :go2 => :gopt
|
31
32
|
|
32
|
-
default do
|
33
|
+
default nil, :hidden do
|
33
34
|
'default command'
|
34
35
|
end
|
35
36
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubikon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 5
|
9
|
-
-
|
10
|
-
version: 0.5.
|
9
|
+
- 2
|
10
|
+
version: 0.5.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Sebastian Staudt
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-12-
|
18
|
+
date: 2010-12-04 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -74,6 +74,7 @@ files:
|
|
74
74
|
- LICENSE
|
75
75
|
- README.md
|
76
76
|
- Rakefile
|
77
|
+
- lib/core_ext/enumerable.rb
|
77
78
|
- lib/core_ext/object.rb
|
78
79
|
- lib/core_ext/string.rb
|
79
80
|
- lib/rubikon.rb
|