ame 0.1.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/README +541 -3
  3. data/Rakefile +15 -6
  4. data/lib/ame-1.0.rb +31 -0
  5. data/lib/ame-1.0/argument.rb +63 -0
  6. data/lib/ame-1.0/arguments.rb +44 -0
  7. data/lib/ame-1.0/arguments/complete.rb +37 -0
  8. data/lib/ame-1.0/arguments/optional.rb +34 -0
  9. data/lib/ame-1.0/arguments/undefined.rb +71 -0
  10. data/lib/ame-1.0/class.rb +436 -0
  11. data/lib/ame-1.0/flag.rb +101 -0
  12. data/lib/{ame → ame-1.0}/help.rb +1 -1
  13. data/lib/ame-1.0/help/delegate.rb +19 -0
  14. data/lib/ame-1.0/help/terminal.rb +132 -0
  15. data/lib/ame-1.0/method.rb +75 -0
  16. data/lib/ame-1.0/method/undefined.rb +184 -0
  17. data/lib/ame-1.0/methods.rb +40 -0
  18. data/lib/ame-1.0/multioption.rb +36 -0
  19. data/lib/ame-1.0/option.rb +37 -0
  20. data/lib/ame-1.0/optional.rb +31 -0
  21. data/lib/ame-1.0/options.rb +68 -0
  22. data/lib/ame-1.0/options/undefined.rb +114 -0
  23. data/lib/ame-1.0/root.rb +174 -0
  24. data/lib/ame-1.0/splat.rb +16 -0
  25. data/lib/ame-1.0/splus.rb +22 -0
  26. data/lib/ame-1.0/switch.rb +39 -0
  27. data/lib/ame-1.0/types.rb +60 -0
  28. data/lib/ame-1.0/types/boolean.rb +13 -0
  29. data/lib/ame-1.0/types/enumeration.rb +40 -0
  30. data/lib/ame-1.0/types/float.rb +11 -0
  31. data/lib/{ame → ame-1.0}/types/integer.rb +3 -3
  32. data/lib/{ame → ame-1.0}/types/string.rb +2 -2
  33. data/lib/ame-1.0/types/symbol.rb +9 -0
  34. data/lib/ame-1.0/version.rb +62 -0
  35. data/test/unit/ame-1.0.rb +4 -0
  36. data/test/unit/ame-1.0/argument.rb +46 -0
  37. data/test/unit/ame-1.0/arguments.rb +63 -0
  38. data/test/unit/ame-1.0/arguments/complete.rb +4 -0
  39. data/test/unit/ame-1.0/arguments/optional.rb +4 -0
  40. data/test/unit/ame-1.0/arguments/undefined.rb +63 -0
  41. data/test/unit/ame-1.0/class.rb +4 -0
  42. data/test/unit/ame-1.0/flag.rb +31 -0
  43. data/test/unit/ame-1.0/help.rb +4 -0
  44. data/test/unit/ame-1.0/help/delegate.rb +4 -0
  45. data/test/unit/{ame/help/console.rb → ame-1.0/help/terminal.rb} +34 -23
  46. data/test/unit/ame-1.0/method.rb +4 -0
  47. data/test/unit/ame-1.0/method/undefined.rb +33 -0
  48. data/test/unit/ame-1.0/methods.rb +9 -0
  49. data/test/unit/ame-1.0/multioption.rb +4 -0
  50. data/test/unit/ame-1.0/option.rb +11 -0
  51. data/test/unit/ame-1.0/optional.rb +9 -0
  52. data/test/unit/ame-1.0/options.rb +149 -0
  53. data/test/unit/ame-1.0/options/undefined.rb +33 -0
  54. data/test/unit/ame-1.0/root.rb +4 -0
  55. data/test/unit/ame-1.0/splat.rb +9 -0
  56. data/test/unit/ame-1.0/splus.rb +4 -0
  57. data/test/unit/ame-1.0/switch.rb +15 -0
  58. data/test/unit/ame-1.0/types.rb +4 -0
  59. data/test/{ame → unit/ame-1.0}/types/boolean.rb +0 -0
  60. data/test/unit/ame-1.0/types/enumeration.rb +4 -0
  61. data/test/unit/ame-1.0/types/float.rb +7 -0
  62. data/test/{ame → unit/ame-1.0}/types/integer.rb +0 -0
  63. data/test/{ame → unit/ame-1.0}/types/string.rb +0 -0
  64. data/test/unit/ame-1.0/types/symbol.rb +5 -0
  65. data/test/unit/ame-1.0/version.rb +4 -0
  66. metadata +690 -60
  67. data/lib/ame.rb +0 -26
  68. data/lib/ame/argument.rb +0 -56
  69. data/lib/ame/arguments.rb +0 -65
  70. data/lib/ame/class.rb +0 -117
  71. data/lib/ame/help/console.rb +0 -96
  72. data/lib/ame/method.rb +0 -94
  73. data/lib/ame/methods.rb +0 -30
  74. data/lib/ame/option.rb +0 -50
  75. data/lib/ame/options.rb +0 -102
  76. data/lib/ame/root.rb +0 -57
  77. data/lib/ame/splat.rb +0 -12
  78. data/lib/ame/types.rb +0 -29
  79. data/lib/ame/types/array.rb +0 -16
  80. data/lib/ame/types/boolean.rb +0 -16
  81. data/lib/ame/version.rb +0 -5
  82. data/test/ame/types/array.rb +0 -13
  83. data/test/unit/ame/argument.rb +0 -66
  84. data/test/unit/ame/arguments.rb +0 -106
  85. data/test/unit/ame/method.rb +0 -40
  86. data/test/unit/ame/methods.rb +0 -10
  87. data/test/unit/ame/option.rb +0 -75
  88. data/test/unit/ame/options.rb +0 -136
  89. data/test/unit/ame/root.rb +0 -15
  90. data/test/unit/ame/splat.rb +0 -11
