acclaim 0.1.0 → 0.2.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.
@@ -2,7 +2,17 @@
2
2
 
3
3
  Command-line option parsing and command interface.
4
4
 
5
- ## Introduction
5
+ # Installation
6
+
7
+ Latest version:
8
+
9
+ gem install acclaim
10
+
11
+ From source:
12
+
13
+ git clone git://github.com/matheusmoreira/acclaim.git
14
+
15
+ # Introduction
6
16
 
7
17
  Acclaim makes it easy to describe commands and options for a command-line
8
18
  application in a structured manner. Commands are classes that inherit from
@@ -83,13 +83,13 @@ module Acclaim
83
83
  alias :when_called :action
84
84
 
85
85
  # Adds help subcommand and options to this command.
86
- def help(opts = {})
87
- Help.create(self, opts)
86
+ def help(*args)
87
+ Help.create(self, *args)
88
88
  end
89
89
 
90
90
  # Adds help subcommand and options to this command.
91
- def version(version_string, opts = {})
92
- Version.create(self, version_string, opts)
91
+ def version(*args)
92
+ Version.create(self, *args)
93
93
  end
94
94
 
95
95
  # Parses the argument array using this command's set of options.
@@ -145,16 +145,56 @@ module Acclaim
145
145
  # Finds the root of the command hierarchy.
146
146
  def root
147
147
  command = self
148
- command = command.superclass until command.root?
148
+ until command.root?
149
+ yield command if block_given?
150
+ command = command.superclass
151
+ end
152
+ yield command if block_given?
149
153
  command
150
154
  end
151
155
 
156
+ # Walks the command inheritance tree, yielding each command successively
157
+ # until the root command.
158
+ alias until_root root
159
+
160
+ # Return this command's parent commands.
161
+ def parents
162
+ Array.new.tap do |parents|
163
+ until_root do |command|
164
+ parents << command
165
+ end
166
+ end
167
+ end
168
+
169
+ # Computes the full command line of this command, which takes parent
170
+ # commands into account.
171
+ #
172
+ # class Command < Acclaim::Command
173
+ # class Subcommand < Command
174
+ # class Subcommand2 < Subcommand
175
+ # end
176
+ # end
177
+ # end
178
+ #
179
+ # Command::Subcommand::Subcommand2.full_line
180
+ # => "subcommand subcommand2"
181
+ #
182
+ # Command::Subcommand::Subcommand2.full_line include_root: true
183
+ # => "command subcommand subcommand2"
184
+ def full_line(*args)
185
+ options = args.extract_ribbon!
186
+ parents.tap do |parents|
187
+ parents.pop unless options.include_root?
188
+ end.reverse.map(&:line).join ' '
189
+ end
190
+
152
191
  private
153
192
 
154
193
  # Handles special options such as <tt>--help</tt> or <tt>--version</tt>.
155
194
  def handle_special_options!(opts, args)
156
195
  const_get(:Help).execute opts, args if opts.acclaim_help?
157
196
  const_get(:Version).execute opts, args if opts.acclaim_version?
197
+ # TODO: possibly rescue a NameError and warn user
158
198
  end
159
199
 
160
200
  # Deletes all argument separators in the given argument array.
@@ -1,4 +1,5 @@
1
1
  require 'acclaim/command/help/template'
2
+ require 'ribbon/core_ext/array'
2
3
 
3
4
  module Acclaim
4
5
  class Command
@@ -6,47 +7,67 @@ module Acclaim
6
7
  # Module which adds help support to a command.
7
8
  module Help
8
9
 
9
- # Adds a special help option to the given +command+.
10
- #
11
- # The last argument is an option +Hash+, which accepts the following
12
- # options:
13
- #
14
- # [:switches] The switches used when creating the help option.
15
- def self.add_options_to!(command, opts = {})
16
- switches = opts.fetch :switches, %w(-h --help)
17
- description = opts.fetch :description, 'Show usage information and exit.'
18
- command.option :acclaim_help, *switches, description
19
- end
10
+ # The class methods.
11
+ class << self
20
12
 
