acclaim 0.3.2 → 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/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  *.lock
2
2
  doc/
3
+ .yardoc/
@@ -1,24 +1,27 @@
1
1
  #!/usr/bin/env gem build
2
2
  # encoding: utf-8
3
- $:.unshift File.expand_path('../lib', __FILE__)
4
3
 
5
- require 'acclaim/version'
4
+ Gem::Specification.new 'acclaim' do |gem|
6
5
 
7
- Gem::Specification.new('acclaim') do |gem|
6
+ current_directory = File.dirname __FILE__
7
+ version_file = File.expand_path "#{gem.name}.version", current_directory
8
8
 
9
- gem.version = Acclaim::Version::STRING
10
- gem.summary = 'Command-line option parser and command interface.'
11
- gem.description = gem.summary
12
- gem.homepage = 'https://github.com/matheusmoreira/acclaim'
9
+ gem.version = File.read(version_file).chomp
10
+
11
+ gem.summary = 'Command-line option parser and command interface.'
12
+ gem.homepage = 'https://github.com/matheusmoreira/acclaim'
13
13
 
14
14
  gem.author = 'Matheus Afonso Martins Moreira'
15
- gem.email = 'matheus.a.m.moreira@gmail.com'
15
+ gem.email = 'matheus.a.m.moreira@gmail.com'
16
16
 
17
17
  gem.files = `git ls-files`.split "\n"
18
18
 
19
+ gem.add_runtime_dependency 'jewel'
19
20
  gem.add_runtime_dependency 'ribbon'
20
21
 
21
- gem.add_development_dependency 'rspec'
22
+ gem.add_development_dependency 'redcarpet'
22
23
  gem.add_development_dependency 'rookie'
24
+ gem.add_development_dependency 'rspec'
25
+ gem.add_development_dependency 'yard'
23
26
 
24
27
  end
@@ -0,0 +1 @@
1
+ 0.4.0
@@ -1,7 +1,14 @@
1
- # Acclaim is a command line option parsing and command interface for Ruby.
1
+ # Command line option parsing and command interface for Ruby.
2
+ #
3
+ # @author Matheus Afonso Martins Moreira
4
+ # @since 0.0.1
2
5
  module Acclaim
3
6
  end
4
7
 
5
- %w(command option version).each do |file|
6
- require file.prepend 'acclaim/'
7
- end
8
+ %w(
9
+
10
+ acclaim/command
11
+ acclaim/gem
12
+ acclaim/option
13
+
14
+ ).each { |file| require file }
@@ -1,8 +1,15 @@
1
- %w(option option/parser option/parser/regexp).each do |file|
2
- require file.prepend 'acclaim/'
3
- end
1
+ %w(
2
+
3
+ acclaim/command/dsl
4
+ acclaim/command/parser
5
+ acclaim/option
6
+ acclaim/option/parser
7
+ acclaim/option/parser/regexp
4
8
 
5
- %w(ribbon ribbon/core_extensions/object).each { |file| require file }
9
+ ribbon
10
+ ribbon/core_extensions/object
11
+
12
+ ).each { |file| require file }
6
13
 
7
14
  module Acclaim
8
15
 
@@ -42,177 +49,19 @@ module Acclaim
42
49
  # Verbose? yes
43
50
  # Doing testing with acclaim and safeguard!
44
51
  class Command
52
+ end
45
53
 