@@ -0,0 +1,101 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Represents a boolean option to a {Method} that doesn’t take an argument,
4
+ # though an argument is actually allowed if it’s made explicit by following the
5
+ # option name with a ‘=’ character and the argument value. Does the potential
6
+ # processing of the argument or simply returns the inverse {#default} value of
7
+ # the flag.
8
+ # @api developer
9
+ class Ame::Flag
10
+ # @api internal
11
+ # @param [String] short
12
+ # @param [String] long
13
+ # @param [Boolean] default
14
+ # @param [String] description
15
+ # @yield [?]
16
+ # @yieldparam [Hash<String, Object>] options
17
+ # @yieldparam [Boolean] value
18
+ # @raise [ArgumentError] If SHORT and LONG are #strip#empty?
19
+ # @raise [ArgumentError] If SHORT#strip#length > 1
20
+ def initialize(short, long, default, description, &validate)
21
+ @short, @long, @default, @description, @validate =
22
+ (s = short.strip).empty? ? nil : s, (l = long.strip).empty? ? nil : l,
23
+ default, description, validate || proc{ |_, a| a }
24
+ raise ArgumentError, 'both short and long can’t be empty' if
25
+ @short.nil? and @long.nil?
26
+ raise ArgumentError, 'short can’t be longer than 1: %s' % @short if
27
+ @short and @short.length > 1
28
+ end
29
+
30
+ # Invokes the optional block passed to the receiver when it was created for
31
+ # additional validation and parsing after optionally parsing one or more of
32
+ # the ARGUMENTS passed to it (see subclasses’ {#parse} methods for their
33
+ # behaviour).
34
+ # @api internal
35
+ # @param [Hash<String, Object>] options
36
+ # @param [Array<String>] arguments
37
+ # @param [String] name
38
+ # @raise [MissingArgument] If a required argument to an option is missing
39
+ # @raise [MalformedArgument] If an argument to an option can’t be parsed
40
+ # @return [Boolean]
41
+ def process(options, arguments, name, explicit)
42
+ @validate.call(options, parse(arguments, explicit))
43
+ rescue Ame::MalformedArgument, ArgumentError, TypeError => e
44
+ raise Ame::MalformedArgument, '%s: %s' % [name, e]
45
+ end
46
+
47
+ # Invokes {#process} with arguments depending on whether REMAINDER, which is
48
+ # any content following a short option, should be seen as an argument to the
49
+ # receiver or not (see subclasses’ {#process_combined} methods for their
50
+ # behaviour), returning the result of {#process} and REMAINDER if it was
51
+ # used, or an empty String if it was.
52
+ # @api internal
53
+ # @param (see #process)
54
+ # @param [String] remainder
55
+ # @return [[Boolean, String]]
56
+ def process_combined(options, arguments, name, remainder)
57
+ [process(options, arguments, name, nil), remainder]
58
+ end
59
+
60
+ # @return [String] The long or short name of the option
61
+ def name
62
+ @name ||= names.first
63
+ end
64
+
65
+ # @return [Array<String>] The long and/or short name of the option
66
+ def names
67
+ @names ||= [long, short].reject{ |e| e.nil? }
68
+ end
69
+
70
+ # @return True if the receiver shouldn’t be included in the Hash of option
71
+ # names and their values
72
+ def ignored?
73
+ default.nil?
74
+ end
75
+
76
+ # @return [String] The short name of the receiver
77
+ attr_reader :short
78
+
79
+ # @return [String] The long name of the receiver
80
+ attr_reader :long
81
+
82
+ # @return [Boolean] The default value of the receiver
83
+ attr_reader :default
84
+
85
+ # @return [String] The description of the receiver
86
+ attr_reader :description
87
+
88
+ private
89
+
90
+ # Returns the parsed value of EXPLICIT, or the inverse of {#default} if nil.
91
+ # Should be overridden by subclasses that want different behaviour for
92
+ # missing arguments.
93
+ # @api internal
94
+ # @param [Array<String>] arguments
95
+ # @param [String, nil] explicit
96
+ # @return [Boolean]
97
+ # @raise [MalformedArgument] If EXPLICIT is non-nil and can’t be parsed
98
+ def parse(arguments, explicit)
99
+ explicit ? Ame::Types[TrueClass].parse(explicit) : !default
100
+ end
101
+ end
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ # Namespace for help output.
3
4
  module Ame::Help
