rubikon 0.3.0 → 0.4.0
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/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
|