46
- # Module containing the class methods every command class should inherit.
47
- module ClassMethods
48
-
49
- # String which calls this command.
50
- def line(*args)
51
- @line = args.first unless args.empty?
52
- @line ||= (name.gsub(/^.*::/, '').downcase rescue nil)
53
- end
54
-
55
- # Commands which may be given to this command.
56
- def subcommands
57
- @subcommands ||= []
58
- end
59
-
60
- # The options this command can take.
61
- def options
62
- @options ||= []
63
- end
64
-
65
- # Adds an option to this command.
66
- def option(*args, &block)
67
- options << Option.new(*args, &block)
68
- end
69
-
70
- # Same as #option.
71
- alias opt option
72
-
73
- # The block which is executed when this command is called. It is given 2
74
- # parameters; the first is an Ribbon instance which can be queried for
75
- # settings information; the second is the remaining command line.
76
- def action(&block)
77
- @action = block
78
- end
79
-
80
- # Same as #action.
81
- alias when_called action
82
-
83
- # Adds help subcommand and options to this command.
84
- def help(*args)
85
- Help.create(self, *args)
86
- end
87
-
88
- # Adds help subcommand and options to this command.
89
- def version(*args)
90
- Version.create(self, *args)
91
- end
92
-
93
- # Parses the argument array using this command's set of options.
94
- def parse_options!(args)
95
- Option::Parser.new(args, options).parse!
96
- end
97
-
98
- # Looks for this command's subcommands in the argument array.
99
- def parse_subcommands!(args)
100
- Command::Parser.new(args, subcommands).parse!
101
- end
102
-
103
- # Invokes this command with a fresh set of option values.
104
- def run(*args)
105
- invoke args
106
- rescue Option::Parser::Error => error
107
- $stderr.puts error.message
108
- end
109
-
110
- # Parses the argument array. The argument array will be searched for
111
- # subcommands; if one is found, it will be invoked, if not, this command
112
- # will be executed. A subcommand may be anywhere in the array as long as
113
- # it is before an argument separator, which is tipically a double dash
114
- # (<tt>--</tt>) and may be omitted.
115
- #
116
- # All argument separators will be deleted from the argument array before a
117
- # command is executed.
118
- def invoke(args = [], opts = {})
119
- opts = Ribbon.wrap opts
120
- opts.merge! parse_options!(args)
121
- handle_special_options! opts, args
122
- if subcommand = parse_subcommands!(args)
123
- subcommand.invoke args, opts
124
- else
125
- delete_argument_separators_in! args
126
- execute opts, args
127
- end
128
- end
129
-
130
- # Calls this command's action block with the given option values and
131
- # arguments.
132
- def execute(opts, args)
133
- @action.call opts, args if @action
134
- end
135
-
136
- # Same as #execute.
137
- alias call execute
138
-
139
- # True if this is a top-level command.
140
- def root?
141
- superclass == Acclaim::Command
142
- end
143
-
144
- # Returns all command ancestors of this command.
145
- def command_ancestors
146
- ancestors - Acclaim::Command.ancestors
147
- end
148
-
149
- # Returns the root of the command hierarchy.
150
- def root
151
- command_ancestors.last
152
- end
153
-
154
- # Returns the sequence of commands from #root that leads to this command.
155
- def command_path
156
- command_ancestors.reverse
157
- end
158
-
159
- # Computes the full command line of this command, which takes parent
160
- # commands into account.
161
- #
162
- # class Command < Acclaim::Command
163
- # class Do < Command
164
- # class Something < Do
165
- # end
166
- # end
167
- # end
168
- #
169
- # Command::Do::Something.full_line
170
- # => "do something"
171
- #
172
- # Command::Do::Something.full_line include_root: true
173
- # => "command do something"
174
- def full_line(*args)
175
- options = args.extract_ribbon!
176
- command_path.tap do |path|
177
- path.shift unless options.include_root?
178
- end.map(&:line).join ' '
179
- end
180
-
181
- private
182
-
183
- # Handles special options such as <tt>--help</tt> or <tt>--version</tt>.
184
- def handle_special_options!(opts, args)
185
- const_get(:Help).execute opts, args if opts.acclaim_help?
186
- const_get(:Version).execute opts, args if opts.acclaim_version?
187
- # TODO:
188
- # possibly rescue a NameError and warn user
189
- # fix bug:
190
- # calling this method causes a subcommand to be executed even if it
191
- # wasn't given on the command line. This may result up to **three**
192
- # commands (help, version and the actual command) running in one
193
- # invocation.
194
- end
195
-
196
- # Deletes all argument separators in the given argument array.
197
- def delete_argument_separators_in!(args)
198
- args.delete_if do |arg|
199
- arg =~ Option::Parser::Regexp::ARGUMENT_SEPARATOR
200
- end
201
- end
202
-
203
- end
54
+ class << Command
204
55
 
205
56
  # Add the class methods to the subclass and add it to this command's list of
206
57
  # subcommands.
