acclaim 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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