acclaim 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.markdown CHANGED
@@ -2,4 +2,184 @@
2
2
 
3
3
  Command-line option parsing and command interface.
4
4
 
5
- Extracted from [Safeguard](https://github.com/matheusmoreira/safeguard).
5
+ ## Introduction
6
+
7
+ Acclaim makes it easy to describe commands and options for a command-line
8
+ application in a structured manner. Commands are classes that inherit from
9
+ `Acclaim::Command`:
10
+
11
+ require 'acclaim'
12
+
13
+ module App
14
+ class Command < Acclaim::Command
15
+ option :verbose, '-v', '--verbose'
16
+
17
+ when_called do |options, args|
18
+ puts 'Hello World!'
19
+ puts args.join ', ' if options.verbose? and args.any?
20
+ end
21
+ end
22
+ end
23
+
24
+ $ app --verbose a b c
25
+ Hello World!
26
+ a, b, c
27
+
28
+ Every command has a set of options and block that is executed when it is called.
29
+ The options are parsed into an object and passed to the command's block along
30
+ with the remaining command line arguments. The first argument of the `option`
31
+ method is the key used to store the value of the option, the other strings are
32
+ either switches or a description:
33
+
34
+ option :verbose, '-v', '--verbose', '--run-verbosely', 'Run verbosely.'
35
+
36
+ Acclaim provides especial `help` and `version` commands that may be added to
37
+ your program. The help command will automatically generate and print a help page
38
+ for all commands and options. The version command will print your program's
39
+ version and exit. To use them:
40
+
41
+ class App::Command
42
+ help
43
+ version '1.2.3'
44
+ end
45
+
46
+ $ app -h
47
+ $ app --help
48
+ $ app help
49
+
50
+ -v, --verbose, --run-verbosely Run verbosely.
51
+ -h, --help Show usage information and exit.
52
+ -v, --version Show version and exit.
53
+
54
+ $ app -v
55
+ $ app --version
56
+ $ app version
57
+ 1.2.3
58
+
59
+ Both methods can take a hash as the last parameter, which accepts the same
60
+ configurations. If you don't want the options, or if you want to specify a
61
+ different set of switches or a different description, you can write something
62
+ like:
63
+
64
+ help options: false
65
+ version '1.2.3', switches: %w(--version),
66
+ description: "Shows this program's version."
67
+
68
+ ### Subcommands
69
+
70
+ Essentially, a command given to another command. Subcommands benefit from all
71
+ the option processing done by its parents. To create one, you simply inherit
72
+ from an existing command:
73
+
74
+ class App::Command::Do < App::Command
75
+
76
+ # option is aliased as opt
77
+ opt :what, '--what', 'What to do.', default: 'something', arity: [1, 0]
78
+
79
+ # when_called is aliased as action
80
+ action do |options, args|
81
+ puts "Doing #{options.what} with #{args.join ', '}"
82
+ end
83
+ end
84
+
85
+ $ app do x, y, z
86
+ Doing something with x, y, z
87
+
88
+ $ app do --what x, y, z
89
+ Doing x with y, z
90
+
91
+ Options may also take an Hash as the last parameter. Among the things that can
92
+ be configured is the default value for the option and its arity. The default
93
+ value is `nil` by default and is used if the option is not given. The arity of
94
+ the option represents the minimum number of arguments it __must__ take and the
95
+ number of optional arguments it __may__ take. It is specified as an array in the
96
+ form `[minimum, optional]`. Options that take zero arguments, which is the
97
+ default, are flags.
98
+
99
+ So, options can take from zero to an unlimited number of arguments, right?
100
+
101
+ class App::Command::Do < App::Command
102
+
103
+ # Negative number of optional arguments denote unlimited argument count
104
+ opt :what, '--what', default: 'something', arity: [0, -1]
105
+
106
+ action do |options, args|
107
+ what = (options.what.join ', ' rescue options.what)
108
+ subjects = args.join ', '
109
+ puts "Doing #{what} with #{subjects}"
110
+ end
111
+
112
+ $ app do --what x y z
113
+ Doing x, y, z with
114
+
115
+ Now, our option is eating up all the arguments in the command line! Hope is not
116
+ lost, however. Even though the list of arguments may be unlimited, parsing will
117
+ still stop if either another switch or an argument separator is encountered. An
118
+ argument separator is a group of two or more dashes:
119
+
120
+ $ app do --what w x -- y z
121
+ Doing w, x with y, z
122
+
123
+ An important thing to understand is that options are not parsed all at once;
124
+ first, the main command's options are parsed, then the remaining arguments are
125
+ searched for subcommands. If one is found, its options are parsed, the remaining
126
+ arguments are searched and so on. If a subcommand can't be found, the most
127
+ specific command found is executed.
128
+
129
+ Options are deleted from the command line as they are parsed, so the following
130
+ will not work:
131
+
132
+ $ app do --what w x --verbose y z
133
+ Doing w, x, y, z with
134
+
135
+ This happens because `--verbose` is an option of the main command. Since it will
136
+ be parsed and deleted from the argument array, when `do` gets its turn it will
137
+ be parsing the `%w(--what w x y z)` array.
138
+
139
+ ### Option Type Handlers
140
+
141
+ Arguments given to options are by default strings. To make life easier, you may
142
+ specify the type of the arguments by passing a class among the arguments:
143
+
144
+ class App::Command::Do
145
+ opt :when, '--when', 'When to do it.', Date,
146
+ default: Date.today, arity: [1,0]
147
+
148
+ action do |options, args|
149
+ what = (options.what.join ', ' rescue options.what)
150
+ subjects = args.join ', '
151
+ date = options.when
152
+ puts 'Merry Christmas!' if date.month == 12 and date.day == 25
153
+ date = date.strftime '%m/%d/%Y'
154
+ puts "Doing #{what} with #{subjects} on #{date}"
155
+ end
156
+ end
157
+
158
+ $ app do --what w x --when 2011-12-25 y z
159
+ Merry Christmas!
160
+ Doing w, x with y, z on 12/25/2011
161
+
162
+ There are type handlers included for `Date`s, `Time`s, `DateTime`s, `URI`s and
163
+ `String`s, but if you need more you can always write your own:
164
+
165
+ Acclaim::Option::Type.add_handler_for(Symbol) { |str| str.to_sym }
166
+
167
+ class App::Command::Handle < App::Command
168
+ opt :syms, '--symbol', '--symbols', Symbol, arity: [1,-1], required: true
169
+
170
+ when_called do |options, args|
171
+ options.syms.each { |sym| puts "#{sym.class} => #{sym.inspect}" }
172
+ end
173
+ end
174
+
175
+ $ app handle --symbols a s d
176
+ Symbol => :a
177
+ Symbol => :s
178
+ Symbol => :d
179
+
180
+ `add_handler_for` takes a class and a block, which will be called for every
181
+ argument of that class that must be parsed.
182
+
183
+ ---
184
+
185
+ Originally extracted from [Safeguard](https://github.com/matheusmoreira/safeguard).
data/lib/acclaim.rb CHANGED
@@ -1,11 +1,11 @@
1
+ # Acclaim is a command line option parsing and command interface for Ruby.
2
+ module Acclaim
3
+ end
4
+
1
5
  %w(
2
6
 
3
7
  command
4
8
  option
5
- option/arity
6
- option/parser
7
- option/parser/regexp
8
- option/values
9
9
  version
10
10
 
11
11
  ).each { |file| require file.prepend 'acclaim/' }
@@ -81,12 +81,12 @@ module Acclaim
81
81
 
82
82
  # Adds help subcommand and options to this command.
83
83
  def help(opts = {})
84
- subcommands << Help.create(self, opts)
84
+ Help.create(self, opts)
85
85
  end
86
86
 
87
87
  # Adds help subcommand and options to this command.
88
88
  def version(version_string, opts = {})
89
- subcommands << Version.create(self, version_string, opts)
89
+ Version.create(self, version_string, opts)
90
90
  end
91
91
 
92
92
  # Parses the argument array using this command's set of options.
@@ -113,6 +113,7 @@ module Acclaim
113
113
  args.delete subcommand.line
114
114
  subcommand.invoke(opts, args)
115
115
  else
116
+ args.delete_if { |arg| arg =~ Option::Parser::Regexp::ARGUMENT_SEPARATOR }
116
117
  execute(opts, args)
117
118
  end
118
119
  end
@@ -120,7 +121,7 @@ module Acclaim
120
121
  # Calls this command's action block with the given option values and
121
122
  # arguments.
122
123
  def execute(opts, args)
123
- @action.call opts, args
124
+ @action.call opts, args if @action
124
125
  end
125
126
 
126
127
  alias :call :execute
@@ -1,9 +1,17 @@
1
+ require 'acclaim/command/help/template'
2
+
1
3
  module Acclaim
2
4
  class Command
3
5
 
4
6
  # Module which adds help support to a command.
5
7
  module Help
6
8
 
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.
7
15
  def self.add_options_to!(command, opts = {})
8
16
  switches = opts.fetch :switches, %w(-h --help)
9
17
  description = opts.fetch :description, 'Show usage information and exit.'
@@ -12,6 +20,16 @@ module Acclaim
12
20
 
13
21
  private_class_method :add_options_to!
14
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.
15
33
  def self.create(base, opts = {})
16
34
  if opts.fetch :options, true
17
35
  add_options_to! base, opts
@@ -27,21 +45,7 @@ module Acclaim
27
45
  # Displays a very simple help screen for the given command and all its
28
46
  # subcommands.
29
47
  def self.display_help_for(command)
30
- # TODO rewrite this VERY CRUDE implementation.
31
- # Look into how to code a text formatter later.
32
- help_string = ''
33
- command.options.tap do |options|
34
- if options.any?
35
- help_string << "\nCommand '#{command.line}':\n\n" unless command.root?
36
- max = options.map { |option| option.names.join(', ').length }.max
37
- options.each do |option|
38
- switches = option.names.join ', '
39
- help_string << ' ' * 4 << switches << ' ' * (4 + max - switches.length)
40
- help_string << option.description << "\n"
41
- end
42
- end
43
- end
44
- puts help_string unless help_string.empty?
48
+ puts Template.for(command) if command.options.any?
45
49
  command.subcommands.each { |subcommand| display_help_for subcommand }
46
50
  end
47
51
 
@@ -0,0 +1,30 @@
1
+ require 'erb'
2
+
3
+ module Acclaim
4
+ class Command
5
+ module Help
6
+
7
+ # Manages help templates.
8
+ module Template
9
+
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
17
+
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
+ end
25
+
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,8 @@
1
+ <% unless root? or options.empty? %>
2
+ Command '<%= line %>':
3
+ <% end %>
4
+
5
+ <% options.each do |option| %>
6
+ <%= option.names.join ', ' %> <%= option.description %>
7
+ <% end %>
8
+
@@ -4,6 +4,12 @@ module Acclaim
4
4
  # Module which adds version query support to a command.
5
5
  module Version
6
6
 
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.
7
13
  def self.add_options_to!(command, opts = {})
8
14
  switches = opts.fetch :switches, %w(-v --version)
9
15
  description = opts.fetch :description, 'Show version and exit.'
@@ -12,6 +18,16 @@ module Acclaim
12
18
 
13
19
  private_class_method :add_options_to!
14
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.
15
31
  def self.create(base, version_string, opts = {})
16
32
  if opts.fetch :options, true
17
33
  add_options_to! base, opts
@@ -9,6 +9,33 @@ module Acclaim
9
9
 
10
10
  attr_accessor :key, :names, :description, :type, :default, :handler
11
11
 
12
+ # Initializes a command line option. The +key+ is the object used to
13
+ # associate this option with a value. The other arguments may be:
14
+ #
15
+ # [short switches] Strings starting with <tt>'-'</tt>, like:
16
+ # <tt>'-h'</tt>; <tt>'-v'</tt>
17
+ # [long switches] Strings starting with <tt>'--'</tt>, like:
18
+ # <tt>'--help'</tt>; <tt>'--version'</tt>
19
+ # [description] Strings that don't start with either <tt>'-'</tt>
20
+ # nor <tt>'--'</tt>, like:
21
+ # <tt>'Display this help text and exit.'</tt>;
22
+ # <tt>'Display version and exit.'</tt>
23
+ # [class] The <tt>Class</tt> which will be used in parameter
24
+ # conversion. The default is <tt>String</tt>.
25
+ #
26
+ # The last argument can be a hash of options, which may specify:
27
+ #
28
+ # [:arity] The number of required and optional arguments. See Arity for
29
+ # defails.
30
+ # [:default] The default value for this option.
31
+ # [:required] Whether or not the option must be present on the command
32
+ # line.
33
+ #
34
+ # Additionally, if a block is given, it will be called when the option is
35
+ # parsed with a Values instance and the parameters given to the option. The
36
+ # parameters will already be converted to this option's specified type; if
37
+ # this is not desirable consider not specifying a class to the option or
38
+ # registering a custom type handler.
12
39
  def initialize(key, *args, &block)
13
40
  options = args.last.is_a?(Hash) ? args.pop : {}
14
41
  matches = args.select { |arg| arg.is_a? String }.group_by do |arg|
@@ -25,18 +52,24 @@ module Acclaim
25
52
  self.handler = block
26
53
  end
27
54
 
55
+ # Converts all given arguments using the type handler for this option's
56
+ # type.
28
57
  def convert_parameters(*args)
29
58
  args.map { |arg| Type[type].call arg }
30
59
  end
31
60
 
61
+ # Returns true if the given string is equal to any of this option's names.
32
62
  def =~(str)
33
63
  names.include? str.strip
34
64
  end
35
65
 
66
+ # Returns this option's arity. See Arity for details.
36
67
  def arity
37
68
  @arity ||= Arity.new
38
69
  end
39
70
 
71
+ # Sets this option's arity. The value given may be an Arity, or an array in
72
+ # the form of <tt>[ required_parameters, optional_parameters ]</tt>.
40
73
  def arity=(arity_or_array)
41
74
  @arity = if arity.nil? or arity_or_array.is_a? Arity
42
75
  arity_or_array
@@ -45,18 +78,22 @@ module Acclaim
45
78
  end
46
79
  end
47
80
 
81
+ # Whether or not this option is required on the command line.
48
82
  def required?
49
83
  @required
50
84
  end
51
85
 
86
+ # Sets whether or not this option is required.
52
87
  def required=(value)
53
- @required = value
88
+ @required = (value ? true : false)
54
89
  end
55
90
 
91
+ # Require that this option be given on the command line.
56
92
  def require
57
93
  self.required = true
58
94
  end
59
95
 
96
+ # Returns true if this option takes no arguments.
60
97
  def flag?
61
98
  not arity or arity == [0, 0]
62
99
  end
@@ -39,6 +39,8 @@ module Acclaim
39
39
  bound? ? minimum + optional : nil
40
40
  end
41
41
 
42
+ # Converts this arity to an array in the form of
43
+ # <tt>[ required, optional ]</tt>.
42
44
  def to_a
43
45
  [ minimum, optional ]
44
46
  end
@@ -46,10 +48,16 @@ module Acclaim
46
48
  alias :to_ary :to_a
47
49
  alias :to_array :to_a
48
50
 
51
+ # Equivalent to <tt>to_a.hash</tt>.
49
52
  def hash
50
53
  to_a.hash
51
54
  end
52
55
 
56
+ # Converts both +self+ and +arity+ to an array and compares them. This is
57
+ # so that comparing directly with an array is possible:
58
+ #
59
+ # Arity.new(1, 3) == [1, 3]
60
+ # => true
53
61
  def ==(arity)
54
62
  to_a == arity.to_a
55
63
  end
@@ -57,11 +65,21 @@ module Acclaim
57
65
  alias :eql? :==
58
66
  alias :=== :==
59
67
 
68
+ # Returns a string in the following format:
69
+ #
70
+ # Arity: minimum +optional
71
+ #
72
+ # The value of +optional+ will be <tt>'infinite'</tt> if #unlimited? is
73
+ # +true+.
60
74
  def to_s
61
75
  "Arity: #{minimum} +#{unlimited? ? 'infinite' : optional}"
62
76
  end
63
77
 
64
- alias :inspect :to_s
78
+ # Returns the output of #to_s, enclosed in angle brackets (<tt>'<'</tt>
79
+ # and <tt>'>'</tt>).
80
+ def inspect
81
+ "<#{to_s}>"
82
+ end
65
83
 
66
84
  end
67
85
 
@@ -9,12 +9,19 @@ module Acclaim
9
9
 
10
10
  include Parser::Regexp
11
11
 
12
+ # Errors raised by the parser.
12
13
  class Error < StandardError
13
14
 
15
+ # Raises an Error with the following error message:
16
+ #
17
+ # Wrong number of arguments (actual for minimum)
14
18
  def self.raise_wrong_arg_number(actual, minimum, optional)
15
19
  raise self, "Wrong number of arguments (#{actual} for #{minimum})"
16
20
  end
17
21
 
22
+ # Raises an Error with the following error message:
23
+ #
24
+ # Missing required argument (arg)
18
25
  def self.raise_missing_arg(arg)
19
26
  raise self, "Missing required argument (#{arg})"
20
27
  end
@@ -32,9 +39,22 @@ module Acclaim
32
39
  end
33
40
 
34
41
  # Parses the meaning of the options given to this parser. If none were
35
- # given, the argument array will only be preprocessed. Any parsed options
42
+ # given, the argument array will be preprocessed only. Any parsed options
36
43
  # and arguments will be removed from the argument array, so pass in a
37
44
  # duplicate if you need the original.
45
+ #
46
+ # include Acclaim
47
+ #
48
+ # args = %w(-F log.txt --verbose arg1 arg2)
49
+ # options = []
50
+ # options << Option.new(:file, '-F', arity: [1,0], required: true)
51
+ # options << Option.new(:verbose, '--verbose')
52
+ #
53
+ # Option::Parser.new(args, options).parse!
54
+ # => #<Acclaim::Option::Values:0x00000002a2fee8 @options={:file=>"log.txt", :verbose=>true}>
55
+ #
56
+ # args
57
+ # => ["arg1", "arg2"]
38
58
  def parse!
39
59
  preprocess_argv!
40
60
  parse_values! unless options.nil?
@@ -42,15 +62,16 @@ module Acclaim
42
62
 
43
63
  private
44
64
 
45
- # Argument array preprocessing.
65
+ # Preprocesses the argument array.
46
66
  def preprocess_argv!
47
67
  split_multiple_short_options!
48
68
  normalize_parameters!
49
- # TODO: normalize parameter formats?
50
- # -sPARAM1[,PARAM2,PARAM3...] - possibly incompatible with split_multiple_short_options!
51
69
  argv.compact!
52
70
  end
53
71
 
72
+ # Splits multiple short options.
73
+ #
74
+ # %w(-abcdef PARAM1 PARAM2) => %w(-a -b -c -d -e -f PARAM1 PARAM2)
54
75
  def split_multiple_short_options!
55
76
  argv.find_all { |arg| arg =~ MULTIPLE_SHORT_SWITCHES }.each do |multiples|
56
77
  multiples_index = argv.index multiples
@@ -60,6 +81,12 @@ module Acclaim
60
81
  end
61
82
  end
62
83
 
84
+ # Splits switches that are connected to a comma-separated parameter list.
85
+ #
86
+ # %w(--switch=) => %w(--switch)
87
+ # %w(--switch=PARAM1,PARAM2) => %w(--switch PARAM1 PARAM2)
88
+ # %w(--switch=PARAM1,) => %w(--switch PARAM1)
89
+ # %w(--switch=,PARAM2) => [ '--switch', '', 'PARAM2' ]
63
90
  def normalize_parameters!
64
91
  argv.find_all { |arg| arg =~ SWITCH_PARAM_EQUALS }.each do |switch|
65
92
  switch_index = argv.index switch
@@ -70,20 +97,22 @@ module Acclaim
70
97
  end
71
98
  end
72
99
 
100
+ # Parses the options and their arguments, associating that information
101
+ # with a Values instance.
73
102
  def parse_values!
74
- Values.new.tap do |options_instance|
103
+ Values.new.tap do |values|
75
104
  options.each do |option|
76
105
  key = option.key
77
- options_instance[key] = option.default unless options_instance[key]
106
+ values[key] = option.default unless values[key]
78
107
  switches = argv.find_all { |switch| option =~ switch }
79
108
  if switches.any?
80
109
  if option.flag?
81
- set_option_value option, options_instance
110
+ set_option_value option, values
111
+ argv.delete *switches
82
112
  else
83
113
  switches.each do |switch|
84
114
  params = extract_parameters_of! option, switch
85
- argv.delete switch
86
- set_option_value option, options_instance, params
115
+ set_option_value option, values, params
87
116
  end
88
117
  end
89
118
  else
@@ -93,6 +122,14 @@ module Acclaim
93
122
  end
94
123
  end
95
124
 
125
+ # Finds the +switch+ in #argv and scans the next +option.arity.total+
126
+ # elements if +option.arity.bound?+ is +true+, or all parameters
127
+ # otherwise. In either case, the algorithm will stop if it finds +nil+,
128
+ # another switch or an argument separator among the parameters.
129
+ #
130
+ # Deletes the switch and every value that was extracted from #argv. Raises
131
+ # an Error if the number of parameters found is less than
132
+ # +option.arity.required+.
96
133
  def extract_parameters_of!(option, switch)
97
134
  arity = option.arity
98
135
  switch_index = argv.index switch
@@ -113,9 +150,15 @@ module Acclaim
113
150
  end
114
151
  count = values.count
115
152
  Error.raise_wrong_arg_number count, *arity if count < arity.required
153
+ argv.delete switch
116
154
  values.each { |value| argv.delete value }
117
155
  end
118
156
 
157
+ # If the option has an custom handler associated, call it with the
158
+ # parameters. Otherwise, if the option is a flag, the value corresponding
159
+ # to the option's key will be set to +true+, if it is not, the value will
160
+ # be set to params.first+ if +params+ contains only one element or to
161
+ # +params+ if it contains more.
119
162
  def set_option_value(option, values, params = [])
120
163
  params = option.convert_parameters *params
121
164
  if handler = option.handler
@@ -7,13 +7,13 @@ module Acclaim
7
7
 
8
8
  # Regular expression for a short option switch.
9
9
  #
10
- # Matches strings that begin with a single dash and contain only word
11
- # characters or digits until the end of the string.
10
+ # Matches strings that begin with a single dash and contains only one
11
+ # word character or digit before the end of the string.
12
12
  #
13
- # Examples: <tt>-s; -mult; -5; -_</tt>
13
+ # Examples: <tt>-s; -5; -_</tt>
14
14
  #
15
15
  # <tt>'-mult'</tt> will be split into <tt>%w(-m -u -l -t)</tt>.
16
- SHORT_SWITCH = /\A-[\w\d]+\Z/
16
+ SHORT_SWITCH = /\A-[\w\d]\Z/
17
17
 
18
18
  # Regular expression for a long option switch.
19
19
  #
@@ -26,12 +26,6 @@ module Acclaim
26
26
  # --_private-option; --1-1</tt>
27
27
  LONG_SWITCH = /\A--[\w\d]+(-[\w\d]+)*\Z/
28
28
 
29
- # Regular expression for any kind of option switch.
30
- #
31
- # Matches either a SHORT_SWITCH or a LONG_SWITCH. See their descriptions
32
- # for details.
33
- SWITCH = /(#{SHORT_SWITCH})|(#{LONG_SWITCH})/
34
-
35
29
  # Regular expression for multiple short options in a single "short"
36
30
  # switch.
37
31
  #
@@ -66,6 +60,12 @@ module Acclaim
66
60
  # of those isn't a decision for a preprocessor.
67
61
  SWITCH_PARAM_EQUALS = /\A--[\w\d]+(-?[\w\d]+)*=(,*[\w\d]*)*\Z/
68
62
 
63
+ # Regular expression for any kind of option switch.
64
+ #
65
+ # Matches anything that matches any of the other switch regular
66
+ # expressions.
67
+ SWITCH = /(#{SHORT_SWITCH})|(#{LONG_SWITCH})|(#{MULTIPLE_SHORT_SWITCHES})|(#{SWITCH_PARAM_EQUALS})/
68
+
69
69
  # Regular expression for the string that separates options and their
70
70
  # parameters from arguments like filenames.
71
71
  #
@@ -4,45 +4,41 @@ module Acclaim
4
4
  # Associates a class with a handler block.
5
5
  module Type
6
6
 
7
- instance_eval do
8
-
9
- # Yields class, proc pairs if a block was given. Returns an enumerator
10
- # otherwise.
11
- def each(&block)
12
- table.each &block
13
- end
7
+ # Yields class, proc pairs if a block was given. Returns an enumerator
8
+ # otherwise.
9
+ def self.each(&block)
10
+ table.each &block
11
+ end
14
12
 
15
- # Returns all registered classes.
16
- def all
17
- table.keys
18
- end
13
+ # Returns all registered classes.
14
+ def self.all
15
+ table.keys
16
+ end
19
17
 
20
- alias registered all
18
+ # Registers a handler for a class.
19
+ def self.register(klass, &block)
20
+ table[klass] = block
21
+ end
21
22
 
22
- # Registers a handler for a class.
23
- def register(klass, &block)
24
- table[klass] = block
25
- end
23
+ # Returns the handler for the given class.
24
+ def self.handler_for(klass)
25
+ table[klass]
26
+ end
26
27
 
28
+ class << self
29
+ alias registered all
27
30
  alias add_handler_for register
28
31
  alias accept register
29
-
30
- # Returns the handler for the given class.
31
- def handler_for(klass)
32
- table[klass]
33
- end
34
-
35
32
  alias [] handler_for
33
+ end
36
34
 
37
- private
38
-
39
- # The hash used to associate classes with their handlers.
40
- def table
41
- @table ||= {}
42
- end
43
-
35
+ # The hash used to associate classes with their handlers.
36
+ def self.table
37
+ @table ||= {}
44
38
  end
45
39
 
40
+ private_class_method :table
41
+
46
42
  end
47
43
 
48
44
  end
@@ -8,6 +8,7 @@ module Acclaim
8
8
  # Handles dates given as arguments in the command line.
9
9
  module Date
10
10
 
11
+ # Parses a +Date+ from the string.
11
12
  def self.handle(str)
12
13
  ::Date.parse str
13
14
  end
@@ -8,6 +8,7 @@ module Acclaim
8
8
  # Handles dates and times given as arguments in the command line.
9
9
  module DateTime
10
10
 
11
+ # Parses a +DateTime+ from the string.
11
12
  def self.handle(str)
12
13
  ::DateTime.parse str
13
14
  end
@@ -8,6 +8,7 @@ module Acclaim
8
8
  # Handles strings given as arguments in the command line.
9
9
  module String
10
10
 
11
+ # Simply returns +str.to_s+.
11
12
  def self.handle(str)
12
13
  str.to_s
13
14
  end
@@ -8,6 +8,7 @@ module Acclaim
8
8
  # Handles times given as arguments in the command line.
9
9
  module Time
10
10
 
11
+ # Parses a +Time+ from the string.
11
12
  def self.handle(str)
12
13
  ::Time.parse str
13
14
  end
@@ -8,6 +8,7 @@ module Acclaim
8
8
  # Handles URIs given as arguments in the command line.
9
9
  module URI
10
10
 
11
+ # Parses an +URI+ from the string.
11
12
  def self.handle(str)
12
13
  ::URI.parse str
13
14
  end
@@ -1,11 +1,30 @@
1
1
  module Acclaim
2
+
3
+ # Acclaim's version.
2
4
  module Version
3
5
 
6
+ # Major version.
7
+ #
8
+ # Increments denote backward-incompatible changes and additions.
4
9
  MAJOR = 0
10
+
11
+ # Minor version.
12
+ #
13
+ # Increments denote backward-compatible changes and additions.
5
14
  MINOR = 0
6
- PATCH = 4
15
+
16
+ # Patch version.
17
+ #
18
+ # Increments denote changes in implementation.
19
+ PATCH = 5
20
+
21
+ # Build version.
22
+ #
23
+ # Used for pre-release versions.
7
24
  BUILD = nil
8
25
 
26
+ # Complete version string, which is every individual version number joined
27
+ # by a dot (<tt>'.'</tt>), in descending order of prescedence.
9
28
  STRING = [ MAJOR, MINOR, PATCH, BUILD ].compact.join '.'
10
29
 
11
30
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acclaim
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-12-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &13170100 !ruby/object:Gem::Requirement
16
+ requirement: &8505620 !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: :development
23
23
  prerelease: false
24
- version_requirements: *13170100
24
+ version_requirements: *8505620
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rookie
27
- requirement: &13169620 !ruby/object:Gem::Requirement
27
+ requirement: &8505100 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *13169620
35
+ version_requirements: *8505100
36
36
  description: Command-line option parser and command interface.
37
37
  email: matheus.a.m.moreira@gmail.com
38
38
  executables: []
@@ -49,6 +49,8 @@ files:
49
49
  - lib/acclaim.rb
50
50
  - lib/acclaim/command.rb
51
51
  - lib/acclaim/command/help.rb
52
+ - lib/acclaim/command/help/template.rb
53
+ - lib/acclaim/command/help/template/command.erb
52
54
  - lib/acclaim/command/version.rb
53
55
  - lib/acclaim/option.rb
54
56
  - lib/acclaim/option/arity.rb