207
- def self.inherited(sub)
208
- sub.extend ClassMethods
209
- subcommands << sub if respond_to? :subcommands
58
+ #
59
+ # @param [Class] command the class that inherited from this command
60
+ def inherited(command)
61
+ command.extend Command::DSL
62
+ subcommands << command if respond_to? :subcommands
210
63
  end
211
64
 
212
65
  end
213
66
 
214
67
  end
215
-
216
- %w(help parser version).each do |command|
217
- require command.prepend 'acclaim/command/'
218
- end
@@ -0,0 +1,181 @@
1
+ require 'acclaim/command/dsl/root'
2
+
3
+ module Acclaim
4
+ class Command
5
+
6
+ # Module containing the methods that make up the domain-specific language
7
+ # used to create commands.
8
+ #
9
+ # @author Matheus Afonso Martins Moreira
10
+ # @since 0.4.0
11
+ module DSL
12
+
13
+ # The string used to invoke this command from the command line.
14
+ #
15
+ # @overload line
16
+ # If not set, will try to figure out the name from the command's class.
17
+ #
18
+ # @return [String] the name used to invoke this command
19
+ #
20
+ # @overload line(string)
21
+ # Uses the given string to invoke this command.
22
+ #
23
+ # @param [String, nil] string the new command name
24
+ # @return [String] the name used to invoke this command
25
+ def line(*arguments)
26
+ @line = arguments.first unless arguments.empty?
27
+ @line ||= (name.gsub(/^.*::/, '').downcase if respond_to? :name)
28
+ end
29
+
30
+ # Commands which may be given to this command.
31
+ #
32
+ # @return [Array] this command's subcommands
33
+ def subcommands
34
+ @subcommands ||= []
35
+ end
36
+
37
+ # The options this command can take.
38
+ #
39
+ # @return [Array] the options this command takes
40
+ def options
41
+ @options ||= []
42
+ end
43
+
44
+ # Adds an option to this command.
45
+ #
46
+ # @see Acclaim::Option#initialize
47
+ def option(*arguments, &block)
48
+ options << Option.new(*arguments, &block)
49
+ end
50
+
51
+ alias opt option
52
+
53
+ # The block which is executed when this command is called.
54
+ #
55
+ # @yieldparam [Ribbon] options a Ribbon instance which associates options
56
+ # with their corresponding values
57
+ # @yieldparam [Array] arguments the arguments that remained in the command
58
+ # line
59
+ # @return [Proc, nil] the given block
60
+ def action(&block)
61
+ @action = block if block.respond_to? :call
62
+ @action
63
+ end
64
+
65
+ alias when_called action
66
+
67
+ # Parses the argument array using this command's set of options.
68
+ def parse_options_in!(arguments)
69
+ Option::Parser.new(arguments, options).parse!
70
+ end
71
+
72
+ # Looks for this command's subcommands in the argument array.
73
+ def parse_subcommands_in!(arguments)
74
+ Command::Parser.new(arguments, subcommands).parse!
75
+ end
76
+
77
+ # Invokes this command with a fresh set of option values.
78
+ def run(*arguments)
79
+ invoke arguments
80
+ rescue Option::Parser::Error => error
81
+ $stderr.puts error.message
82
+ end
83
+
84
+ # Parses the argument array. The argument array will be searched for
85
+ # subcommands; if one is found, it will be invoked, if not, this command
86
+ # will be executed. A subcommand may be anywhere in the array as long as
87
+ # it is before an argument separator, which is tipically a double dash
88
+ # (<tt>--</tt>) and may be omitted.
89
+ #
90
+ # All argument separators will be deleted from the argument array before a
91
+ # command is executed.
92
+ def invoke(arguments = [], options = [])
93
+ options = options + self.options
94
+ subcommand = parse_subcommands_in! arguments
95
+ if subcommand.nil?
96
+ parsed_options = Option::Parser.new(arguments, options).parse!
97
+ delete_argument_separators_in! arguments
98
+ execute parsed_options, arguments
99
+ else
100
+ subcommand.invoke arguments, options
101
+ end
102
+ end
103
+
104
+ # Calls this command's action block with the given option values and
105
+ # arguments.
106
+ def execute(options, arguments)
107
+ @action.call options, arguments if @action.respond_to? :call
108
+ end
109
+
110
+ alias call execute
111
+
112
+ # True if this is a top-level command.
113
+ def root?
114
+ superclass == Acclaim::Command
115
+ end
116
+
117
+ # Returns all command ancestors of this command.
118
+ def command_ancestors
119
+ ancestors - Acclaim::Command.ancestors
120
+ end
121
+
122
+ # Returns the root of the command hierarchy.
123
+ def root
124
+ command_ancestors.last
125
+ end
126
+
127
+ # Returns the sequence of commands from #root that leads to this command.
128
+ def command_path
129
+ command_ancestors.reverse
130
+ end
131
+
132
+ # Computes the full command line of this command, which takes parent
133
+ # commands into account.
134
+ #
135
+ # class Command < Acclaim::Command
136
+ # class Do < Command
137
+ # class Something < Do
138
+ # end
139
+ # end
140
+ # end
141
+ #
142
+ # Command::Do::Something.full_line
143
+ # => "do something"
144
+ #
145
+ # Command::Do::Something.full_line include_root: true
146
+ # => "command do something"
147
+ def full_line(*arguments)
148
+ options = arguments.extract_ribbon!
149
+ command_path.tap do |path|
150
+ path.shift unless options.include_root?
151
+ end.map(&:line).join ' '
152
+ end
153
+
154
+ private
155
+
156
+ # Handles special options such as <tt>--help</tt> or <tt>--version</tt>.
157
+ def handle_special_options!(options, arguments)
158
+ const_get(:Help).execute options, arguments if options.acclaim_help?
159
+ const_get(:Version).execute options, arguments if options.acclaim_version?
160
+ # TODO:
161
+ # possibly rescue a NameError and warn user
162
+ # fix bug:
163
+ # calling this method causes a subcommand to be executed even if it
164
+ # wasn't given on the command line. This may result up to **three**
165
+ # commands (help, version and the actual command) running in one
166
+ # invocation.
167
+ end
168
+
169
+ # Deletes all argument separators in the given argument array.
170
+ def delete_argument_separators_in!(arguments)
171
+ arguments.delete_if do |arg|
172
+ arg =~ Option::Parser::Regexp::ARGUMENT_SEPARATOR
173
+ end
174
+ end
175
+
176
+ include Root
177
+
178
+ end
179
+
180
+ end
181
+ end
@@ -0,0 +1,36 @@
1
+ %w(
2
+
3
+ acclaim/command/help
4
+ acclaim/command/version
5
+
6
+ ).each { |file| require file }
7
+
8
+ module Acclaim
9
+ class Command
10
+ module DSL
11
+
12
+ # Methods that only work with root commands.
13
+ #
14
+ # @author Matheus Afonso Martins Moreira
15
+ # @since 0.4.0
16
+ module Root
17
+
18
+ # Adds help subcommand and options to this command.
19
+ #
20
+ # @see Acclaim::Command::Help.create
21
+ def help(*arguments, &block)
22
+ Help.create root, *arguments, &block
23
+ end
24
+
25
+ # Adds version subcommand and options to this command.
26
+ #
27
+ # @see Acclaim::Command::Help.create
28
+ def version(*arguments, &block)
29
+ Version.create root, *arguments, &block
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ require 'jewel'
2
+
3
+ module Acclaim
4
+
5
+ # Acclaim gem information and metadata.
6
+ #
7
+ # @author Matheus Afonso Martins Moreira
8
+ # @since 0.4.0
9
+ class Gem < Jewel::Gem
10
+
11
+ root '../..'
12
+
13
+ specification ::Gem::Specification.load root.join('acclaim.gemspec').to_s
14
+
15
+ end
16
+
17
+ end
@@ -139,7 +139,7 @@ module Acclaim
139
139
 
