rubikon 0.5.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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
|