acclaim 0.0.7 → 0.1.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.markdown +43 -35
- data/lib/acclaim/command.rb +4 -0
- data/lib/acclaim/command/parser.rb +6 -2
- data/lib/acclaim/option.rb +72 -16
- data/lib/acclaim/option/arity.rb +13 -1
- data/lib/acclaim/option/parser.rb +5 -1
- data/lib/acclaim/option/type.rb +39 -24
- data/lib/acclaim/version.rb +2 -2
- metadata +10 -10
data/README.markdown
CHANGED
@@ -12,7 +12,7 @@ application in a structured manner. Commands are classes that inherit from
|
|
12
12
|
|
13
13
|
module App
|
14
14
|
class Command < Acclaim::Command
|
15
|
-
option :verbose, '-
|
15
|
+
option :verbose, '-V', '--verbose'
|
16
16
|
|
17
17
|
when_called do |options, args|
|
18
18
|
puts 'Hello World!'
|
@@ -21,17 +21,19 @@ application in a structured manner. Commands are classes that inherit from
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
App::Command.run *ARGV
|
25
|
+
|
24
26
|
$ app --verbose a b c
|
25
27
|
Hello World!
|
26
28
|
a, b, c
|
27
29
|
|
28
|
-
Every command has a set of options and block
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
Every command has a set of options and block. When the application runs, the
|
31
|
+
options are parsed into an object and passed to the command's block along with
|
32
|
+
the remaining command line arguments. The first argument of the `option` method
|
33
|
+
is the key used to store the value of the option, the other strings are either
|
34
|
+
switches or a description:
|
33
35
|
|
34
|
-
option :verbose, '-
|
36
|
+
option :verbose, '-V', '--verbose', '--run-verbosely', 'Run verbosely.'
|
35
37
|
|
36
38
|
Acclaim provides especial `help` and `version` commands that may be added to
|
37
39
|
your program. The help command will automatically generate and print a help page
|
@@ -56,10 +58,9 @@ version and exit. To use them:
|
|
56
58
|
$ app version
|
57
59
|
1.2.3
|
58
60
|
|
59
|
-
Both methods can take a hash as the last parameter
|
60
|
-
|
61
|
-
|
62
|
-
like:
|
61
|
+
Both methods can take a hash as the last parameter. If you don't want the
|
62
|
+
options, or if you want to specify a different set of switches or a different
|
63
|
+
description, you can write:
|
63
64
|
|
64
65
|
help options: false
|
65
66
|
version '1.2.3', switches: %w(--version),
|
@@ -82,21 +83,19 @@ from an existing command:
|
|
82
83
|
end
|
83
84
|
end
|
84
85
|
|
85
|
-
$ app do x y
|
86
|
-
Doing something with x y, z
|
86
|
+
$ app do x y z
|
87
|
+
Doing something with x, y, z
|
87
88
|
|
88
|
-
$ app do --what x y
|
89
|
+
$ app do --what x y z
|
89
90
|
Doing x with y, z
|
90
91
|
|
91
|
-
Options may also take an
|
92
|
+
Options may also take an hash as the last parameter. Among the things that can
|
92
93
|
be configured is the default value for the option and its arity. The default
|
93
94
|
value is `nil` by default and is used if the option is not given. The arity of
|
94
95
|
the option represents the minimum number of arguments it __must__ take and the
|
95
|
-
number of optional arguments it __may__ take. It
|
96
|
-
form `[minimum, optional]`. Options that take zero arguments, which is the
|
97
|
-
default, are
|
98
|
-
|
99
|
-
So, options can take from zero to an unlimited number of arguments, right?
|
96
|
+
number of optional arguments it __may__ take. It can be specified as an array in
|
97
|
+
the form `[minimum, optional]`. Options that take zero arguments, which is the
|
98
|
+
default, are called switches.
|
100
99
|
|
101
100
|
class App::Command::Do < App::Command
|
102
101
|
|
@@ -107,6 +106,7 @@ So, options can take from zero to an unlimited number of arguments, right?
|
|
107
106
|
what = (options.what.join ', ' rescue options.what)
|
108
107
|
subjects = args.join ', '
|
109
108
|
puts "Doing #{what} with #{subjects}"
|
109
|
+
end
|
110
110
|
end
|
111
111
|
|
112
112
|
$ app do --what x y z
|
@@ -132,9 +132,8 @@ will not work:
|
|
132
132
|
$ app do --what w x --verbose y z
|
133
133
|
Doing w, x, y, z with
|
134
134
|
|
135
|
-
This happens because `--verbose` is an option of the main command.
|
136
|
-
|
137
|
-
be parsing the `%w(--what w x y z)` array.
|
135
|
+
This happens because `--verbose` is an option of the main command. When `do`
|
136
|
+
gets its turn it will be parsing the `%w(--what w x y z)` array.
|
138
137
|
|
139
138
|
### Option Type Handlers
|
140
139
|
|
@@ -142,8 +141,7 @@ Arguments given to options are by default strings. To make life easier, you may
|
|
142
141
|
specify the type of the arguments by passing a class among the arguments:
|
143
142
|
|
144
143
|
class App::Command::Do
|
145
|
-
opt :when, '--when', 'When to do it.', Date,
|
146
|
-
default: Date.today, arity: [1,0]
|
144
|
+
opt :when, '--when', 'When to do it.', Date, default: Date.today, arity: [1,0]
|
147
145
|
|
148
146
|
action do |options, args|
|
149
147
|
what = (options.what.join ', ' rescue options.what)
|
@@ -159,23 +157,33 @@ specify the type of the arguments by passing a class among the arguments:
|
|
159
157
|
Merry Christmas!
|
160
158
|
Doing w, x with y, z on 12/25/2011
|
161
159
|
|
162
|
-
There are type handlers included for `Date`s, `Time`s, `DateTime`s, `URI`s
|
163
|
-
`String`s, but if you need more you can always write your own:
|
160
|
+
There are type handlers included for `Date`s, `Time`s, `DateTime`s, `URI`s,
|
161
|
+
`Symbol`s and `String`s, but if you need more you can always write your own:
|
162
|
+
|
163
|
+
class Person
|
164
|
+
attr_accessor :first_name, :middle_names, :last_name
|
165
|
+
|
166
|
+
def initialize(first, *others)
|
167
|
+
@first_name, @last_name, @middle_names = first, others.pop, others
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
Acclaim::Option::Type.add_handler_for Person do |argument|
|
172
|
+
Person.new *argument.split
|
173
|
+
end
|
164
174
|
|
165
|
-
|
175
|
+
class App::Command::Show < App::Command
|
166
176
|
|
167
|
-
|
168
|
-
opt :
|
177
|
+
# If no switches are specified, one will be derived from the key
|
178
|
+
opt :person, Person, arity: [1,0], required: true
|
169
179
|
|
170
180
|
when_called do |options, args|
|
171
|
-
|
181
|
+
puts "#{options.person.last_name}, #{options.person.first_name}"
|
172
182
|
end
|
173
183
|
end
|
174
184
|
|
175
|
-
$ app
|
176
|
-
|
177
|
-
Symbol => :s
|
178
|
-
Symbol => :d
|
185
|
+
$ app show --person 'Matheus Afonso Martins Moreira'
|
186
|
+
Moreira, Matheus
|
179
187
|
|
180
188
|
`add_handler_for` takes a class and a block, which will be called for every
|
181
189
|
argument of that class that must be parsed.
|
data/lib/acclaim/command.rb
CHANGED
@@ -69,6 +69,7 @@ module Acclaim
|
|
69
69
|
options << Option.new(*args, &block)
|
70
70
|
end
|
71
71
|
|
72
|
+
# Same as #option.
|
72
73
|
alias :opt :option
|
73
74
|
|
74
75
|
# The block which is executed when this command is called. It is given 2
|
@@ -78,6 +79,7 @@ module Acclaim
|
|
78
79
|
@action = block
|
79
80
|
end
|
80
81
|
|
82
|
+
# Same as #action.
|
81
83
|
alias :when_called :action
|
82
84
|
|
83
85
|
# Adds help subcommand and options to this command.
|
@@ -132,6 +134,7 @@ module Acclaim
|
|
132
134
|
@action.call opts, args if @action
|
133
135
|
end
|
134
136
|
|
137
|
+
# Same as #execute.
|
135
138
|
alias :call :execute
|
136
139
|
|
137
140
|
# True if this is a top-level command.
|
@@ -154,6 +157,7 @@ module Acclaim
|
|
154
157
|
const_get(:Version).execute opts, args if opts.acclaim_version?
|
155
158
|
end
|
156
159
|
|
160
|
+
# Deletes all argument separators in the given argument array.
|
157
161
|
def delete_argument_separators_in!(args)
|
158
162
|
args.delete_if do |arg|
|
159
163
|
arg =~ Option::Parser::Regexp::ARGUMENT_SEPARATOR
|
@@ -7,7 +7,11 @@ module Acclaim
|
|
7
7
|
# the elements of the array.
|
8
8
|
class Parser
|
9
9
|
|
10
|
-
|
10
|
+
# The argument array to be searched.
|
11
|
+
attr_accessor :argv
|
12
|
+
|
13
|
+
# The commands to search for.
|
14
|
+
attr_accessor :commands
|
11
15
|
|
12
16
|
# Initializes a new command parser, with the given argument array and set
|
13
17
|
# of commands to search for.
|
@@ -36,7 +40,7 @@ module Acclaim
|
|
36
40
|
|
37
41
|
# Searches for one of the given commands in the argument array, and
|
38
42
|
# returns it. Removes the string that matched the command name from
|
39
|
-
# +argv+. Returns +nil if no command was found.
|
43
|
+
# +argv+. Returns +nil+ if no command was found.
|
40
44
|
def find_command
|
41
45
|
commands.find do |command|
|
42
46
|
arguments_up_to_separator.include? command.line
|
data/lib/acclaim/option.rb
CHANGED
@@ -1,13 +1,36 @@
|
|
1
1
|
require 'acclaim/option/arity'
|
2
2
|
require 'acclaim/option/parser/regexp'
|
3
3
|
require 'acclaim/option/type'
|
4
|
+
require 'ribbon'
|
5
|
+
require 'ribbon/core_ext/array'
|
4
6
|
|
5
7
|
module Acclaim
|
6
8
|
|
7
9
|
# Represents a command-line option.
|
8
10
|
class Option
|
9
11
|
|
10
|
-
|
12
|
+
# The key used to store the value of the option.
|
13
|
+
attr_accessor :key
|
14
|
+
|
15
|
+
# The strings that refer to this option in the command line.
|
16
|
+
attr_accessor :names
|
17
|
+
|
18
|
+
# The description of this option.
|
19
|
+
attr_accessor :description
|
20
|
+
|
21
|
+
# The type the option's value will be converted to. See Option::Type.
|
22
|
+
attr_accessor :type
|
23
|
+
|
24
|
+
# The default value for the option. Default is +nil+.
|
25
|
+
attr_accessor :default
|
26
|
+
|
27
|
+
# This option's custom handler.
|
28
|
+
attr_accessor :handler
|
29
|
+
|
30
|
+
# How the parser should react when multiple instances of this option are
|
31
|
+
# found in the command line. It will, by default, replace the old value with
|
32
|
+
# the new one, but it can also collect all values or raise an error.
|
33
|
+
attr_accessor :on_multiple
|
11
34
|
|
12
35
|
# Initializes a command line option. The +key+ is the object used to
|
13
36
|
# associate this option with a value. The other arguments may be:
|
@@ -23,13 +46,20 @@ module Acclaim
|
|
23
46
|
# [class] The <tt>Class</tt> which will be used in parameter
|
24
47
|
# conversion. The default is <tt>String</tt>.
|
25
48
|
#
|
49
|
+
# If no switches were specified, the +key+ will be used to derive one. See
|
50
|
+
# Option::name_from for details.
|
51
|
+
#
|
26
52
|
# The last argument can be a hash of options, which may specify:
|
27
53
|
#
|
28
|
-
# [:arity]
|
29
|
-
#
|
30
|
-
# [:default]
|
31
|
-
# [:required]
|
32
|
-
#
|
54
|
+
# [:arity] The number of required and optional arguments. See Arity
|
55
|
+
# for defails. Defaults to no arguments.
|
56
|
+
# [:default] The default value for this option. Defaults to +nil+.
|
57
|
+
# [:required] Whether or not the option must be present on the command
|
58
|
+
# line. Default is +false+.
|
59
|
+
# [:on_multiple] What to do if the option is encountered multiple times.
|
60
|
+
# Supported modes are <tt>:replace</tt>, <tt>:append</tt>
|
61
|
+
# and <tt>:raise</tt>. New values will replace old ones by
|
62
|
+
# default.
|
33
63
|
#
|
34
64
|
# Additionally, if a block is given, it will be called when the option is
|
35
65
|
# parsed with a ribbon instance and the parameters given to the option. The
|
@@ -37,18 +67,20 @@ module Acclaim
|
|
37
67
|
# this is not desirable consider not specifying a class to the option or
|
38
68
|
# registering a custom type handler.
|
39
69
|
def initialize(key, *args, &block)
|
40
|
-
options = args.
|
41
|
-
matches = args.select
|
70
|
+
options = args.extract_ribbon!
|
71
|
+
matches = args.select do |arg|
|
72
|
+
arg.is_a? String
|
73
|
+
end.group_by do |arg|
|
42
74
|
arg =~ Parser::Regexp::SWITCH ? true : false
|
43
75
|
end
|
44
76
|
klass = args.find { |arg| arg.is_a? Module }
|
45
77
|
self.key = key
|
46
|
-
self.names = matches.fetch
|
78
|
+
self.names = matches.fetch(true) { [ Option.name_from(key) ] }
|
47
79
|
self.description = matches.fetch(false, []).first
|
48
|
-
self.on_multiple = options.
|
49
|
-
self.arity = options
|
50
|
-
self.default = options
|
51
|
-
self.required = options
|
80
|
+
self.on_multiple = options.on_multiple? :replace
|
81
|
+
self.arity = options.arity?
|
82
|
+
self.default = options.default?
|
83
|
+
self.required = options.required?
|
52
84
|
self.type = klass || String
|
53
85
|
self.handler = block
|
54
86
|
end
|
@@ -94,14 +126,38 @@ module Acclaim
|
|
94
126
|
self.required = true
|
95
127
|
end
|
96
128
|
|
97
|
-
# Returns true if this option takes no arguments.
|
129
|
+
# Returns +true+ if this option takes no arguments.
|
98
130
|
def flag?
|
99
131
|
not arity or arity == [0, 0]
|
100
132
|
end
|
101
133
|
|
102
|
-
|
134
|
+
# Same as <tt>flag?</tt>
|
135
|
+
alias :bool? :flag?
|
136
|
+
|
137
|
+
# Same as <tt>flag?</tt>
|
103
138
|
alias :boolean? :flag?
|
104
|
-
|
139
|
+
|
140
|
+
# Same as <tt>flag?</tt>
|
141
|
+
alias :switch? :flag?
|
142
|
+
|
143
|
+
# The class methods.
|
144
|
+
class << self
|
145
|
+
|
146
|
+
# Derives a name from the given key's string representation. All
|
147
|
+
# underscores will be replaced with dashes.
|
148
|
+
#
|
149
|
+
# If the string is empty, an +ArgumentError+ will be raised. If the
|
150
|
+
# resulting name is not a valid switch, a +NameError+ will be raised.
|
151
|
+
def name_from(key)
|
152
|
+
name = key.to_s
|
153
|
+
raise ArgumentError, "Can't derive name from empty string representation." if name.empty?
|
154
|
+
name = (name.length == 1 ? '-' : '--') + name
|
155
|
+
name.gsub! '_', '-'
|
156
|
+
raise NameError, "Derived name is invalid: #{name}" unless name =~ Parser::Regexp::SWITCH
|
157
|
+
name
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
105
161
|
|
106
162
|
end
|
107
163
|
end
|
data/lib/acclaim/option/arity.rb
CHANGED
@@ -5,7 +5,13 @@ module Acclaim
|
|
5
5
|
# and optional.
|
6
6
|
class Arity
|
7
7
|
|
8
|
-
|
8
|
+
# The minimum number of arguments.
|
9
|
+
attr_accessor :minimum
|
10
|
+
|
11
|
+
# The number of optional arguments.
|
12
|
+
attr_accessor :optional
|
13
|
+
|
14
|
+
# Same as +minimum+.
|
9
15
|
alias :required :minimum
|
10
16
|
|
11
17
|
# Initializes this arity with a number of required parameters and a number
|
@@ -45,7 +51,10 @@ module Acclaim
|
|
45
51
|
[ minimum, optional ]
|
46
52
|
end
|
47
53
|
|
54
|
+
# Same as +to_a+.
|
48
55
|
alias :to_ary :to_a
|
56
|
+
|
57
|
+
# Same as +to_a+.
|
49
58
|
alias :to_array :to_a
|
50
59
|
|
51
60
|
# Equivalent to <tt>to_a.hash</tt>.
|
@@ -62,7 +71,10 @@ module Acclaim
|
|
62
71
|
to_a == arity.to_a
|
63
72
|
end
|
64
73
|
|
74
|
+
# Same as <tt>==</tt>
|
65
75
|
alias :eql? :==
|
76
|
+
|
77
|
+
# Same as <tt>==</tt>
|
66
78
|
alias :=== :==
|
67
79
|
|
68
80
|
# Returns a string in the following format:
|
@@ -37,7 +37,11 @@ module Acclaim
|
|
37
37
|
|
38
38
|
end
|
39
39
|
|
40
|
-
|
40
|
+
# The argument array to parse.
|
41
|
+
attr_accessor :argv
|
42
|
+
|
43
|
+
# The options to be parsed.
|
44
|
+
attr_accessor :options
|
41
45
|
|
42
46
|
# Initializes a new parser, with the given argument array and set of
|
43
47
|
# options. If no option array is given, the argument array will be
|
data/lib/acclaim/option/type.rb
CHANGED
@@ -4,40 +4,55 @@ module Acclaim
|
|
4
4
|
# Associates a class with a handler block.
|
5
5
|
module Type
|
6
6
|
|
7
|
-
#
|
8
|
-
|
9
|
-
def self.each(&block)
|
10
|
-
table.each &block
|
11
|
-
end
|
7
|
+
# The class methods.
|
8
|
+
class << self
|
12
9
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
# Yields class, proc pairs if a block was given. Returns an enumerator
|
11
|
+
# otherwise.
|
12
|
+
def each(&block)
|
13
|
+
table.each &block
|
14
|
+
end
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
table[klass] = block
|
21
|
-
end
|
16
|
+
# Take advantage of each method.
|
17
|
+
include Enumerable
|
22
18
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
# Returns all registered classes.
|
20
|
+
def all
|
21
|
+
table.keys
|
22
|
+
end
|
27
23
|
|
28
|
-
|
24
|
+
# Registers a handler for a class.
|
25
|
+
def register(klass, &block)
|
26
|
+
table[klass] = block
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the handler for the given class.
|
30
|
+
def handler_for(klass)
|
31
|
+
table.fetch klass do
|
32
|
+
raise "#{klass} does not have an associated handler"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Same as <tt>all</tt>.
|
29
37
|
alias registered all
|
38
|
+
|
39
|
+
# Same as <tt>register</tt>.
|
30
40
|
alias add_handler_for register
|
41
|
+
|
42
|
+
# Same as <tt>register</tt>.
|
31
43
|
alias accept register
|
44
|
+
|
45
|
+
# Same as <tt>handler_for</tt>.
|
32
46
|
alias [] handler_for
|
33
|
-
end
|
34
47
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
48
|
+
private
|
49
|
+
|
50
|
+
# The hash used to associate classes with their handlers.
|
51
|
+
def table
|
52
|
+
@table ||= {}
|
53
|
+
end
|
39
54
|
|
40
|
-
|
55
|
+
end
|
41
56
|
|
42
57
|
end
|
43
58
|
|
data/lib/acclaim/version.rb
CHANGED
@@ -11,12 +11,12 @@ module Acclaim
|
|
11
11
|
# Minor version.
|
12
12
|
#
|
13
13
|
# Increments denote backward-compatible changes and additions.
|
14
|
-
MINOR =
|
14
|
+
MINOR = 1
|
15
15
|
|
16
16
|
# Patch version.
|
17
17
|
#
|
18
18
|
# Increments denote changes in implementation.
|
19
|
-
PATCH =
|
19
|
+
PATCH = 0
|
20
20
|
|
21
21
|
# Build version.
|
22
22
|
#
|
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.1.0
|
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: 2012-01-
|
12
|
+
date: 2012-01-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ribbon
|
16
|
-
requirement: &
|
16
|
+
requirement: &22189080 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *22189080
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &22188500 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *22188500
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rookie
|
38
|
-
requirement: &
|
38
|
+
requirement: &22188080 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *22188080
|
47
47
|
description: Command-line option parser and command interface.
|
48
48
|
email: matheus.a.m.moreira@gmail.com
|
49
49
|
executables: []
|
@@ -94,7 +94,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
94
|
version: '0'
|
95
95
|
segments:
|
96
96
|
- 0
|
97
|
-
hash:
|
97
|
+
hash: -901301498998529047
|
98
98
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
99
|
none: false
|
100
100
|
requirements:
|
@@ -103,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
103
|
version: '0'
|
104
104
|
segments:
|
105
105
|
- 0
|
106
|
-
hash:
|
106
|
+
hash: -901301498998529047
|
107
107
|
requirements: []
|
108
108
|
rubyforge_project:
|
109
109
|
rubygems_version: 1.8.10
|