140
140
  # Returns +true+ if this option takes no arguments.
141
141
  def flag?
142
- arity and arity.none?
142
+ arity.none?
143
143
  end
144
144
 
145
145
  # Same as <tt>flag?</tt>
@@ -151,6 +151,22 @@ module Acclaim
151
151
  # Same as <tt>flag?</tt>
152
152
  alias switch? flag?
153
153
 
154
+ # Generate human-readable string containing this option's data.
155
+ #
156
+ # @return [String] string describing this option
157
+ def inspect
158
+ '#<%s %s (%s) %s = %s %s %s %s>' % [
159
+ self.class.name,
160
+ key,
161
+ names.join('|'),
162
+ type.inspect,
163
+ default.inspect,
164
+ arity.inspect,
165
+ on_multiple,
166
+ if required? then :required else :optional end
167
+ ]
168
+ end
169
+
154
170
  end
155
171
 
156
172
  class << Option
@@ -1,11 +1,19 @@
1
- %w(error regexp).each { |file| require file.prepend 'acclaim/option/parser/' }
1
+ %w(
2
2
 
3
- require 'ribbon'
3
+ acclaim/option/parser/error
4
+ acclaim/option/parser/regexp
5
+
6
+ ribbon
7
+
8
+ ).each { |file| require file }
4
9
 