21
- private_class_method :add_options_to!
22
-
23
- # Creates a help subcommand that inherits from the given +base+ command
24
- # and stores the class in the +Help+ constant of +base+. When called, the
25
- # command displays a help screen including information for all commands
26
- # and then exits.
27
- #
28
- # The last argument is an option +Hash+, which accepts the following
29
- # options:
30
- #
31
- # [:options] If +true+, will add a help option to the +base+ command.
32
- # [:switches] The switches used when creating the help option.
33
- def self.create(base, opts = {})
34
- if opts.fetch :options, true
35
- add_options_to! base, opts
36
- end
37
- base.const_set(:Help, Class.new(base)).tap do |help_command|
38
- help_command.when_called do |options, args|
39
- display_help_for base.root
40
- exit
13
+ # Creates a help subcommand that inherits from the given +base+ command
14
+ # and stores the class in the +Help+ constant of +base+. When called,
15
+ # the command displays a help screen including information for all
16
+ # commands and then exits.
17
+ #
18
+ # The last argument can be a configuration hash, which accepts the
19
+ # following options:
20
+ #
21
+ # [:options] If +true+, will add a help option to the +base+
22
+ # command.
23
+ # [:switches] The switches used when creating the help option.
24
+ # [:exit] If +true+, +exit+ will be called when the command is
25
+ # done.
26
+ # [:include_root] Includes the root command when displaying a command's
27
+ # usage.
28
+ def create(*args)
29
+ opts, base = args.extract_ribbon!, args.shift
30
+ add_options_to! base, opts if opts.options? true
31
+ base.const_set(:Help, Class.new(base)).tap do |help_command|
32
+ help_command.when_called do |options, args|
33
+ # TODO: implement a way to specify a command to the help option
34
+ # and command.
35
+ # display_for options.command || args.pop
36
+ display_for base.root, opts
37
+ exit if opts.exit? true
38
+ end
41
39
  end
42
40
  end
43
- end
44
41
 
45
- # Displays a very simple help screen for the given command and all its
46
- # subcommands.
47
- def self.display_help_for(command)
48
- puts Template.for(command) if command.options.any?
49
- command.subcommands.each { |subcommand| display_help_for subcommand }
42
+ # Displays a very simple help screen for the given command and all its
43
+ # subcommands.
44
+ #
45
+ # The last argument can be a configuration hash, which accepts the
46
+ # following options:
47
+ #
48
+ # [:include_root] Includes the root command when displaying a command's
49
+ # usage.
50
+ def display_for(*args)
51
+ options, command = args.extract_ribbon!, args.shift
52
+ puts Template.for(command, options) if command.options.any?
53
+ command.subcommands.each { |subcommand| display_for(subcommand, options) }
54
+ end
55
+
56
+ private
57
+
58
+ # Adds a special help option to the given +command+.
59
+ #
60
+ # The last argument can be a configuration hash, which accepts the
61
+ # following options:
62
+ #
63
+ # [:switches] The switches used when creating the help option.
64
+ def add_options_to!(*args)
65
+ opts, command = args.extract_ribbon!, args.shift
66
+ switches = opts.switches? %w(-h --help)
67
+ description = opts.description? 'Show usage information and exit.'
68
+ command.option :acclaim_help, *switches, description
69
+ end
70
+
50
71
  end
51
72
 
52
73
  end
@@ -1,4 +1,5 @@
1
1
  require 'erb'
2
+ require 'ribbon/core_ext/array'
2
3
 
3
4
  module Acclaim
4
5
  class Command
@@ -7,20 +8,38 @@ module Acclaim
7
8
  # Manages help templates.
8
9
  module Template
9
10
 
10
- # Loads an ERB template file from the
11
- # +lib/acclaim/command/help/template+ folder and instantiates a new ERB
12
- # instance with its contents.
13
- def self.load(template)
14
- filename = File.join File.dirname(__FILE__), 'template', template
15
- ERB.new File.read(filename), nil, '%<>'
16
- end
11
+ # The class methods.
12
+ class << self
13
+
14
+ # Returns the +template+ folder relative to this directory.
15
+ def folder
16
+ File.join File.dirname(__FILE__), 'template'
17
+ end
18
+
19
+ # Loads the contents of a template file from the template #folder.
20
+ def load(template_file)
21
+ File.read File.join(folder, template_file)
22
+ end
23
+
24
+ # Creates a new ERB instance with the contents of +template+.
25
+ def create_from(template_file)
26
+ ERB.new load(template_file), nil, '%<>'
27
+ end
28
+
29
+ # Computes the result of the template +file+ using the +command+'s
30
+ # binding.
31
+ def for(*args)
32
+ template_options, command = args.extract_ribbon!, args.shift
33
+ template = create_from template_options.file?('command.erb')
34
+ b = command.instance_eval { binding }
35
+ # Since blocks are closures, the binding has access to the
36
+ # template_options ribbon:
37
+ #
38
+ # p b.eval 'template_options'
39
+ # => {}
40
+ template.result b
41
+ end
17
42
 