4
- autoload :Console, 'ame/help/console'
5
5
  end
@@ -0,0 +1,19 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Delegates help output requests to another help output.
4
+ # @api internal
5
+ class Ame::Help::Delegate
6
+ def initialize(help)
7
+ @help = help
8
+ end
9
+
10
+ def dispatch(method, klass)
11
+ @help.dispatch method, klass
12
+ self
13
+ end
14
+
15
+ def method(method)
16
+ @help.method method
17
+ self
18
+ end
19
+ end
@@ -0,0 +1,132 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Outputs help requests to a pair of IO objects, defaulting to `$stdout` and
4
+ # `$stderr`. An instance of this class is used by default for outputting help
5
+ # requests from {Root}, but can be overridden by invoking {Root.help} with
6
+ # another object (such as an instance of this class that’s been constructed
7
+ # with different parameters).
8
+ # @api developer/user
9
+ class Ame::Help::Terminal
10
+ # Sets up help requests to be made to OUTPUT ({#dispatch}, {#method}, and
11
+ # {#version}) and ERROR ({#error}), as well as specifying whether to
12
+ # EXIT_ON_ERROR or not, see {#error}.
13
+ # @param [#puts] output
14
+ # @param [#puts] error
15
+ # @param [Boolean] exit_on_error
16
+ def initialize(output = $stdout, error = $stderr, exit_on_error = true)
17
+ @output, @error, @exit_on_error = output, error, exit_on_error
18
+ end
19
+
20
+ # Outputs a help request for a {Class.dispatch} METHOD to KLASS, displaying
21
+ # all options and arguments to the method and listing the possible dispatch
22
+ # methods.
23
+ # @param [Method] method
24
+ # @param [Class] klass
25
+ # @return [self]
26
+ def dispatch(method, klass)
27
+ output(method_s(method).tap{ |result|
28
+ append_group result, 'Methods', klass.methods.sort_by{ |m| m.name } do |m|
29
+ m.name
30
+ end
31
+ })
32
+ end
33
+
34
+ # Outputs a help request for METHOD, displaying all its options and
35
+ # arguments.
36
+ # @param [Method] method
37
+ # @return [self]
38
+ def method(method)
39
+ output(method_s(method))
40
+ end
41
+
42
+ # Outputs VERSION information for METHOD.
43
+ # @param [Method] method
44
+ # @param [String] version
45
+ # @return [self]
46
+ def version(method, version)
47
+ output('%s %s' % [method.name, version])
48
+ end
49
+
50
+ # Outputs ERROR that occurred while processing METHOD.
51
+ # @raise [SystemExit] If exit_on_error was given as true to the receiver’s
52
+ # constructor
53
+ # @raise [error] If exit_on_error wasn’t given as true to the receiver’s
54
+ # constructor
55
+ def error(method, error)
56
+ errput '%s: %s' % [method, error]
57
+ exit 1 if @exit_on_error
58
+ raise error
59
+ end
60
+
61
+ private
62
+
63
+ def output(string)
64
+ @output.puts string
65
+ self
66
+ end
67
+
68
+ def errput(string)
69
+ @error.puts string
70
+ self
71
+ end
72
+
73
+ def method_s(method)
74
+ ['Usage:'].tap{ |result|
75
+ append result, ' ', method.qualified_name
76
+ append result, ' ', method.options.count > 0 ? '[OPTIONS]...' : ''
77
+ append result, ' ', method.arguments.map{ |a|
78
+ case a
79
+ when Ame::Splat then '[%s]...'
80
+ when Ame::Splus then '%s...'
81
+ when Ame::Optional then '[%s]'
82
+ else '%s'
83
+ end % a
84
+ }.join(' ')
85
+ result << "\n"
86
+ append result, ' ', method.description
87
+ append_group result, 'Arguments', method.arguments do |argument|
88
+ case argument
89
+ when Ame::Splat then '[%s]...' % argument
90
+ when Ame::Splus then '%s...' % argument
91
+ when Ame::Optional then '[%s=%s]' % [argument, argument.default]
92
+ else argument.to_s
93
+ end
94
+ end
95
+ os = method.options.select{ |o| o.description }.sort_by{ |o| (o.short or o.long).to_s }
96
+ short = os.any?{ |o| o.short }
97
+ append_group result, 'Options', os do |o|
98
+ case o
99
+ when Ame::Multioption then '%s*' % option(o, short)
100
+ when Ame::Option then option(o, short)
101
+ when Ame::Switch then '%s[=%s]' % [flag(o, short), o.argument]
102
+ else flag(o, short)
103
+ end
104
+ end
105
+ }.join('')
106
+ end
107
+
108
+ def append(result, prefix, string)
109
+ result << prefix << string unless string.empty?
110
+ end
111
+
112
+ def append_group(result, heading, objects)
113
+ strings = objects.map{ |o| [o, yield(o)] }
114
+ longest = strings.map{ |_, s| s.length }.max
115
+ append result, "\n\n%s:\n" % heading,
116
+ strings.map{ |o, s| ' %-*s %s' % [longest, s, o.description] }.join("\n")
117
+ end
118
+
119
+ def flag(option, short)
120
+ if option.short and option.long
121
+ '-%s, --%s' % [option.short, option.long]
122
+ elsif option.short
123
+ '-%s' % option.short
124
+ else
125
+ '%s--%s' % [short ? ' ' : '', option.long]
126
+ end
127
+ end
128
+
129
+ def option(option, short)
130
+ '%s%s%s' % [flag(option, short), option.long ? '=' : '', option.argument]
131
+ end
132
+ end
@@ -0,0 +1,75 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # A method in its defined state.
4
+ # @api developer
5
+ class Ame::Method
6
+ class << self
7
+ # @param [String] name
8
+ # @return [Symbol] The Ruby version of NAME, possibly the name of the
9
+ # method given on the command-line, replacing any ‘-’ with ‘_’.
10
+ def ruby_name(name)
11
+ name.gsub('-', '_').to_sym
12
+ end
13
+
14
+ # @param [Symbol] ruby_name
15
+ # @return [String] The command-line version of RUBY_NAME, replacing any ‘_’
16
+ # with ‘-’
17
+ def name(ruby_name)
18
+ ruby_name.to_s.gsub('_', '-')
19
+ end
20
+ end
21
+
22
+ def initialize(ruby_name, klass, description, options, arguments)
23
+ @ruby_name, @class, @description, @options, @arguments =
24
+ ruby_name, klass, description, options, arguments
25
+ end
26
+
27
+ # Process ARGUMENTS as a set of {Options} and {Arguments}, then {#call} the
28
+ # receiver’s method on INSTANCE with them.
29
+ # @api internal
30
+ # @param [Class] instance
31
+ # @param [Array<String>] arguments
32
+ # @raise (see Options#process)
33
+ # @raise (see Arguments#process)
34
+ # @return [self]
35
+ def process(instance, arguments)
36
+ options, remainder = @options.process(arguments)
37
+ call(instance, @arguments.process(options, remainder), options)
38
+ end
39
+
40
+ # Call the receiver’s method on INSTANCE with ARGUMENTS and OPTIONS,
41
+ # retrieving any default values for them if they’re nil.
42
+ # @api internal
43
+ # @param [Class] instance
44
+ # @param [Array<Object>, nil] arguments
45
+ # @param [Hash<String, Object>] options
46
+ # @raise (see Options#process)
47
+ # @raise (see Arguments#process)
48
+ # @return [self]
49
+ def call(instance, arguments = nil, options = nil)
50
+ options, _ = @options.process([]) unless options
51
+ arguments ||= @arguments.process(options, [])
52
+ instance.send @ruby_name, *(arguments + (options.empty? ? [] : [options]))
53
+ self
54
+ end
55
+
56
+ # @return [String] The description of the receiver
57
+ attr_reader :description
58
+
59
+ # @return [Options] The options of the receiver
60
+ attr_reader :options
61
+
62
+ # @return [Arguments] The arguments of the receiver
63
+ attr_reader :arguments
64
+
65
+ # @return [String] The command-line name of the receiver
66
+ def name
67
+ @name ||= self.class.name(@ruby_name)
68
+ end
69
+
70
+ # @return [String] The full command-line name of the receiver, including the
71
+ # class that this method belongs to’s {Class.fullname}
72
+ def qualified_name
73
+ [@class.fullname, name].reject(&:empty?).join(' ')
74
+ end
75
+ end
@@ -0,0 +1,184 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # A {Method} in its undefined state. This class is used to construct the
4
+ # method before it gets defined, setting up a description, specifying that
5
+ # options_must_precede_arguments, adding flags, toggles, switches, options,
6
+ # multioptions, arguments, optional arguments, splats, spluses, and finally
7
+ # defining it.
8
+ # @api developer
9
+ class Ame::Method::Undefined
10
+ # Sets up an as yet undefined method on KLASS.
11
+ # @api internal
12
+ # @param [Class] klass
13
+ def initialize(klass)
14
+ @class = klass
15
+ @description = nil
16
+ @options = Ame::Options::Undefined.new
17
+ @arguments = Ame::Arguments::Undefined.new
18
+ end
19
+
20
+ # Sets the DESCRIPTION of the method, or returns it if DESCRIPTION is nil.
21
+ # The description is used in help output and similar circumstances.
22
+ # @api internal
23
+ # @param [String, nil] description
24
+ # @return [String]
25
+ def description(description = nil)
26
+ return @description unless description
27
+ @description = description
28
+ self
29
+ end
30
+
31
+ # Forces options to the method to precede any arguments to be processed
32
+ # correctly.
33
+ # @api internal
34
+ # @return [self]
35
+ def options_must_precede_arguments
36
+ @options.options_must_precede_arguments
37
+ self
38
+ end
39
+
40
+ # Delegates {Class.flag} to {Options::Undefined#flag}.
41
+ # @api internal
42
+ # @param (see Options::Undefined#flag)
43
+ # @yield (see Options::Undefined#flag)
44
+ # @yieldparam (see Options::Undefined#flag)
45
+ # @raise (see Options::Undefined#flag)
46
+ # @return [self]
47
+ def flag(short, long, default, description, &validate)
48
+ @options.flag short, long, default, description, &validate
49
+ self
50
+ end
51
+
52
+ # Delegates {Class.toggle} to {Options::Undefined#toggle}.
53
+ # @api internal
54
+ # @param (see Options::Undefined#toggle)
55
+ # @yield (see Options::Undefined#toggle)
56
+ # @yieldparam (see Options::Undefined#toggle)
57
+ # @raise (see Options::Undefined#toggle)
58
+ # @return [self]
59
+ def toggle(short, long, default, description, &validate)
60
+ @options.toggle short, long, default, description, &validate
61
+ self
62
+ end
63
+
64
+ # Delegates {Class.switch} to {Options::Undefined#switch}.
65
+ # @api internal
66
+ # @param (see Options::Undefined#switch)
67
+ # @yield (see Options::Undefined#switch)
68
+ # @yieldparam (see Options::Undefined#switch)
69
+ # @raise (see Options::Undefined#switch)
70
+ # @return [self]
71
+ def switch(short, long, argument, default, argument_default, description, &validate)
72
+ @options.switch short, long, argument, default, argument_default, description, &validate
73
+ self
74
+ end
75
+
76
+ # Delegates {Class.option} to {Options::Undefined#option}.
77
+ # @api internal
78
+ # @param (see Options::Undefined#option)
79
+ # @yield (see Options::Undefined#option)
80
+ # @yieldparam (see Options::Undefined#option)
81
+ # @raise (see Options::Undefined#option)
82
+ # @return [self]
83
+ def option(short, long, argument, default, description, &validate)
84
+ @options.option short, long, argument, default, description, &validate
85
+ self
86
+ end
87
+
88
+ # Delegates {Class.multioption} to {Options::Undefined#multioption}.
89
+ # @api internal
90
+ # @param (see Options::Undefined#multioption)
91
+ # @yield (see Options::Undefined#multioption)
92
+ # @yieldparam (see Options::Undefined#multioption)
93
+ # @raise (see Options::Undefined#multioption)
94
+ # @return [self]
95
+ def multioption(short, long, argument, type, description, &validate)
96
+ @options.multioption short, long, argument, type, description, &validate
97
+ self
98
+ end
99
+
100
+ # Delegates {Class.argument} to {Arguments::Undefined#argument}.
101
+ # @api internal
102
+ # @param (see Arguments::Undefined#argument)
103
+ # @yield (see Arguments::Undefined#argument)
104
+ # @yieldparam (see Arguments::Undefined#argument)
105
+ # @raise (see Arguments::Undefined#argument)
106
+ # @raise (see Arguments::Optional#argument)
107
+ # @raise (see Arguments::Complete#argument)
108
+ # @return [self]
109
+ def argument(name, type, description, &validate)
110
+ @arguments.argument(name, type, description, &validate)
111
+ self
112
+ end
113
+
114
+ # Delegates {Class.argument} to {Arguments::Undefined#optional} or
115
+ # {Arguments::Optional#optional}.
116
+ # @api internal
117
+ # @param (see Arguments::Undefined#optional)
118
+ # @yield (see Arguments::Undefined#optional)
119
+ # @yieldparam (see Arguments::Undefined#optional)
120
+ # @param (see Arguments::Undefined#optional)
121
+ # @raise (see Arguments::Undefined#optional)
122
+ # @raise (see Arguments::Complete#optional)
123
+ # @return [self]
124
+ def optional(name, default, description, &validate)
125
+ @arguments = @arguments.optional(name, default, description, &validate)
126
+ self
127
+ end
128
+
129
+ # Delegates {Class.argument} to {Arguments::Undefined#splat}.
130
+ # @api internal
131
+ # @param (see Arguments::Undefined#splat)
132
+ # @option (see Arguments::Undefined#splat)
133
+ # @yield (see Arguments::Undefined#splat)
134
+ # @yieldparam (see Arguments::Undefined#splat)
135
+ # @raise (see Arguments::Undefined#splat)
136
+ # @raise (see Arguments::Complete#splat)
137
+ # @return [self]
138
+ def splat(name, type, description, &validate)
139
+ @arguments = @arguments.splat(name, type, description, &validate)
140
+ self
141
+ end
142
+
143
+ # Delegates {Class.argument} to {Arguments::Undefined#splus}.
144
+ # @api internal
145
+ # @param (see Arguments::Undefined#splus)
146
+ # @option (see Arguments::Undefined#splus)
147
+ # @yield (see Arguments::Undefined#splus)
148
+ # @yieldparam (see Arguments::Undefined#splus)
149
+ # @raise (see Arguments::Undefined#splus)
150
+ # @raise (see Arguments::Optional#splus)
151
+ # @raise (see Arguments::Complete#splus)
152
+ # @return [self]
153
+ def splus(name, type, description, &validate)
154
+ @arguments = @arguments.splus(name, type, description, &validate)
155
+ self
156
+ end
157
+
158
+ # @api internal
159
+ # @return [Method] The method RUBY_NAME after adding a “help” flag that’ll
160
+ # display help via {Class.help}#method and raise {AbortAllProcessing}
161
+ def define(ruby_name)
162
+ flag '', 'help', nil, 'Display help for this method' do
163
+ @class.help.method @class.methods[Ame::Method.name(ruby_name)]
164
+ throw Ame::AbortAllProcessing
165
+ end unless @options.include? 'help'
166
+ Ame::Method.new(ruby_name, @class, @description, @options.define, @arguments.define)
167
+ end
168
+
169
+ # @param [String] option
170
+ # @return [Boolean] True if OPTION has been defined on the receiver
171
+ def option?(option)
172
+ @options.include? option
173
+ end
174
+
175
+ # @return [Boolean] True if any arguments have been defined on the receiver
176
+ def arguments?
177
+ not @arguments.empty?
178
+ end
179
+
180
+ # @return [Boolean] True if a description has been defined on the receiver
181
+ def valid?
182
+ not description.nil?
183
+ end
184
+ end