5
10
  module Acclaim
6
11
  class Option
7
12
 
8
13
  # Parses arrays of strings and returns an Options instance containing data.
14
+ #
15
+ # @author Matheus Afonso Martins Moreira
16
+ # @since 0.0.1
9
17
  class Parser
10
18
 
11
19
  include Parser::Regexp
@@ -24,11 +32,15 @@ module Acclaim
24
32
  self.options = options || []
25
33
  end
26
34
 
27
- # Parses the meaning of the options given to this parser. If none were
28
- # given, the argument array will be preprocessed only. Any parsed options
29
- # and arguments will be removed from the argument array, so pass in a
30
- # duplicate if you need the original.
35
+ # Parses the given argument array, looking for the given {Option options}
36
+ # and their arguments if any.
37
+ #
38
+ # If no options were given, the argument array will be preprocessed only.
39
+ #
40
+ # @note Parsed options and their parameters will be removed from the
41
+ # argument array.
31
42
  #
43
+ # @example
32
44
  # include Acclaim
33
45
  #
34
46
  # args = %w(-F log.txt --verbose arg1 arg2)
@@ -37,22 +49,49 @@ module Acclaim
37
49
  # options << Option.new(:verbose)
38
50
  #
39
51
  # Option::Parser.new(args, options).parse!
40
- # => {file: "log.txt", verbose: true}
52
+ # # => {file: "log.txt", verbose: true}
41
53
  #
42
54
  # args
43
- # => ["arg1", "arg2"]
55
+ # # => ["arg1", "arg2"]
44
56
  def parse!
45
57
  preprocess_argv!
46
- parse_values!
58
+ parse_values!.tap do
59
+ delete_options_from_argv!
60
+ end
47
61
  end
48
62
 
49
63
  private
50
64
 
65
+ # List of arguments that are to be removed from argv, identified by their
66
+ # index.
67
+ #
68
+ # @return [Array] the indexes of options marked for deletion
69
+ # @see #delete_options_from_argv!
70
+ # @since 0.4.0
71
+ def deleted_options
72
+ @deleted_options ||= []
73
+ end
74
+
75
+ # Deletes all marked options from argv.
76
+ #
77
+ # @note The list of removed indexes will be discarded.
78
+ #
79
+ # @see #deleted_options
80
+ # @since 0.4.0
81
+ def delete_options_from_argv!
82
+ argv.delete_if.with_index do |argument, index|
83
+ deleted_options.include? index
84
+ end
85
+ ensure
86
+ deleted_options.clear
87
+ end
88
+
51
89
  # Preprocesses the argument array.
52
90
  def preprocess_argv!
53
91
  split_multiple_short_options!
54
92
  normalize_parameters!
55
93
  argv.compact!
94
+ check_for_errors!
56
95
  end
57
96
 
58
97
  # Splits multiple short options.
@@ -73,6 +112,8 @@ module Acclaim
73
112
  # %w(--switch=PARAM1,PARAM2) => %w(--switch PARAM1 PARAM2)
74
113
  # %w(--switch=PARAM1,) => %w(--switch PARAM1)
75
114
  # %w(--switch=,PARAM2) => [ '--switch', '', 'PARAM2' ]
115
+ #
116
+ # @since 0.0.3
76
117
  def normalize_parameters!
77
118
  argv.find_all { |arg| arg =~ SWITCH_PARAM_EQUALS }.each do |switch|
78
119
  switch_index = argv.index switch
@@ -83,48 +124,79 @@ module Acclaim
83
124
  end
84
125
  end
85
126
 