18
- # Computes the result of the template +file+ using the +command+'s
19
- # binding.
20
- def self.for(command, file = 'command.erb')
21
- template = self.load file
22
- b = command.instance_eval { binding }
23
- template.result b
24
43
  end
25
44
 
26
45
  end
@@ -1,8 +1,9 @@
1
1
  <% unless root? or options.empty? %>
2
- Command '<%= line %>':
2
+ Command '<%= full_line include_root: template_options.include_root? %>':
3
3
  <% end %>
4
4
 
5
5
  <% options.each do |option| %>
6
- <%= option.names.join ', ' %> <%= option.description %>
6
+ <%= option.names.join ', ' %>
7
+ <%= option.description %>
7
8
  <% end %>
8
9
 
@@ -1,43 +1,53 @@
1
+ require 'ribbon/core_ext/array'
2
+
1
3
  module Acclaim
2
4
  class Command
3
5
 
4
6
  # Module which adds version query support to a command.
5
7
  module Version
6
8
 
7
- # Adds a special version option to the given +command+.
8
- #
9
- # The last argument is an option +Hash+, which accepts the following
10
- # options:
11
- #
12
- # [:switches] The switches used when creating the version option.
13
- def self.add_options_to!(command, opts = {})
14
- switches = opts.fetch :switches, %w(-v --version)
15
- description = opts.fetch :description, 'Show version and exit.'
16
- command.option :acclaim_version, *switches, description
17
- end
9
+ # The class methods.
10
+ class << self
18
11
 
19
- private_class_method :add_options_to!
20
-
21
- # Creates a <tt>version</tt> subcommand that inherits from the given
22
- # +base+ command and stores the class in the +Version+ constant of +base+.
23
- # When called, the command displays the +version_string+ of the program
24
- # and then exits.
25
- #
26
- # The last argument is an option +Hash+, which accepts the following
27
- # options:
28
- #
29
- # [:options] If +true+, will add a version option to the +base+ command.
30
- # [:switches] The switches used when creating the version option.
31
- def self.create(base, version_string, opts = {})
32
- if opts.fetch :options, true
33
- add_options_to! base, opts
34
- end
35
- base.const_set(:Version, Class.new(base)).tap do |version_command|
36
- version_command.when_called do |options, args|
37
- puts version_string
38
- exit
12
+ # Creates a <tt>version</tt> subcommand that inherits from the given
13
+ # +base+ command and stores the class in the +Version+ constant of
14
+ # +base+. When called, the command displays the +version_string+ of the
15
+ # program and then exits.
16
+ #
17
+ # The last argument can be a configuration hash, which accepts the
18
+ # following options:
19
+ #
20
+ # [:options] If +true+, will add a version option to the +base+
21
+ # command.
22
+ # [:switches] The switches used when creating the version option.
23
+ # [:exit] If +true+, +exit+ will be called when the command is
24
+ # done.
25
+ def create(*args)
26
+ opts, base, version_string = args.extract_ribbon!, args.shift, args.shift
27
+ add_options_to! base, opts if opts.options? true
28
+ base.const_set(:Version, Class.new(base)).tap do |version_command|
29
+ version_command.when_called do |options, args|
30
+ puts version_string
31
+ exit if opts.exit? true
32
+ end
39
33
  end
40
34
  end
