rubikon 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +12 -11
- data/Rakefile +4 -2
- data/lib/core_ext/object.rb +43 -0
- data/lib/core_ext/string.rb +8 -0
- data/lib/rubikon/application/base.rb +8 -9
- data/lib/rubikon/application/class_methods.rb +4 -2
- data/lib/rubikon/application/dsl_methods.rb +75 -62
- data/lib/rubikon/application/instance_methods.rb +106 -20
- data/lib/rubikon/application/sandbox.rb +70 -0
- data/lib/rubikon/command.rb +67 -23
- data/lib/rubikon/flag.rb +0 -8
- data/lib/rubikon/has_arguments.rb +182 -0
- data/lib/rubikon/option.rb +2 -9
- data/lib/rubikon/parameter.rb +16 -52
- data/lib/rubikon/progress_bar.rb +1 -1
- data/lib/rubikon.rb +11 -2
- data/samples/helloworld/hello_world.rb +69 -0
- data/test/{application_tests.rb → test_application.rb} +43 -5
- data/test/{command_tests.rb → test_command.rb} +19 -28
- data/test/{flag_tests.rb → test_flag.rb} +7 -5
- data/test/test_has_arguments.rb +99 -0
- data/test/test_helper.rb +1 -0
- data/test/test_option.rb +32 -0
- data/test/test_parameter.rb +21 -0
- data/test/{progress_bar_tests.rb → test_progress_bar.rb} +1 -1
- data/test/{throbber_tests.rb → test_throbber.rb} +3 -9
- data/test/testapps.rb +60 -1
- metadata +39 -17
- data/test/option_tests.rb +0 -75
data/README.md
CHANGED
@@ -28,7 +28,7 @@ Creating a Rubikon application is as simple as creating a Ruby class:
|
|
28
28
|
require 'rubygems'
|
29
29
|
require 'rubikon'
|
30
30
|
|
31
|
-
class MyApplication < Rubikon::Application
|
31
|
+
class MyApplication < Rubikon::Application::Base
|
32
32
|
end
|
33
33
|
|
34
34
|
If you save this code in a file called `myapp.rb` you can run it using
|
@@ -39,7 +39,7 @@ even more easily by typing `./myapp.rb`.
|
|
39
39
|
Now go on and define what your application should do when the user runs it.
|
40
40
|
This is done using `default`:
|
41
41
|
|
42
|
-
class MyApplication < Rubikon::Application
|
42
|
+
class MyApplication < Rubikon::Application::Base
|
43
43
|
|
44
44
|
default do
|
45
45
|
puts 'Hello World!'
|
@@ -49,9 +49,9 @@ This is done using `default`:
|
|
49
49
|
|
50
50
|
If you run this application it will just print `Hello World!`.
|
51
51
|
|
52
|
-
You can also add command-line options to your
|
52
|
+
You can also add command-line options to your application using `command`:
|
53
53
|
|
54
|
-
class MyApplication < Rubikon::Application
|
54
|
+
class MyApplication < Rubikon::Application::Base
|
55
55
|
|
56
56
|
command :hello do
|
57
57
|
puts 'Hello World!'
|
@@ -74,19 +74,18 @@ Flags and options are easily added to your application's commands using
|
|
74
74
|
Rubikon's DSL:
|
75
75
|
|
76
76
|
flag :more
|
77
|
-
option :name,
|
77
|
+
option :name, [:who]
|
78
78
|
command :hello do
|
79
|
-
|
79
|
+
puts "Hello #{who}"
|
80
80
|
end
|
81
81
|
|
82
|
-
|
83
82
|
Please see the `samples` directory for more in detail sample applications.
|
84
83
|
|
85
84
|
**Warning**:
|
86
85
|
|
87
86
|
Rubikon is still in an early development stage. If you want to use it be aware
|
88
|
-
that you will
|
89
|
-
|
87
|
+
that you will might run into problems and or restrictions. See the Contribute
|
88
|
+
section if you want to help to make Rubikon better.
|
90
89
|
|
91
90
|
## Features
|
92
91
|
|
@@ -132,8 +131,8 @@ You may also see Rubikon as a portmanteau word consisting of *"Ruby"* and
|
|
132
131
|
## License
|
133
132
|
|
134
133
|
This code is free software; you can redistribute it and/or modify it under the
|
135
|
-
terms of the new BSD License. A copy of this license can be found in the
|
136
|
-
file.
|
134
|
+
terms of the new BSD License. A copy of this license can be found in the
|
135
|
+
LICENSE file.
|
137
136
|
|
138
137
|
## Credits
|
139
138
|
|
@@ -146,6 +145,8 @@ file.
|
|
146
145
|
* [GitHub project page][1]
|
147
146
|
* [GitHub issue tracker][2]
|
148
147
|
|
148
|
+
Follow Rubikon on Twitter [@rubikonrb](http://twitter.com/rubikonrb).
|
149
|
+
|
149
150
|
[1]: http://github.com/koraktor/rubikon
|
150
151
|
[2]: http://github.com/koraktor/rubikon/issues
|
151
152
|
[3]: http://koraktor.github.com/rubikon
|
data/Rakefile
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
|
6
6
|
require 'rake/testtask'
|
7
7
|
|
8
|
+
samples_files = Dir.glob(File.join('samples', '**', '*.rb'))
|
8
9
|
src_files = Dir.glob(File.join('lib', '**', '*.rb'))
|
9
10
|
test_files = Dir.glob(File.join('test', '**', '*.rb'))
|
10
11
|
|
@@ -13,7 +14,7 @@ task :default => :test
|
|
13
14
|
# Test task
|
14
15
|
Rake::TestTask.new do |t|
|
15
16
|
t.libs << 'lib' << 'test'
|
16
|
-
t.pattern = 'test
|
17
|
+
t.pattern = 'test/**/test_*.rb'
|
17
18
|
t.verbose = true
|
18
19
|
end
|
19
20
|
|
@@ -31,13 +32,14 @@ begin
|
|
31
32
|
gem.email = 'koraktor@gmail.com'
|
32
33
|
gem.description = 'A simple to use, yet powerful Ruby framework for building console-based applications.'
|
33
34
|
gem.date = Time.now
|
34
|
-
gem.files = %w(README.md Rakefile LICENSE) + src_files + test_files
|
35
|
+
gem.files = %w(README.md Rakefile LICENSE) + samples_files + src_files + test_files
|
35
36
|
gem.has_rdoc = false
|
36
37
|
gem.homepage = 'http://koraktor.github.com/rubikon'
|
37
38
|
gem.name = gem.rubyforge_project = 'rubikon'
|
38
39
|
gem.summary = 'Rubikon - A Ruby console app framework'
|
39
40
|
|
40
41
|
gem.add_development_dependency('jeweler')
|
42
|
+
gem.add_development_dependency('shoulda')
|
41
43
|
gem.add_development_dependency('yard')
|
42
44
|
end
|
43
45
|
rescue LoadError
|
@@ -0,0 +1,43 @@
|
|
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 Object.method_defined?(:respond_to_missing?)
|
7
|
+
|
8
|
+
# Extends Ruby's own Object class with method #start_with? for Ruby < 1.9.2
|
9
|
+
#
|
10
|
+
# @author Sebastian Staudt
|
11
|
+
# @since 0.4.0
|
12
|
+
class Object
|
13
|
+
|
14
|
+
# Returns +true+ if _obj_ responds to the given method. Private methods
|
15
|
+
# are included in the search only if the optional second parameter
|
16
|
+
# evaluates to +true+.
|
17
|
+
#
|
18
|
+
# If the method is not implemented, as Process.fork on Windows,
|
19
|
+
# File.lchmod on GNU/Linux, etc., +false+ is returned.
|
20
|
+
#
|
21
|
+
# If the method is not defined, respond_to_missing? method is called and
|
22
|
+
# the result is returned.
|
23
|
+
#
|
24
|
+
# @see #respond_to_missing?
|
25
|
+
def respond_to?(symbol, include_private = false)
|
26
|
+
super || respond_to_missing?(symbol, include_private)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Hook method to return whether the _obj_ can respond to _id_ method or
|
30
|
+
# not.
|
31
|
+
#
|
32
|
+
# @param [Symbol] symbol The id of the method to check
|
33
|
+
# @return [Boolean] +true+ if this object responds to this method via
|
34
|
+
# via method_missing
|
35
|
+
# @see #method_missing
|
36
|
+
# @see #respond_to?
|
37
|
+
def respond_to_missing?(symbol, include_private = false)
|
38
|
+
false
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/lib/core_ext/string.rb
CHANGED
@@ -5,8 +5,16 @@
|
|
5
5
|
|
6
6
|
unless String.method_defined?(:start_with?)
|
7
7
|
|
8
|
+
# Extends Ruby's own String class with method #start_with? for Ruby < 1.8.7
|
9
|
+
#
|
10
|
+
# @author Sebastian Staudt
|
11
|
+
# @since 0.3.0
|
8
12
|
class String
|
9
13
|
|
14
|
+
# Returns true if this string starts with the given substring
|
15
|
+
#
|
16
|
+
# @param [String] start The substring to check
|
17
|
+
# @return [Boolean] +true+ if this String starts with the given substring
|
10
18
|
def start_with?(start)
|
11
19
|
!/^#{start}/.match(self).nil?
|
12
20
|
end
|
@@ -3,15 +3,17 @@
|
|
3
3
|
#
|
4
4
|
# Copyright (c) 2009-2010, Sebastian Staudt
|
5
5
|
|
6
|
-
require 'singleton'
|
7
|
-
require 'yaml'
|
8
|
-
|
9
6
|
require 'rubikon/application/class_methods'
|
10
7
|
require 'rubikon/application/dsl_methods'
|
11
8
|
require 'rubikon/application/instance_methods'
|
12
9
|
|
13
10
|
module Rubikon
|
14
11
|
|
12
|
+
# The Application module contains all basic functionality of a Rubikon
|
13
|
+
# application
|
14
|
+
#
|
15
|
+
# @author Sebastian Staudt
|
16
|
+
# @since 0.2.0
|
15
17
|
module Application
|
16
18
|
|
17
19
|
# The main class of Rubikon. Let your own application class inherit from
|
@@ -21,13 +23,10 @@ module Rubikon
|
|
21
23
|
# @since 0.2.0
|
22
24
|
class Base
|
23
25
|
|
24
|
-
|
25
|
-
include Rubikon::Application::ClassMethods
|
26
|
-
end
|
26
|
+
extend ClassMethods
|
27
27
|
|
28
|
-
include
|
29
|
-
include
|
30
|
-
include Singleton
|
28
|
+
include DSLMethods
|
29
|
+
include InstanceMethods
|
31
30
|
|
32
31
|
end
|
33
32
|
|
@@ -3,6 +3,8 @@
|
|
3
3
|
#
|
4
4
|
# Copyright (c) 2009-2010, Sebastian Staudt
|
5
5
|
|
6
|
+
require 'singleton'
|
7
|
+
|
6
8
|
module Rubikon
|
7
9
|
|
8
10
|
module Application
|
@@ -30,8 +32,8 @@ module Rubikon
|
|
30
32
|
# @param [Class] subclass The subclass inheriting from Application::Base.
|
31
33
|
# This is the user's application.
|
32
34
|
def inherited(subclass)
|
33
|
-
|
34
|
-
|
35
|
+
subclass.class_eval { include Singleton }
|
36
|
+
subclass.send(:base_file=, File.expand_path(caller.first.split(':').first))
|
35
37
|
at_exit { subclass.run if subclass.send(:autorun?) }
|
36
38
|
end
|
37
39
|
|
@@ -16,25 +16,13 @@ module Rubikon
|
|
16
16
|
# @since 0.3.0
|
17
17
|
module DSLMethods
|
18
18
|
|
19
|
-
|
19
|
+
# @return [String] The (first) definition file of the application
|
20
|
+
attr_reader :base_file
|
20
21
|
|
21
|
-
#
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
#
|
26
|
-
# @example
|
27
|
-
# command :something do
|
28
|
-
# puts arguments[0]
|
29
|
-
# end
|
30
|
-
def args
|
31
|
-
unless @current_command.nil?
|
32
|
-
@current_command.arguments
|
33
|
-
else
|
34
|
-
@current_global_option.arguments
|
35
|
-
end
|
36
|
-
end
|
37
|
-
alias_method :arguments, :args
|
22
|
+
# @return [String] The absolute path of the application
|
23
|
+
attr_reader :path
|
24
|
+
|
25
|
+
private
|
38
26
|
|
39
27
|
# Define a new application Command or an alias to an existing one
|
40
28
|
#
|
@@ -50,7 +38,7 @@ module Rubikon
|
|
50
38
|
#
|
51
39
|
# @return [Command]
|
52
40
|
# @since 0.2.0
|
53
|
-
def command(name, description = nil, &block)
|
41
|
+
def command(name, arg_count = nil, description = nil, &block)
|
54
42
|
if name.is_a? Hash
|
55
43
|
name.each do |alias_name, command_name|
|
56
44
|
command = @commands[command_name]
|
@@ -62,7 +50,7 @@ module Rubikon
|
|
62
50
|
end
|
63
51
|
end
|
64
52
|
else
|
65
|
-
command = Command.new(self, name, &block)
|
53
|
+
command = Command.new(self, name, arg_count, &block)
|
66
54
|
command.description = description unless description.nil?
|
67
55
|
@commands.each do |command_alias, command_name|
|
68
56
|
if command_name == command.name
|
@@ -75,7 +63,7 @@ module Rubikon
|
|
75
63
|
|
76
64
|
unless command.nil? || @parameters.empty?
|
77
65
|
@parameters.each do |parameter|
|
78
|
-
command
|
66
|
+
command.add_param(parameter)
|
79
67
|
end
|
80
68
|
@parameters.clear
|
81
69
|
end
|
@@ -131,7 +119,7 @@ module Rubikon
|
|
131
119
|
if name.is_a? Hash
|
132
120
|
@parameters << name
|
133
121
|
else
|
134
|
-
@parameters << Flag.new(name, &block)
|
122
|
+
@parameters << Flag.new(self, name, &block)
|
135
123
|
end
|
136
124
|
end
|
137
125
|
|
@@ -144,15 +132,16 @@ module Rubikon
|
|
144
132
|
# @example
|
145
133
|
# flag :status
|
146
134
|
# command :something do
|
147
|
-
# print_status if
|
135
|
+
# print_status if active? :status
|
148
136
|
# end
|
149
|
-
def
|
137
|
+
def active?(name)
|
150
138
|
name = name.to_sym
|
151
139
|
parameter = @global_parameters[name]
|
152
140
|
parameter = @current_command.parameters[name] if parameter.nil?
|
153
141
|
return false if parameter.nil?
|
154
142
|
parameter.active?
|
155
143
|
end
|
144
|
+
alias_method :given?, :active?
|
156
145
|
|
157
146
|
# Create a new flag with the given name to be used globally
|
158
147
|
#
|
@@ -184,7 +173,7 @@ module Rubikon
|
|
184
173
|
end
|
185
174
|
end
|
186
175
|
else
|
187
|
-
flag = Flag.new(name, &block)
|
176
|
+
flag = Flag.new(self, name, &block)
|
188
177
|
@global_parameters.each do |flag_alias, flag_name|
|
189
178
|
if flag_name == flag.name
|
190
179
|
@global_parameters[flag_alias] = flag
|
@@ -225,7 +214,7 @@ module Rubikon
|
|
225
214
|
end
|
226
215
|
end
|
227
216
|
else
|
228
|
-
option = Option.new(name, arg_count, &block)
|
217
|
+
option = Option.new(self, name, arg_count, &block)
|
229
218
|
@global_parameters.each do |option_alias, option_name|
|
230
219
|
if option_name == option.name
|
231
220
|
@global_parameters[option_alias] = option
|
@@ -243,7 +232,7 @@ module Rubikon
|
|
243
232
|
# @since 0.2.0
|
244
233
|
#
|
245
234
|
# @example Display a prompt "Please type something: "
|
246
|
-
#
|
235
|
+
# command 'interactive' do
|
247
236
|
# user_provided_value = input 'Please type something'
|
248
237
|
#
|
249
238
|
# # Do something with the data
|
@@ -280,7 +269,7 @@ module Rubikon
|
|
280
269
|
if name.is_a? Hash
|
281
270
|
@parameters << name
|
282
271
|
else
|
283
|
-
@parameters << Option.new(name.to_s, arg_count, &block)
|
272
|
+
@parameters << Option.new(self, name.to_s, arg_count, &block)
|
284
273
|
end
|
285
274
|
end
|
286
275
|
|
@@ -297,46 +286,44 @@ module Rubikon
|
|
297
286
|
@settings[:ostream]
|
298
287
|
end
|
299
288
|
|
300
|
-
#
|
301
|
-
#
|
302
|
-
#
|
303
|
-
# @
|
304
|
-
#
|
305
|
-
#
|
306
|
-
|
307
|
-
|
308
|
-
# command :something do
|
309
|
-
# puts parameters[:message].args[0] if given? :message
|
310
|
-
# end
|
311
|
-
def params
|
312
|
-
@current_command.parameters
|
289
|
+
# Defines a block of code used as a hook that should be executed after
|
290
|
+
# the command execution has finished
|
291
|
+
#
|
292
|
+
# @param [Proc] The code block to execute after the command execution has
|
293
|
+
# finished
|
294
|
+
# @since 0.4.0
|
295
|
+
def post_execute(&block)
|
296
|
+
@hooks[:post_execute] = block
|
313
297
|
end
|
314
|
-
alias_method :parameters, :params
|
315
298
|
|
316
|
-
#
|
317
|
-
#
|
318
|
-
#
|
319
|
-
# @
|
320
|
-
|
321
|
-
|
322
|
-
|
299
|
+
# Defines a block of code used as a hook that should be executed after
|
300
|
+
# the application has been initialized
|
301
|
+
#
|
302
|
+
# @param [Proc] The code block to execute after the application has been
|
303
|
+
# initialized
|
304
|
+
# @since 0.4.0
|
305
|
+
def post_init(&block)
|
306
|
+
@hooks[:post_init] = block
|
323
307
|
end
|
324
308
|
|
325
|
-
#
|
326
|
-
#
|
327
|
-
#
|
328
|
-
#
|
329
|
-
#
|
330
|
-
|
331
|
-
|
309
|
+
# Defines a block of code used as a hook that should be executed before
|
310
|
+
# the command has been started
|
311
|
+
#
|
312
|
+
# @param [Proc] The code block to execute before the command has been
|
313
|
+
# started
|
314
|
+
# @since 0.4.0
|
315
|
+
def pre_execute(&block)
|
316
|
+
@hooks[:pre_execute] = block
|
332
317
|
end
|
333
318
|
|
334
|
-
#
|
335
|
-
#
|
336
|
-
#
|
337
|
-
# @
|
338
|
-
|
339
|
-
|
319
|
+
# Defines a block of code used as a hook that should be executed before
|
320
|
+
# the application has been initialized
|
321
|
+
#
|
322
|
+
# @param [Proc] The code block to execute before the application has been
|
323
|
+
# initialized
|
324
|
+
# @since 0.4.0
|
325
|
+
def pre_init(&block)
|
326
|
+
@hooks[:pre_init] = block
|
340
327
|
end
|
341
328
|
|
342
329
|
# Displays a progress bar while the given block is executed
|
@@ -373,6 +360,32 @@ module Rubikon
|
|
373
360
|
end
|
374
361
|
end
|
375
362
|
|
363
|
+
# Output text using +IO#<<+ of the output stream
|
364
|
+
#
|
365
|
+
# @param [String] text The text to write into the output stream
|
366
|
+
# @since 0.2.0
|
367
|
+
def put(text)
|
368
|
+
@settings[:ostream] << text
|
369
|
+
@settings[:ostream].flush
|
370
|
+
end
|
371
|
+
|
372
|
+
# Output a character using +IO#putc+ of the output stream
|
373
|
+
#
|
374
|
+
# @param [String, Numeric] char The character to write into the output
|
375
|
+
# stream
|
376
|
+
# @since 0.2.0
|
377
|
+
def putc(char)
|
378
|
+
@settings[:ostream].putc char
|
379
|
+
end
|
380
|
+
|
381
|
+
# Output a line of text using +IO#puts+ of the output stream
|
382
|
+
#
|
383
|
+
# @param [String] text The text to write into the output stream
|
384
|
+
# @since 0.2.0
|
385
|
+
def puts(text)
|
386
|
+
@settings[:ostream].puts text
|
387
|
+
end
|
388
|
+
|
376
389
|
# Sets an application setting
|
377
390
|
#
|
378
391
|
# @param [Symbol, #to_sym] setting The name of the setting to change
|
@@ -3,6 +3,9 @@
|
|
3
3
|
#
|
4
4
|
# Copyright (c) 2009-2010, Sebastian Staudt
|
5
5
|
|
6
|
+
require 'pathname'
|
7
|
+
|
8
|
+
require 'rubikon/application/sandbox'
|
6
9
|
require 'rubikon/command'
|
7
10
|
require 'rubikon/exceptions'
|
8
11
|
require 'rubikon/flag'
|
@@ -22,8 +25,11 @@ module Rubikon
|
|
22
25
|
# @since 0.2.0
|
23
26
|
module InstanceMethods
|
24
27
|
|
25
|
-
# @return [
|
26
|
-
|
28
|
+
# @return [Parameter] The parameter that's currently executed
|
29
|
+
attr_accessor :current_param
|
30
|
+
|
31
|
+
# @return [Application::Sandbox] The sandbox this application runs in
|
32
|
+
attr_reader :sandbox
|
27
33
|
|
28
34
|
# Initialize with default settings
|
29
35
|
#
|
@@ -32,17 +38,18 @@ module Rubikon
|
|
32
38
|
#
|
33
39
|
# @see #set
|
34
40
|
def initialize
|
35
|
-
@commands
|
36
|
-
@current_command
|
37
|
-
@
|
38
|
-
@
|
39
|
-
@
|
40
|
-
@
|
41
|
-
@
|
42
|
-
@
|
41
|
+
@commands = {}
|
42
|
+
@current_command = nil
|
43
|
+
@current_global_param = nil
|
44
|
+
@current_param = nil
|
45
|
+
@global_parameters = {}
|
46
|
+
@hooks = {}
|
47
|
+
@initialized = false
|
48
|
+
@parameters = []
|
49
|
+
@sandbox = Sandbox.new(self)
|
50
|
+
@settings = {
|
43
51
|
:autorun => true,
|
44
52
|
:help_as_default => true,
|
45
|
-
:help_banner => "Usage: #{$0}",
|
46
53
|
:istream => $stdin,
|
47
54
|
:name => self.class.to_s,
|
48
55
|
:ostream => $stdout,
|
@@ -61,22 +68,25 @@ module Rubikon
|
|
61
68
|
# given to the application as options
|
62
69
|
def run(args = ARGV)
|
63
70
|
begin
|
64
|
-
init
|
65
|
-
|
71
|
+
init
|
66
72
|
command, parameters, args = parse_arguments(args)
|
67
73
|
|
68
74
|
parameters.each do |parameter|
|
75
|
+
@current_global_param = parameter
|
69
76
|
if parameter.is_a? Option
|
70
77
|
parameter.check_args
|
71
|
-
@current_global_option = parameter
|
72
78
|
end
|
73
79
|
parameter.active!
|
74
|
-
@
|
80
|
+
@current_global_param = nil
|
75
81
|
end
|
76
82
|
|
77
83
|
@current_command = command
|
84
|
+
hook :pre_execute
|
78
85
|
result = command.run(*args)
|
86
|
+
hook :post_execute
|
79
87
|
@current_command = nil
|
88
|
+
|
89
|
+
reset
|
80
90
|
result
|
81
91
|
rescue
|
82
92
|
raise $! if @settings[:raise_errors]
|
@@ -89,6 +99,22 @@ module Rubikon
|
|
89
99
|
|
90
100
|
private
|
91
101
|
|
102
|
+
# Sets the (first) file this application has been defined in.
|
103
|
+
#
|
104
|
+
# This also sets the path of the application used to load external
|
105
|
+
# command code and the default banner for the help screen.
|
106
|
+
#
|
107
|
+
# @param [String] file The (first) file of the class definition
|
108
|
+
# @see DSLMethods#base_file
|
109
|
+
# @see DSLMethods#path
|
110
|
+
# @since 0.4.0
|
111
|
+
def base_file=(file)
|
112
|
+
@base_file = file
|
113
|
+
@path = File.dirname(file)
|
114
|
+
|
115
|
+
@settings[:help_banner] ||= "Usage: #{Pathname.new(file).relative_path_from(Pathname.new(Dir.getwd))}"
|
116
|
+
end
|
117
|
+
|
92
118
|
# Defines a global Flag for enabling debug output
|
93
119
|
#
|
94
120
|
# This will define a Flag <tt>--debug</tt> (with alias <tt>-d</tt>) to
|
@@ -108,16 +134,20 @@ module Rubikon
|
|
108
134
|
# This takes any defined commands and it's corresponding options and
|
109
135
|
# descriptions and displays them in a user-friendly manner.
|
110
136
|
def help_command
|
111
|
-
|
112
|
-
|
137
|
+
commands = @commands
|
138
|
+
global_parameters = @global_parameters
|
139
|
+
settings = @settings
|
140
|
+
|
141
|
+
command :help, nil, 'Display this help screen' do
|
142
|
+
put settings[:help_banner]
|
113
143
|
|
114
144
|
help = {}
|
115
|
-
|
145
|
+
commands.each_value do |command|
|
116
146
|
help[command.name.to_s] = command.description
|
117
147
|
end
|
118
148
|
|
119
149
|
global_params = ''
|
120
|
-
|
150
|
+
global_parameters.values.uniq.sort {|a,b| a.name.to_s <=> b.name.to_s }.each do |param|
|
121
151
|
global_params << ' ['
|
122
152
|
([param.name] + param.aliases).each_with_index do |name, index|
|
123
153
|
name = name.to_s
|
@@ -137,7 +167,7 @@ module Rubikon
|
|
137
167
|
puts "Without command: #{default_description}\n\n"
|
138
168
|
end
|
139
169
|
|
140
|
-
puts
|
170
|
+
puts 'Commands:'
|
141
171
|
max_command_length = help.keys.max { |a, b| a.size <=> b.size }.size
|
142
172
|
help.sort_by { |name, description| name }.each do |name, description|
|
143
173
|
puts " #{name.ljust(max_command_length)} #{description}"
|
@@ -163,11 +193,27 @@ module Rubikon
|
|
163
193
|
@settings[:ostream] = current_ostream
|
164
194
|
end
|
165
195
|
|
196
|
+
# Executes the hook with the secified name
|
197
|
+
#
|
198
|
+
# @param [Symbol] name The name of the hook to execute
|
199
|
+
# @since 0.4.0
|
200
|
+
def hook(name)
|
201
|
+
@sandbox.instance_eval &@hooks[name] unless @hooks[name].nil?
|
202
|
+
end
|
203
|
+
|
166
204
|
# This method is called once for each application and is used to
|
167
205
|
# initialize anything that needs to be ready before the application is
|
168
206
|
# run, but <em>after</em> the application is setup, i.e. after the user
|
169
207
|
# has defined the application class.
|
170
208
|
def init
|
209
|
+
return if @initialized
|
210
|
+
|
211
|
+
@current_command = nil
|
212
|
+
@current_param = nil
|
213
|
+
@current_global_param = nil
|
214
|
+
|
215
|
+
hook :pre_init
|
216
|
+
|
171
217
|
debug_flag
|
172
218
|
help_command
|
173
219
|
verbose_flag
|
@@ -177,6 +223,34 @@ module Rubikon
|
|
177
223
|
end
|
178
224
|
|
179
225
|
@initialized = true
|
226
|
+
|
227
|
+
hook :post_init
|
228
|
+
end
|
229
|
+
|
230
|
+
# This is used to determine the receiver of a method call inside the
|
231
|
+
# application code.
|
232
|
+
#
|
233
|
+
# This is used to have a convenient way to access e.g. paramter
|
234
|
+
# arguments.
|
235
|
+
#
|
236
|
+
# This will delegate a method call to the currently executed parameter
|
237
|
+
# if the receiving object exists and responds to the desired method.
|
238
|
+
# Currently executed means the application's execution is inside a
|
239
|
+
# parameter's code block at the moment, i.e. a call to a missing method
|
240
|
+
# inside a parameter's code block will trigger this behavior.
|
241
|
+
#
|
242
|
+
# @example Access a command's arguments
|
243
|
+
# command :args, [:one, :two] do
|
244
|
+
# puts "One: #{one}, Two: #{two}"
|
245
|
+
# end
|
246
|
+
# @since 0.4.0
|
247
|
+
def method_missing(name, *args, &block)
|
248
|
+
receiver = @current_param || @current_global_param || @current_command
|
249
|
+
if receiver.nil? || !receiver.respond_to?(name)
|
250
|
+
super
|
251
|
+
else
|
252
|
+
receiver.send(name, *args, &block)
|
253
|
+
end
|
180
254
|
end
|
181
255
|
|
182
256
|
# Parses the command-line arguments given to the application by the
|
@@ -223,6 +297,18 @@ module Rubikon
|
|
223
297
|
return command, parameters, args
|
224
298
|
end
|
225
299
|
|
300
|
+
# Resets this application to its initial state
|
301
|
+
#
|
302
|
+
# @see Command#reset
|
303
|
+
# @see HasArguments#reset
|
304
|
+
# @see Parameter#reset
|
305
|
+
# @since 0.4.0
|
306
|
+
def reset
|
307
|
+
(@commands.values + @global_parameters.values).uniq.each do |param|
|
308
|
+
param.reset
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
226
312
|
# Defines a global Flag for enabling verbose output
|
227
313
|
#
|
228
314
|
# This will define a Flag <tt>--verbose</tt> and <tt>-v</tt> to enable
|