127
+ # Checks to see if the arguments have any errors
128
+ #
129
+ # @since 0.4.0
130
+ def check_for_errors!
131
+ ensure_required_options_are_present!
132
+ raise_on_multiple_options!
133
+ end
134
+
135
+ # Ensures all options are present in the argument array; raises a parser
136
+ # error otherwise.
137
+ #
138
+ # @since 0.4.0
139
+ def ensure_required_options_are_present!
140
+ options.find_all(&:required?).each do |option|
141
+ Error.raise_missing_required option if argv.find_all do |argument|
142
+ option =~ argument
143
+ end.empty?
144
+ end
145
+ end
146
+
147
+ # Raises a parser error if multiple switches were found for an option that
148
+ # explicitly disallowed it.
149
+ #
150
+ # @since 0.4.0
151
+ def raise_on_multiple_options!
152
+ options.find_all do |option|
153
+ option.on_multiple == :raise
154
+ end.each do |option|
155
+ Error.raise_multiple option if argv.find_all do |argument|
156
+ option =~ argument
157
+ end.count > 1
158
+ end
159
+ end
160
+
86
161
  # Parses the options and their arguments, associating that information
87
162
  # with a Ribbon instance.
163
+ #
164
+ # @since 0.0.3
88
165
  def parse_values!
89
166
  values = Ribbon.wrap
90
- options.each do |option|
91
- key = option.key
92
- values[key] = option.default unless values.has_key? key
93
- switches = argv.find_all { |switch| option =~ switch }
94
- Error.raise_missing_required option if option.required? and switches.empty?
95
- Error.raise_multiple option if option.on_multiple == :raise and switches.count > 1
96
- switches.each do |switch|
167
+ argv.each_with_index do |argument, index|
168
+ options.find_all do |option|
169
+ option =~ argument
170
+ end.each do |option|
171
+ key = option.key
172
+ values[key] = option.default unless values.has_key? key
97
173
  if option.flag?
98
174
  found_boolean option, values.ribbon
99
- argv.delete_at argv.index(switch)
175
+ deleted_options << index
100
176
  else
101
- params = extract_parameters_of! option, switch
102
- found_params_for option, params, values.ribbon
177
+ parameters = extract_parameters_of! option, index
178
+ found_params_for option, parameters, values.ribbon
103
179
  end
104
180
  end
105
181
  end
106
182
  values
107
183
  end
108
184
 
109
- # Finds the +switch+ in #argv and scans the next +option.arity.total+
110
- # elements if +option.arity.bound?+ is +true+, or all parameters
111
- # otherwise. In either case, the algorithm will stop if it finds +nil+,
112
- # another switch or an argument separator among the parameters.
185
+ # Starting from the given index, extracts parameters from the following
186
+ # arguments. Stops if it finds nil, another switch, an argument separator,
187
+ # or if enough values have been found according to the option's arity.
188
+ #
189
+ # @note All arguments scanned, in addition to the option at the given
190
+ # index, will be marked for deletion.
113
191
  #
114
- # Deletes the switch and every value that was extracted from #argv. Raises
115
- # an Error if the number of parameters found is less than
116
- # +option.arity.required+.
117
- def extract_parameters_of!(option, switch)
192
+ # @return [Array] the parameters for the given option found in argv
193
+ # @raise [Parser::Error] if not enough arguments are found
194
+ # @since 0.0.4
195
+ def extract_parameters_of!(option, index)
118
196
  arity = option.arity
119
- switch_index = argv.index switch
120
- len = if arity.bound?
121
- switch_index + arity.total
122
- else
123
- argv.length - 1
124
- end
125
- params = argv[switch_index + 1, len]
197
+ length = if arity.bound? then index + arity.total else argv.length - 1 end
126
198
  values = []
127
- params.each do |param|
199
+ argv[index + 1, length].each do |param|
128
200
  case param
129
201
  when nil, SWITCH, ARGUMENT_SEPARATOR then break
130
202
  else
@@ -134,7 +206,9 @@ module Acclaim
134
206
  end
135
207
  count = values.count
136
208
  Error.raise_wrong_arg_number count, *arity if count < arity.required
137
- argv.slice! switch_index..(switch_index + count)
209
+ limit = index + count
210
+ range = index..limit
211
+ deleted_options.push *range
138
212
  values