35
+
36
+ private
37
+
38
+ # Adds a special version option to the given +command+.
39
+ #
40
+ # The last argument can be a configuration hash, which accepts the
41
+ # following options:
42
+ #
43
+ # [:switches] The switches used when creating the version option.
44
+ def add_options_to!(*args)
45
+ opts, command = args.extract_ribbon!, args.shift
46
+ switches = opts.switches? %w(-v --version)
47
+ description = opts.description? 'Show version and exit.'
48
+ command.option :acclaim_version, *switches, description
49
+ end
50
+
41
51
  end
42
52
 
43
53
  end
@@ -61,13 +61,13 @@ module Acclaim
61
61
  # args = %w(-F log.txt --verbose arg1 arg2)
62
62
  # options = []
63
63
  # options << Option.new(:file, '-F', arity: [1,0], required: true)
64
- # options << Option.new(:verbose, '--verbose')
64
+ # options << Option.new(:verbose)
65
65
  #
66
66
  # Option::Parser.new(args, options).parse!
67
- # => {Ribbon file: "log.txt", verbose: true}
67
+ # => {file: "log.txt", verbose: true}
68
68
  #
69
69
  # args
70
- # => ["arg1", "arg2"]
70
+ # => ["arg1", "arg2"]
71
71
  def parse!
72
72
  preprocess_argv!
73
73
  parse_values!
@@ -88,8 +88,8 @@ module Acclaim
88
88
  def split_multiple_short_options!
89
89
  argv.find_all { |arg| arg =~ MULTIPLE_SHORT_SWITCHES }.each do |multiples|
90
90
  multiples_index = argv.index multiples
