acclaim 0.0.4 → 0.0.5

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