rubikon 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- puts "r{Error:}\n #{$!.message}"
113
- puts " at #{$!.backtrace.join("\n at ")}" if $DEBUG
114
- exit 1
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, nil, 'Display this help screen' do
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.sort {|a,b| a.name.to_s <=> b.name.to_s }.each do |param|
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
- default_description = help.delete('__default')
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
- puts 'Commands:'
191
- max_command_length = help.keys.max { |a, b| a.size <=> b.size }.size
192
- help.sort_by { |name, description| name }.each do |name, description|
193
- puts " #{name.ljust(max_command_length)} #{description}"
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] && !@commands.keys.include?(:__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.shift
303
- if command_arg.nil? || command_arg.start_with?('-')
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
@@ -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
@@ -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::InstanceMethods#flag
14
- # @see Application::InstanceMethods#global_flag
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
@@ -11,7 +11,8 @@ module Rubikon
11
11
  # arguments.
12
12
  #
13
13
  # @author Sebastian Staudt
14
- # @see Application::InstanceMethods#option
14
+ # @see Application::DSLMethods#option
15
+ # @see Application::DSLMethods#global_option
15
16
  # @see Parameter
16
17
  # @since 0.3.0
17
18
  class Option
@@ -11,6 +11,8 @@ module Rubikon
11
11
  #
12
12
  # @author Sebastian Staudt
13
13
  # @see Command
14
+ # @see Flag
15
+ # @see Option
14
16
  # @since 0.3.0
15
17
  module Parameter
16
18
 
@@ -9,7 +9,7 @@ module Rubikon
9
9
  # A class for displaying and managing progress bars
10
10
  #
11
11
  # @author Sebastian Staudt
12
- # @see Application::InstanceMethods#throbber
12
+ # @see Application::DSLMethods#progress_bar
13
13
  # @since 0.2.0
14
14
  class ProgressBar
15
15
 
@@ -8,7 +8,7 @@ module Rubikon
8
8
  # A class for displaying and managing throbbers
9
9
  #
10
10
  # @author Sebastian Staudt
11
- # @see Application::InstanceMethods#throbber
11
+ # @see Application::DSLMethods#throbber
12
12
  # @since 0.2.0
13
13
  class Throbber < Thread
14
14
 
data/lib/rubikon.rb CHANGED
@@ -24,6 +24,6 @@ require 'rubikon/application/base'
24
24
  module Rubikon
25
25
 
26
26
  # This is the current version of the Rubikon gem
27
- VERSION = '0.5.1'
27
+ VERSION = '0.5.2'
28
28
 
29
29
  end
@@ -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 Display this help screen\n input \n object_id \n parameters \n progressbar \n sandbox \n throbber \n/, @ostream.string
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: 9
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 5
9
- - 1
10
- version: 0.5.1
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-01 00:00:00 +01:00
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