91
- argv.delete multiples
92
- switches = multiples.sub!(/^-/, '').split(//).each { |letter| letter.prepend '-' }
91
+ argv.delete_at multiples_index
92
+ switches = multiples.sub(/^-/, '').split(//).each { |letter| letter.prepend '-' }
93
93
  argv.insert multiples_index, *switches
94
94
  end
95
95
  end
@@ -103,7 +103,7 @@ module Acclaim
103
103
  def normalize_parameters!
104
104
  argv.find_all { |arg| arg =~ SWITCH_PARAM_EQUALS }.each do |switch|
105
105
  switch_index = argv.index switch
106
- argv.delete switch
106
+ argv.delete_at switch_index
107
107
  switch, params = switch.split /\=/
108
108
  params = (params or '').split /,/
109
109
  argv.insert switch_index, *[ switch, *params ]
@@ -113,24 +113,24 @@ module Acclaim
113
113
  # Parses the options and their arguments, associating that information
114
114
  # with a Ribbon instance.
115
115
  def parse_values!
116
- ribbon = Ribbon.new
116
+ values = Ribbon.wrap
117
117
  options.each do |option|
118
118
  key = option.key
119
- ribbon[key] = option.default unless Ribbon[ribbon].has_key? key
119
+ values[key] = option.default unless values.has_key? key
120
120
  switches = argv.find_all { |switch| option =~ switch }
121
121
  Error.raise_missing_required option if option.required? and switches.empty?
122
122
  Error.raise_multiple option if option.on_multiple == :raise and switches.count > 1
123
123
  switches.each do |switch|
124
124
  if option.flag?
125
- found_boolean option, ribbon
125
+ found_boolean option, values.ribbon
126
126
  argv.delete_at argv.index(switch)
127
127
  else
128
128
  params = extract_parameters_of! option, switch
129
- found_params_for option, params, ribbon
129
+ found_params_for option, params, values.ribbon
130
130
  end
131
131
  end
132
132
  end
133
- ribbon
133
+ values.ribbon
134
134
  end
135
135
 
136
136
  # Finds the +switch+ in #argv and scans the next +option.arity.total+
@@ -179,10 +179,10 @@ module Acclaim
179
179
  params = option.convert_parameters *params
180
180
  if handler = option.handler then handler.call ribbon, params
181
181
  else
182
- key = option.key.to_sym
182
+ key = option.key
183
183
  value = option.arity.total == 1 ? params.first : params
184
184
  value = [*ribbon[key], *value] if option.on_multiple == :append
185
- ribbon[option.key.to_sym] = value unless params.empty?
185
+ ribbon[key] = value unless params.empty?
186
186
  end
187
187
  end
188
188
 
@@ -191,7 +191,7 @@ module Acclaim
191
191
  # be set to <tt>true</tt>.
192
192
  def found_boolean(option, ribbon = Ribbon.new)
193
193
  if handler = option.handler then handler.call ribbon
194
- else ribbon[option.key.to_sym] = true end
194
+ else ribbon[option.key] = true end
195
195
  end
196
196
 
197
197
  end
@@ -12,19 +12,19 @@ module Acclaim
12
12
  # <tt>'-mult'</tt> should match MULTIPLE_SHORT_SWITCHES, and will be
13
13
  # split into <tt>%w(-m -u -l -t)</tt>, which in turn should match this
14
14
  # regular expression.
15
- SHORT_SWITCH = /\A-\w\Z/
15
+ SHORT_SWITCH = /\A-[a-zA-Z_]\Z/.freeze
16
16
 
17
17
  # Regular expression for a long option switch.
18
18
  #
19
19
  # Examples: <tt>--long; --no-feature; --with_underscore;
20
20
  # --_private-option; --1-1</tt>
21
- LONG_SWITCH = /\A--[\w\d]+(-[\w\d]+)*\Z/
21
+ LONG_SWITCH = /\A--\w+(-\w+)*\Z/.freeze
22
22
 
23
23
  # Regular expression for multiple short options in a single "short"
24
24
  # switch.
25
25
  #
26
26
  # Examples: <tt>-xvf; -abc; -de_f</tt>
27
- MULTIPLE_SHORT_SWITCHES = /\A-\w{2,}\Z/
27
+ MULTIPLE_SHORT_SWITCHES = /\A-[a-zA-Z_]{2,}\Z/.freeze
28
28
 
29
29
  # Regular expression for a long switch connected to its parameters with
30
30
  # an equal sign. Multiple parameters are be separated by commas.
@@ -40,16 +40,17 @@ module Acclaim
40
40
  # <tt>'--weird=,PARAM2'</tt> will become
41
41
  # <tt>['--weird', '', 'PARAM2']</tt> when it is split up. What to make
42
42
  # of those isn't a decision for a preprocessor.
43
- SWITCH_PARAM_EQUALS = /\A--[\w\d]+(-[\w\d]+)*=(,*[\w\d]*)*\Z/
43
+ SWITCH_PARAM_EQUALS = /\A--\w+(-\w+)*=(,*\w*)*\Z/.freeze
44
44
 
45
45
  # Regular expression for any kind of option switch.
46
- SWITCH = /(#{SHORT_SWITCH})|(#{LONG_SWITCH})|(#{MULTIPLE_SHORT_SWITCHES})|(#{SWITCH_PARAM_EQUALS})/
46
+ SWITCH = ::Regexp.union(SHORT_SWITCH, LONG_SWITCH,
47
+ MULTIPLE_SHORT_SWITCHES, SWITCH_PARAM_EQUALS).freeze
47
48
 
48
49
  # Regular expression for the string that separates options and their
49
50
  # parameters from arguments like filenames.
50
51
  #
51
52
  # Examples: <tt>--; ---</tt>
52
- ARGUMENT_SEPARATOR = /\A-{2,}\Z/
53
+ ARGUMENT_SEPARATOR = /\A-{2,}\Z/.freeze
53
54
 
54
55
  end
55
56
 
@@ -11,7 +11,7 @@ module Acclaim
11
11
  # Minor version.
12
12
  #
13
13
  # Increments denote backward-compatible changes and additions.
14
- MINOR = 1
14
+ MINOR = 2
15
15
 
16
16
  # Patch version.
17
17
  #
@@ -0,0 +1,238 @@
1
+ require 'acclaim/option/parser/regexp'
2
+
3
+ describe Acclaim::Option::Parser::Regexp do
4
+
5
+ # Generate one helper for each constant in the described module.
6
+ described_class.constants.each do |constant|
7
+ let(constant.to_s.downcase.to_sym) { described_class.const_get constant }
8
+ end
9
+
10
+ let(:short_option) { '-o' }
11
+ let(:long_option) { '--option' }
12
+ let(:multiple_short_options) { '-option' }
13
+ let(:long_option_equals_sign) { '--option=' }
14
+ let(:long_option_equals_sign_value) { '--option=VALUE' }
15
+ let(:long_option_equals_sign_values) { '--option=VALUE1,VALUE2,VALUE3' }
16
+ let(:long_option_equals_sign_comma_values) { '--option=,VALUE2,VALUE3' }
17
+ let(:long_option_equals_sign_empty_commas) { '--option=,,' }
18
+ let(:double_argument_separator) { '--' }
19
+ let(:triple_argument_separator) { '---' }
20
+ let(:long_option_with_separators) { '--my-option' }
21
+ let(:short_option_underscore) { '-_' }
22
+ let(:long_option_underscore) { '--_' }
23
+ let(:multiple_short_options_underscore) { '-many_options' }
24
+ let(:long_option_equals_sign_underscore) { '--my_option=' }
25
+ let(:short_option_with_numbers) { '-5' }
26
+ let(:multiple_short_options_with_numbers) { '-1234567890' }
27
+ let(:long_option_equals_sign_and_numbers) { '--1234567890=' }
28
+ let(:long_option_with_numbers) { '--1234567890' }
29
+
30
+ describe 'SHORT_SWITCH' do
31
+ it 'should match short options' do
32
+ short_option.should match(short_switch)
33
+ end
34
+
35
+ it 'should not match long options' do
36
+ long_option.should_not match(short_switch)
37
+ end
38
+
39
+ it 'should not match multiple short options' do
40
+ multiple_short_options.should_not match(short_switch)
41
+ end
42
+
43
+ it 'should not match long options with an equals sign' do
44
+ long_option_equals_sign.should_not match(short_switch)
45
+ end
46
+
47
+ it 'should not match a two-dash argument separator' do
48
+ double_argument_separator.should_not match(short_switch)
49
+ end
50
+
51
+ it 'should not match a three-dash argument separator' do
52
+ triple_argument_separator.should_not match(short_switch)
53
+ end
54
+
55
+ it 'should consider underscores as valid characters' do
56
+ short_option_underscore.should match(short_switch)
57
+ end
58
+
59
+ it 'should not consider digits as valid characters' do
60
+ short_option_with_numbers.should_not match(short_switch)
61
+ end
62
+ end
63
+
64
+ describe 'LONG_SWITCH' do
65
+ it 'should not match short options' do
66
+ short_option.should_not match(long_switch)
67
+ end
68
+
69
+ it 'should match long options' do
70
+ long_option.should match(long_switch)
71
+ end
72
+
73
+ it 'should not match multiple short options' do
74
+ multiple_short_options.should_not match(long_switch)
75
+ end
76
+
77
+ it 'should not match long options with an equals sign' do
78
+ long_option_equals_sign.should_not match(long_switch)
79
+ end
80
+
81
+ it 'should not match a two-dash argument separator' do
82
+ double_argument_separator.should_not match(long_switch)
83
+ end
84
+
85
+ it 'should not match a three-dash argument separator' do
86
+ triple_argument_separator.should_not match(long_switch)
87
+ end
88
+
89
+ it 'should consider underscores as valid characters' do
90
+ long_option_underscore.should match(long_switch)
91
+ end
92
+
93
+ it 'should consider digits as valid characters' do
94
+ long_option_with_numbers.should match(long_switch)
95
+ end
96
+
97
+ it 'should allow dashes as word separators' do
98
+ long_option_with_separators.should match(long_switch)
99
+ end
100
+ end
101
+
102
+ describe 'MULTIPLE_SHORT_SWITCHES' do
103
+ it 'should not match short options' do
104
+ short_option.should_not match(multiple_short_switches)
105
+ end
106
+
107
+ it 'should not match long options' do
108
+ long_option.should_not match(multiple_short_switches)
109
+ end
110
+
111
+ it 'should match multiple short options' do
112
+ multiple_short_options.should match(multiple_short_switches)
113
+ end
114
+
115
+ it 'should not match long options with an equals sign' do
116
+ long_option_equals_sign.should_not match(multiple_short_switches)
117
+ end
118
+
119
+ it 'should not match a two-dash argument separator' do
120
+ double_argument_separator.should_not match(multiple_short_switches)
121
+ end
122
+
123
+ it 'should not match a three-dash argument separator' do
124
+ triple_argument_separator.should_not match(multiple_short_switches)
125
+ end
126
+
127
+ it 'should consider underscores as valid characters' do
128
+ multiple_short_options_underscore.should match(multiple_short_switches)
129
+ end
130
+
131
+ it 'should not consider digits as valid characters' do
132
+ multiple_short_options_with_numbers.should_not match(multiple_short_switches)
133
+ end
134
+ end
135
+
136
+ describe 'SWITCH_PARAM_EQUALS' do
137
+ it 'should not match short options' do
138
+ short_option.should_not match(switch_param_equals)
139
+ end
140
+
141
+ it 'should not match long options' do
142
+ long_option.should_not match(switch_param_equals)
143
+ end
144
+
145
+ it 'should not match multiple short options' do
146
+ multiple_short_options.should_not match(switch_param_equals)
147
+ end
148
+
149
+ it 'should match long options with an equals sign' do
150
+ long_option_equals_sign.should match(switch_param_equals)
151
+ end
152
+
153
+ it 'should not match a two-dash argument separator' do
154
+ double_argument_separator.should_not match(switch_param_equals)
155
+ end
156
+
157
+ it 'should not match a three-dash argument separator' do
158
+ triple_argument_separator.should_not match(switch_param_equals)
159
+ end
160
+
161
+ it 'should consider underscores as valid characters' do
162
+ long_option_equals_sign_underscore.should match(switch_param_equals)
163
+ end
164
+
165
+ it 'should consider digits as valid characters' do
166
+ long_option_equals_sign_and_numbers.should match(switch_param_equals)
167
+ end
168
+
169
+ it 'should match a long option with an equals sign followed by a value' do
170
+ long_option_equals_sign_value.should match(switch_param_equals)
171
+ end
172
+
173
+ it 'should match a long option with an equals sign followed by comma-separated values' do
174
+ long_option_equals_sign_values.should match(switch_param_equals)
175
+ end
176
+
177
+ it 'should match a long option with an equals sign with a comma before the values' do
178
+ long_option_equals_sign_comma_values.should match(switch_param_equals)
179
+ end
180
+
181
+ it 'should match a long option with an equals sign followed by commas' do
182
+ long_option_equals_sign_empty_commas.should match(switch_param_equals)
183
+ end
184
+ end
185
+
186
+ describe 'SWITCH' do
187
+ it 'should match short options' do
188
+ short_option.should match(switch)
189
+ end
190
+
191
+ it 'should match long options' do
192
+ long_option.should match(switch)
193
+ end
194
+
195
+ it 'should match multiple short options' do
196
+ multiple_short_options.should match(switch)
197
+ end
198
+
199
+ it 'should match long options with an equals sign' do
200
+ long_option_equals_sign.should match(switch)
201
+ end
202
+
203
+ it 'should not match a two-dash argument separator' do
204
+ double_argument_separator.should_not match(switch)
205
+ end
206
+
207
+ it 'should not match a three-dash argument separator' do
208
+ triple_argument_separator.should_not match(switch)
209
+ end
210
+ end
211
+
212
+ describe 'ARGUMENT_SEPARATOR' do
213
+ it 'should not match short options' do
214
+ short_option.should_not match(argument_separator)
215
+ end
216
+
217
+ it 'should not match long options' do
218
+ long_option.should_not match(argument_separator)
219
+ end
220
+
221
+ it 'should not match multiple short options' do
222
+ multiple_short_options.should_not match(argument_separator)
223
+ end
224
+
225
+ it 'should not match long options with an equals sign' do
226
+ long_option_equals_sign.should_not match(argument_separator)
227
+ end
228
+
229
+ it 'should match a two-dash argument separator' do
230
+ double_argument_separator.should match(argument_separator)
231
+ end
232
+
233
+ it 'should match a three-dash argument separator' do
234
+ triple_argument_separator.should match(argument_separator)
235
+ end
236
+ end
237
+
238
+ end
@@ -18,14 +18,14 @@ describe Acclaim::Option::Parser do
18
18
  end
19
19
 
20
20
  context 'when given a long switch with multiple parameters separated by an equals sign' do
21
- let!(:args) { %w(--files FILE1 FILE2 FILE3) }
21
+ let!(:args) { %w(--files=FILE1,FILE2,FILE3) }
22
22
 
23
23
  it 'should separate the switch and the parameters' do
24
24
  subject.parse!
25
25
  args.should == %w(--files FILE1 FILE2 FILE3)
26
26
  end
27
27
 
28
- context 'but the parameter list starts with a comma' do
28
+ context 'but without a first parameter' do
29
29
  let!(:args) { %w(--files=,FILE2,FILE3) }
30
30
 
31
31
  it 'should treat the first parameter as if it was an empty string' do
@@ -35,7 +35,7 @@ describe Acclaim::Option::Parser do
35
35
  end
36
36
  end
37
37
 
38
- context 'when given a long siwtch with an equals sign' do
38
+ context 'when given a long switch with an equals sign' do
39
39
  context 'but no parameters' do
40
40
  let!(:args) { %w(--none=) }
41
41
 
@@ -164,7 +164,7 @@ describe Acclaim::Option do
164
164
 
165
165
  context 'when the option was initialized with Date as its type' do
166
166
  let(:type) { Date }
167
- let(:date) { Date.today }
167
+ let(:date) { type.today }
168
168
  let(:params) { [date.to_s] }
169
169
 
170
170
  it 'should convert the parameters to dates' do
@@ -174,7 +174,7 @@ describe Acclaim::Option do
174
174
 
175
175
  context 'when the option was initialized with DateTime as its type' do
176
176
  let(:type) { DateTime }
177
- let(:date_time) { DateTime.now }
177
+ let(:date_time) { type.parse type.now.to_s }
178
178
  let(:params) { [date_time.to_s] }
179
179
 
180
180
  it 'should convert the parameters to dates/times' do
@@ -184,7 +184,7 @@ describe Acclaim::Option do
184
184
 
185
185
  context 'when the option was initialized with Time as its type' do
186
186
  let(:type) { Time }
187
- let(:time) { Time.now }
187
+ let(:time) { type.parse type.now.to_s }
188
188
  let(:params) { [time.to_s] }
189
189
 
190
190
  it 'should convert the parameters to times' do
@@ -194,7 +194,7 @@ describe Acclaim::Option do
194
194
 
195
195
  context 'when the option was initialized with URI as its type' do
196
196
  let(:type) { URI }
197
- let(:uri) { URI.parse 'https://github.com/matheusmoreira/acclaim' }
197
+ let(:uri) { type.parse 'https://github.com/matheusmoreira/acclaim' }
198
198
  let(:params) { [uri.to_s] }
199
199
 
200
200
  it 'should convert the parameters to URIs' 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.1.0
4
+ version: 0.2.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-16 00:00:00.000000000 Z
12
+ date: 2012-01-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ribbon
16
- requirement: &22189080 !ruby/object:Gem::Requirement
16
+ requirement: &20746840 !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: *22189080
24
+ version_requirements: *20746840
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &22188500 !ruby/object:Gem::Requirement
27
+ requirement: &20745700 !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: *22188500
35
+ version_requirements: *20745700
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rookie
38
- requirement: &22188080 !ruby/object:Gem::Requirement
38
+ requirement: &20744980 !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: *22188080
46
+ version_requirements: *20744980
47
47
  description: Command-line option parser and command interface.
48
48
  email: matheus.a.m.moreira@gmail.com
49
49
  executables: []
@@ -78,6 +78,7 @@ files:
78
78
  - lib/acclaim/version.rb
79
79
  - spec/acclaim/command_spec.rb
80
80
  - spec/acclaim/option/arity_spec.rb
81
+ - spec/acclaim/option/parser/regexp_spec.rb
81
82
  - spec/acclaim/option/parser_spec.rb
82
83
  - spec/acclaim/option_spec.rb
83
84
  homepage: https://github.com/matheusmoreira/acclaim
@@ -94,7 +95,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
94
95
  version: '0'
95
96
  segments:
96
97
  - 0
97
- hash: -901301498998529047
98
+ hash: -1211294602011748853
98
99
  required_rubygems_version: !ruby/object:Gem::Requirement
99
100
  none: false
100
101
  requirements:
@@ -103,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
104
  version: '0'
104
105
  segments:
105
106
  - 0
106
- hash: -901301498998529047
107
+ hash: -1211294602011748853
107
108
  requirements: []
108
109
  rubyforge_project:
109
110
  rubygems_version: 1.8.10