acclaim 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +2 -43
- data/acclaim.gemspec +1 -0
- data/lib/acclaim/command.rb +37 -26
- data/lib/acclaim/option.rb +15 -6
- data/lib/acclaim/option/parser.rb +47 -29
- data/lib/acclaim/option/type.rb +55 -0
- data/lib/acclaim/option/type/date.rb +21 -0
- data/lib/acclaim/option/type/date_time.rb +21 -0
- data/lib/acclaim/option/type/string.rb +21 -0
- data/lib/acclaim/option/type/time.rb +21 -0
- data/lib/acclaim/option/type/uri.rb +21 -0
- data/lib/acclaim/version.rb +1 -1
- metadata +21 -4
data/Rakefile
CHANGED
@@ -1,44 +1,3 @@
|
|
1
|
-
|
2
|
-
gem_dir = File.join this_dir, 'gem'
|
3
|
-
spec_file = File.join this_dir, 'acclaim.gemspec'
|
1
|
+
require 'rookie'
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
task :mkdir do
|
8
|
-
FileUtils.mkdir_p gem_dir
|
9
|
-
end
|
10
|
-
|
11
|
-
task :gem => :mkdir do
|
12
|
-
gem_file = File.join this_dir, Gem::Builder.new(spec).build
|
13
|
-
FileUtils.mv gem_file, gem_dir
|
14
|
-
end
|
15
|
-
|
16
|
-
namespace :gem do
|
17
|
-
|
18
|
-
task :build => :gem
|
19
|
-
|
20
|
-
gem_file = File.join gem_dir, "#{spec.name}-#{spec.version}.gem"
|
21
|
-
|
22
|
-
task :push => :gem do
|
23
|
-
sh "gem push #{gem_file}"
|
24
|
-
end
|
25
|
-
|
26
|
-
task :install => :gem do
|
27
|
-
sh "gem install #{gem_file}"
|
28
|
-
end
|
29
|
-
|
30
|
-
task :uninstall do
|
31
|
-
sh "gem uninstall #{spec.name}"
|
32
|
-
end
|
33
|
-
|
34
|
-
task :clean do
|
35
|
-
FileUtils.rm_rf gem_dir
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
task :clean => 'gem:clean'
|
41
|
-
|
42
|
-
task :setup => [ 'gem:install', :clean ]
|
43
|
-
|
44
|
-
task :default => :setup
|
3
|
+
Rookie::Tasks.new 'acclaim.gemspec'
|
data/acclaim.gemspec
CHANGED
data/lib/acclaim/command.rb
CHANGED
@@ -64,25 +64,27 @@ module Acclaim
|
|
64
64
|
end
|
65
65
|
|
66
66
|
# Adds an option to this command.
|
67
|
-
def option(*args)
|
68
|
-
options << Option.new(*args)
|
67
|
+
def option(*args, &block)
|
68
|
+
options << Option.new(*args, &block)
|
69
69
|
end
|
70
70
|
|
71
71
|
alias :opt :option
|
72
72
|
|
73
73
|
# The block which is executed when this command is called. It is given 2
|
74
|
-
# parameters; the first is an
|
75
|
-
# settings information; the second is the remaining command line.
|
74
|
+
# parameters; the first is an Option::Values instance which can be queried
|
75
|
+
# for settings information; the second is the remaining command line.
|
76
76
|
def action(&block)
|
77
77
|
@action = block
|
78
78
|
end
|
79
79
|
|
80
80
|
alias :when_called :action
|
81
81
|
|
82
|
+
# Adds help subcommand and options to this command.
|
82
83
|
def help(opts = {})
|
83
84
|
subcommands << Help.create(self, opts)
|
84
85
|
end
|
85
86
|
|
87
|
+
# Adds help subcommand and options to this command.
|
86
88
|
def version(version_string, opts = {})
|
87
89
|
subcommands << Version.create(self, version_string, opts)
|
88
90
|
end
|
@@ -92,50 +94,43 @@ module Acclaim
|
|
92
94
|
Option::Parser.new(args, options).parse!
|
93
95
|
end
|
94
96
|
|
95
|
-
# Invokes this command with a fresh set of
|
97
|
+
# Invokes this command with a fresh set of option values.
|
96
98
|
def run(*args)
|
97
99
|
invoke Option::Values.new, args
|
98
100
|
rescue Option::Parser::Error => e
|
99
101
|
puts e.message
|
100
102
|
end
|
101
103
|
|
102
|
-
# Parses the argument array.
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
104
|
+
# Parses the argument array. The argument array will be searched for
|
105
|
+
# subcommands; if one is found, it will be invoked, if not, this command
|
106
|
+
# will be executed. A subcommand may be anywhere in the array as long as
|
107
|
+
# it is before an argument separator, which is tipically a double dash
|
108
|
+
# (<tt>--<\tt>) and may be omitted.
|
106
109
|
def invoke(opts, args = [])
|
107
110
|
opts.merge! parse_options!(args)
|
108
111
|
handle_special_options! opts, args
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
index = args.index subcommand.line
|
115
|
-
# If we have the subcommand AND the separator, then we have it if the
|
116
|
-
# subcommand is before the separator.
|
117
|
-
index and (not separator_index or index < separator_index)
|
118
|
-
end.tap do |subcommand|
|
119
|
-
if subcommand
|
120
|
-
args.delete subcommand.line
|
121
|
-
subcommand.invoke(opts, args)
|
122
|
-
else
|
123
|
-
execute(opts, args)
|
124
|
-
end
|
112
|
+
if subcommand = find_subcommand_in(separated args)
|
113
|
+
args.delete subcommand.line
|
114
|
+
subcommand.invoke(opts, args)
|
115
|
+
else
|
116
|
+
execute(opts, args)
|
125
117
|
end
|
126
118
|
end
|
127
119
|
|
128
|
-
# Calls this command's action block with the given
|
120
|
+
# Calls this command's action block with the given option values and
|
121
|
+
# arguments.
|
129
122
|
def execute(opts, args)
|
130
123
|
@action.call opts, args
|
131
124
|
end
|
132
125
|
|
133
126
|
alias :call :execute
|
134
127
|
|
128
|
+
# True if this is a top-level command.
|
135
129
|
def root?
|
136
130
|
superclass == Acclaim::Command
|
137
131
|
end
|
138
132
|
|
133
|
+
# Finds the root of the command hierarchy.
|
139
134
|
def root
|
140
135
|
command = self
|
141
136
|
command = command.superclass until command.root?
|
@@ -150,6 +145,22 @@ module Acclaim
|
|
150
145
|
const_get(:Version).execute opts, args if opts.acclaim_version?
|
151
146
|
end
|
152
147
|
|
148
|
+
# Attempts to find a subcommand of this command in the given argument
|
149
|
+
# array. If a subcommand is found, it is returned, if not, nil is
|
150
|
+
# returned.
|
151
|
+
def find_subcommand_in(args)
|
152
|
+
subcommands.find do |subcommand|
|
153
|
+
args.include? subcommand.line
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Finds the argument separator and returns an array containing all the
|
158
|
+
# elements before it. If a separator is not present, the original array
|
159
|
+
# is returned.
|
160
|
+
def separated(args)
|
161
|
+
args.take_while { |arg| arg !~ Option::Parser::Regexp::ARGUMENT_SEPARATOR }
|
162
|
+
end
|
163
|
+
|
153
164
|
end
|
154
165
|
|
155
166
|
# Add the class methods to the subclass and add it to this command's list of
|
data/lib/acclaim/option.rb
CHANGED
@@ -1,23 +1,32 @@
|
|
1
1
|
require 'acclaim/option/arity'
|
2
2
|
require 'acclaim/option/parser/regexp'
|
3
|
+
require 'acclaim/option/type'
|
3
4
|
|
4
5
|
module Acclaim
|
5
6
|
|
6
7
|
# Represents a command-line option.
|
7
8
|
class Option
|
8
9
|
|
9
|
-
attr_accessor :key, :names, :description, :type, :default
|
10
|
+
attr_accessor :key, :names, :description, :type, :default, :handler
|
10
11
|
|
11
|
-
def initialize(key, *args)
|
12
|
+
def initialize(key, *args, &block)
|
12
13
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
14
|
+
matches = args.select { |arg| arg.is_a? String }.group_by do |arg|
|
15
|
+
arg =~ Parser::Regexp::SWITCH ? true : false
|
16
|
+
end
|
17
|
+
klass = args.find { |arg| arg.is_a? Class }
|
13
18
|
self.key = key
|
14
|
-
self.names =
|
15
|
-
self.description =
|
16
|
-
self.type = args.find { |arg| arg.is_a? Class }
|
19
|
+
self.names = matches.fetch true, []
|
20
|
+
self.description = matches.fetch(false, []).first
|
17
21
|
self.arity = options[:arity]
|
18
22
|
self.default = options[:default]
|
19
23
|
self.required = options[:required]
|
20
|
-
|
24
|
+
self.type = klass || String
|
25
|
+
self.handler = block
|
26
|
+
end
|
27
|
+
|
28
|
+
def convert_parameters(*args)
|
29
|
+
args.map { |arg| Type[type].call arg }
|
21
30
|
end
|
22
31
|
|
23
32
|
def =~(str)
|
@@ -73,39 +73,19 @@ module Acclaim
|
|
73
73
|
def parse_values!
|
74
74
|
Values.new.tap do |options_instance|
|
75
75
|
options.each do |option|
|
76
|
-
key = option.key
|
77
|
-
options_instance[key] = option.default
|
78
|
-
|
79
|
-
if
|
76
|
+
key = option.key
|
77
|
+
options_instance[key] = option.default unless options_instance[key]
|
78
|
+
switches = argv.find_all { |switch| option =~ switch }
|
79
|
+
if switches.any?
|
80
80
|
if option.flag?
|
81
|
-
|
81
|
+
set_option_value option, options_instance
|
82
82
|
else
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
arg_index + arity.total
|
88
|
-
else
|
89
|
-
argv.length - 1
|
90
|
-
end
|
91
|
-
params = argv[arg_index + 1, len]
|
92
|
-
values = []
|
93
|
-
params.each do |param|
|
94
|
-
case param
|
95
|
-
when nil, SWITCH, ARGUMENT_SEPARATOR then break
|
96
|
-
else
|
97
|
-
break if arity.bound? and values.count >= arity.total
|
98
|
-
values << param
|
99
|
-
end
|
100
|
-
end
|
101
|
-
count = values.count
|
102
|
-
Error.raise_wrong_arg_number count, *option.arity if count < arity.required
|
103
|
-
value = if arity.total == 1 then values.first else values end
|
104
|
-
options_instance[key] = value unless values.empty?
|
105
|
-
values.each { |value| argv.delete value }
|
83
|
+
switches.each do |switch|
|
84
|
+
params = extract_parameters_of! option, switch
|
85
|
+
argv.delete switch
|
86
|
+
set_option_value option, options_instance, params
|
106
87
|
end
|
107
88
|
end
|
108
|
-
args.each { |arg| argv.delete arg }
|
109
89
|
else
|
110
90
|
Error.raise_missing_arg(option.names.join ' | ') if option.required?
|
111
91
|
end
|
@@ -113,6 +93,44 @@ module Acclaim
|
|
113
93
|
end
|
114
94
|
end
|
115
95
|
|
96
|
+
def extract_parameters_of!(option, switch)
|
97
|
+
arity = option.arity
|
98
|
+
switch_index = argv.index switch
|
99
|
+
len = if arity.bound?
|
100
|
+
switch_index + arity.total
|
101
|
+
else
|
102
|
+
argv.length - 1
|
103
|
+
end
|
104
|
+
params = argv[switch_index + 1, len]
|
105
|
+
values = []
|
106
|
+
params.each do |param|
|
107
|
+
case param
|
108
|
+
when nil, SWITCH, ARGUMENT_SEPARATOR then break
|
109
|
+
else
|
110
|
+
break if arity.bound? and values.count >= arity.total
|
111
|
+
values << param
|
112
|
+
end
|
113
|
+
end
|
114
|
+
count = values.count
|
115
|
+
Error.raise_wrong_arg_number count, *arity if count < arity.required
|
116
|
+
values.each { |value| argv.delete value }
|
117
|
+
end
|
118
|
+
|
119
|
+
def set_option_value(option, values, params = [])
|
120
|
+
params = option.convert_parameters *params
|
121
|
+
if handler = option.handler
|
122
|
+
if option.flag? then handler.call values
|
123
|
+
else handler.call values, params end
|
124
|
+
else
|
125
|
+
key = option.key.to_sym
|
126
|
+
if option.flag? then values[key] = true
|
127
|
+
else
|
128
|
+
value = option.arity.total == 1 ? params.first : params
|
129
|
+
values[key] = value unless params.empty?
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
116
134
|
end
|
117
135
|
end
|
118
136
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Acclaim
|
2
|
+
class Option
|
3
|
+
|
4
|
+
# Associates a class with a handler block.
|
5
|
+
module Type
|
6
|
+
|
7
|
+
instance_eval do
|
8
|
+
|
9
|
+
# Yields class, proc pairs if a block was given. Returns an enumerator
|
10
|
+
# otherwise.
|
11
|
+
def each(&block)
|
12
|
+
table.each &block
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns all registered classes.
|
16
|
+
def all
|
17
|
+
table.keys
|
18
|
+
end
|
19
|
+
|
20
|
+
alias registered all
|
21
|
+
|
22
|
+
# Registers a handler for a class.
|
23
|
+
def register(klass, &block)
|
24
|
+
table[klass] = block
|
25
|
+
end
|
26
|
+
|
27
|
+
alias add_handler_for register
|
28
|
+
alias accept register
|
29
|
+
|
30
|
+
# Returns the handler for the given class.
|
31
|
+
def handler_for(klass)
|
32
|
+
table[klass]
|
33
|
+
end
|
34
|
+
|
35
|
+
alias [] handler_for
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# The hash used to associate classes with their handlers.
|
40
|
+
def table
|
41
|
+
@table ||= {}
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
require 'acclaim/option/type/date'
|
52
|
+
require 'acclaim/option/type/date_time'
|
53
|
+
require 'acclaim/option/type/string'
|
54
|
+
require 'acclaim/option/type/time'
|
55
|
+
require 'acclaim/option/type/uri'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'acclaim/option/type'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module Acclaim
|
5
|
+
class Option
|
6
|
+
module Type
|
7
|
+
|
8
|
+
# Handles dates given as arguments in the command line.
|
9
|
+
module Date
|
10
|
+
|
11
|
+
def self.handle(str)
|
12
|
+
::Date.parse str
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
self.accept ::Date, &Date.method(:handle)
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'acclaim/option/type'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module Acclaim
|
5
|
+
class Option
|
6
|
+
module Type
|
7
|
+
|
8
|
+
# Handles dates and times given as arguments in the command line.
|
9
|
+
module DateTime
|
10
|
+
|
11
|
+
def self.handle(str)
|
12
|
+
::DateTime.parse str
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
self.accept ::DateTime, &DateTime.method(:handle)
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'acclaim/option/type'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
module Acclaim
|
5
|
+
class Option
|
6
|
+
module Type
|
7
|
+
|
8
|
+
# Handles strings given as arguments in the command line.
|
9
|
+
module String
|
10
|
+
|
11
|
+
def self.handle(str)
|
12
|
+
str.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
self.accept ::String, &String.method(:handle)
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'acclaim/option/type'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
module Acclaim
|
5
|
+
class Option
|
6
|
+
module Type
|
7
|
+
|
8
|
+
# Handles times given as arguments in the command line.
|
9
|
+
module Time
|
10
|
+
|
11
|
+
def self.handle(str)
|
12
|
+
::Time.parse str
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
self.accept ::Time, &Time.method(:handle)
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'acclaim/option/type'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Acclaim
|
5
|
+
class Option
|
6
|
+
module Type
|
7
|
+
|
8
|
+
# Handles URIs given as arguments in the command line.
|
9
|
+
module URI
|
10
|
+
|
11
|
+
def self.handle(str)
|
12
|
+
::URI.parse str
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
self.accept ::URI, &URI.method(:handle)
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/acclaim/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acclaim
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-12-
|
12
|
+
date: 2011-12-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &13170100 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,18 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *13170100
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rookie
|
27
|
+
requirement: &13169620 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *13169620
|
25
36
|
description: Command-line option parser and command interface.
|
26
37
|
email: matheus.a.m.moreira@gmail.com
|
27
38
|
executables: []
|
@@ -43,6 +54,12 @@ files:
|
|
43
54
|
- lib/acclaim/option/arity.rb
|
44
55
|
- lib/acclaim/option/parser.rb
|
45
56
|
- lib/acclaim/option/parser/regexp.rb
|
57
|
+
- lib/acclaim/option/type.rb
|
58
|
+
- lib/acclaim/option/type/date.rb
|
59
|
+
- lib/acclaim/option/type/date_time.rb
|
60
|
+
- lib/acclaim/option/type/string.rb
|
61
|
+
- lib/acclaim/option/type/time.rb
|
62
|
+
- lib/acclaim/option/type/uri.rb
|
46
63
|
- lib/acclaim/option/values.rb
|
47
64
|
- lib/acclaim/version.rb
|
48
65
|
- spec/acclaim/option/arity_spec.rb
|