139
213
  end
140
214
 
@@ -148,6 +222,8 @@ module Acclaim
148
222
  # so. In this case, the value of the option will always be an array.
149
223
  #
150
224
  # The parameters will be converted according to the option's type.
225
+ #
226
+ # @since 0.0.6
151
227
  def found_params_for(option, params = [], ribbon = Ribbon.new)
152
228
  params = option.convert_parameters *params
153
229
  if handler = option.handler then handler.call ribbon, params
@@ -162,6 +238,8 @@ module Acclaim
162
238
  # If the option has an custom handler associated, it will be called with
163
239
  # only the option values as the first argument. Otherwise, the value will
164
240
  # be set to <tt>true</tt>.
241
+ #
242
+ # @since 0.0.6
165
243
  def found_boolean(option, ribbon = Ribbon.new)
166
244
  if handler = option.handler then handler.call ribbon
167
245
  else ribbon[option.key] = true end
@@ -201,6 +201,31 @@ describe Acclaim::Option::Parser do
201
201
  end
202
202
  end
203
203
 
204
+ context 'which contains one option with unbound aritiy and one boolean option' do
205
+ let(:options) { [ Acclaim::Option.new(:boolean), Acclaim::Option.new(:parameters, arity: [1, -1]) ] }
206
+
207
+ context 'and the arguments are such that the boolean option is between the parameters' do
208
+ let!(:args) { %w(--parameters a b c d --boolean e f g) }
209
+
210
+ it 'should parse from left to right, stopping at the boolean option' do
211
+ subject.parse!
212
+ args.should == %w(e f g)
213
+ end
214
+
215
+ context 'the parsed ribbon' do
216
+ let(:ribbon) { subject.parse! }
217
+
218
+ it 'should cointain the correct value for boolean' do
219
+ ribbon.parameters.should == %w(a b c d)
220
+ end
221
+
222
+ it 'should cointain the correct value for parameters' do
223
+ ribbon.boolean.should be_true
224
+ end
225
+ end
226
+ end
227
+ end
228
+
204
229
  context 'containing an option which' do
205
230
  let!(:options) { [ Acclaim::Option.new(:files, '-f', arity: [1,0], on_multiple: on_multiple, &block) ] }
206
231
  let!(:args) { %w(-f f1 -f f2 -f f3) }
@@ -15,17 +15,45 @@ describe Acclaim::Option do
15
15
  subject.key.should == key
16
16
  end
17
17
 
18
- context 'when given multiple strings' do
18
+ context 'when given multiple switches' do
19
19
  let(:switches) { %w(-s --switch) }
20
+
21
+ context 'directly' do
22
+ let(:args) { [*switches] }
23
+
24
+ it 'should find the switches' do
25
+ subject.names.should == switches
26
+ end
27
+ end
28
+
29
+ context 'as an array' do
30
+ let(:args) { [switches] }
31
+
32
+ it 'should find the switches' do
33
+ subject.names.should == switches
34
+ end
35
+ end
36
+ end
37
+
38
+ context 'when given a description string' do
20
39
  let(:description) { 'Description' }
21
- let(:args) { [*switches, description] }
22
40
 
23
- it 'should find the switches' do
24
- subject.names.should == switches
41
+ context 'by itself' do
42
+ let(:args) { [description] }
43
+
44
+ it 'should find the description' do
45
+ subject.description.should == description
46
+ end
25
47
  end
26
48
 
27
- it 'should find the description' do
28
- subject.description.should == description
49
+ context 'with another description specified in the options hash' do
50
+ let(:description_from_options_hash) { 'Description from options hash' }
51
+ let(:options_hash) { { description: description_from_options_hash } }
52
+ let(:args) { [description, options_hash] }
53
+
54
+ it 'should use the description from the options hash' do
55
+ subject.description.should == description_from_options_hash
56
+ end
29
57
  end
30
58
  end
31
59
 
@@ -114,6 +142,27 @@ describe Acclaim::Option do
114
142
  end
115
143
  end
116
144
  end
145
+
146
+ context 'that specifies a description' do
147
+ let(:hash) { { description: description } }
148
+
149
+ context 'as a regular string' do
150
+ let(:description) { 'Description' }
151
+
152
+ it 'should use the string as the description' do
153
+ subject.description.should == description
154
+ end
155
+ end
156
+
157
+ context 'as a block' do
158
+ let(:description) { -> { 'Description' } }
159
+
160
+ it 'should call the block and use return value as the description' do
161
+ value = description.call
162
+ subject.description.should == value
163
+ end
164
+ end
165
+ end
117
166
  end
118
167
 
119
168
  context 'when not given a block' do
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.3.2
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-10 00:00:00.000000000 Z
12
+ date: 2012-06-22 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: jewel
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: ribbon
16
32
  requirement: !ruby/object:Gem::Requirement
@@ -28,7 +44,7 @@ dependencies:
28
44
  - !ruby/object:Gem::Version
29
45
  version: '0'
30
46
  - !ruby/object:Gem::Dependency
31
- name: rspec
47
+ name: redcarpet
32
48
  requirement: !ruby/object:Gem::Requirement
33
49
  none: false
34
50
  requirements:
@@ -59,7 +75,39 @@ dependencies:
59
75
  - - ! '>='
60
76
  - !ruby/object:Gem::Version
61
77
  version: '0'
62
- description: Command-line option parser and command interface.
78
+ - !ruby/object:Gem::Dependency
79
+ name: rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: yard
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description:
63
111
  email: matheus.a.m.moreira@gmail.com
64
112
  executables: []
65
113
  extensions: []
@@ -72,13 +120,17 @@ files:
72
120
  - README.markdown
73
121
  - Rakefile
74
122
  - acclaim.gemspec
123
+ - acclaim.version
75
124
  - lib/acclaim.rb
76
125
  - lib/acclaim/command.rb
126
+ - lib/acclaim/command/dsl.rb
127
+ - lib/acclaim/command/dsl/root.rb
77
128
  - lib/acclaim/command/help.rb
78
129
  - lib/acclaim/command/help/template.rb
79
130
  - lib/acclaim/command/help/template/command.erb
80
131
  - lib/acclaim/command/parser.rb
81
132
  - lib/acclaim/command/version.rb
133
+ - lib/acclaim/gem.rb
82
134
  - lib/acclaim/option.rb
83
135
  - lib/acclaim/option/arity.rb
84
136
  - lib/acclaim/option/parser.rb
@@ -97,7 +149,6 @@ files:
97
149
  - lib/acclaim/option/type/symbol.rb
98
150
  - lib/acclaim/option/type/time.rb
99
151
  - lib/acclaim/option/type/uri.rb
100
- - lib/acclaim/version.rb
101
152
  - spec/acclaim/command_spec.rb
102
153
  - spec/acclaim/option/arity_spec.rb
103
154
  - spec/acclaim/option/parser/regexp_spec.rb
@@ -117,7 +168,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
117
168
  version: '0'
118
169
  segments:
119
170
  - 0
120
- hash: 4033184433190617249
171
+ hash: 3293933185562874440
121
172
  required_rubygems_version: !ruby/object:Gem::Requirement
122
173
  none: false
123
174
  requirements:
@@ -126,7 +177,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
177
  version: '0'
127
178
  segments:
128
179
  - 0
129
- hash: 4033184433190617249
180
+ hash: 3293933185562874440
130
181
  requirements: []
131
182
  rubyforge_project:
132
183
  rubygems_version: 1.8.24
@@ -1,31 +0,0 @@
1
- module Acclaim
2
-
3
- # Acclaim's version.
4
- module Version
5
-
6
- # Major version.
7
- #
8
- # Increments denote backward-incompatible changes and additions.
9
- MAJOR = 0
10
-
11
- # Minor version.
12
- #
13
- # Increments denote backward-compatible changes and additions.
14
- MINOR = 3
15
-
16
- # Patch version.
17
- #
18
- # Increments denote changes in implementation.
19
- PATCH = 2
20
-
21
- # Build version.
22
- #
23
- # Used for pre-release versions.
24
- BUILD = nil
25
-
26
- # Complete version string, which is every individual version number joined
27
- # by a dot (<tt>'.'</tt>), in descending order of prescedence.
28
- STRING = [ MAJOR, MINOR, PATCH, BUILD ].compact.join '.'
29
-
30
- end
31
- end