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,40 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Stores {Methods#each #each} {Method} defined on a {Class}.
4
+ # @api developer
5
+ class Ame::Methods
6
+ include Enumerable
7
+
8
+ def initialize
9
+ @methods = {}
10
+ end
11
+
12
+ # Adds METHOD to the receiver
13
+ # @param [Method] method
14
+ # @return [self]
15
+ def <<(method)
16
+ @methods[method.name] = method
17
+ self
18
+ end
19
+
20
+ # @return [Method] The method NAME in the receiver
21
+ # @raise [UnrecognizedMethod] If NAME isn’t a method in the receiver
22
+ def [](name)
23
+ @methods[name] or
24
+ raise Ame::UnrecognizedMethod, 'unrecognized method: %s' % name
25
+ end
26
+
27
+ # @overload
28
+ # Enumerates the methods.
29
+ #
30
+ # @yieldparam [Method] option
31
+ # @overload
32
+ # @return [Enumerator<Method>] An Enumerator over the methods
33
+ def each
34
+ return enum_for(__method__) unless block_given?
35
+ @methods.each_value do |method|
36
+ yield method
37
+ end
38
+ self
39
+ end
40
+ end
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Represents an option to a {Method} that takes an argument that can be given
4
+ # any number of times. If an explicit (‘=’-separated) argument is given, it’ll
5
+ # be used, otherwise the following argument will be used.
6
+ # @api developer
7
+ class Ame::Multioption < Ame::Option
8
+ # @api internal
9
+ # @param (see Option#initialize)
10
+ # @param [::Class] type
11
+ # @yield (see Option#initialize)
12
+ # @yieldparam (see Option#initialize)
13
+ # @raise (see Flag#initialize)
14
+ # @raise [ArgumentError] If TYPE isn’t one that Ame knows how to parse
15
+ def initialize(short, long, argument, type, description, &validate)
16
+ super short, long, argument, nil, description, &validate
17
+ @type = Ame::Types[type]
18
+ @ignored = true
19
+ end
20
+
21
+ # Invokes {super} and adds it to an Array added to OPTIONS before returning
22
+ # it.
23
+ # @api internal
24
+ # @param (see Flag#process)
25
+ # @raise (see Flag#process)
26
+ # @return [Object]
27
+ def process(options, arguments, name, explicit)
28
+ @ignored = false
29
+ (options[self.name] ||= []) << super
30
+ end
31
+
32
+ # @return True if the receiver hasn’t been asked to process any options yet
33
+ def ignored?
34
+ @ignored
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Represents an option to a {Method} that takes an argument. If an explicit
4
+ # (‘=’-separated) argument is given, it’ll be used, otherwise the following
5
+ # argument will be used.
6
+ # @api developer
7
+ class Ame::Option < Ame::Switch
8
+ # @api internal
9
+ # @param (see Switch#initialize)
10
+ # @yield (see Switch#initialize)
11
+ # @yieldparam (see Switch#initialize)
12
+ # @raise (see Flag#initialize)
13
+ # @raise [ArgumentError] If the type of DEFAULT isn’t one that Ame knows how
14
+ # to parse
15
+ def initialize(short, long, argument, default, description, &validate)
16
+ super short, long, argument, default, nil, description, &validate
17
+ end
18
+
19
+ # Invokes {Flag#process} with REMAINDER as the explicit argument if it’s
20
+ # non-empty.
21
+ # @api internal
22
+ # @param (see Flag#process_combined)
23
+ # @return [[Boolean, '']]
24
+ def process_combined(options, arguments, name, remainder)
25
+ [process(options, arguments, name, remainder.empty? ? nil : remainder), '']
26
+ end
27
+
28
+ private
29
+
30
+ # @api internal
31
+ # @param (see Flag#parse)
32
+ # @return [Object] The parsed value of EXPLICIT, if non-nil, the next argument otherwise
33
+ # @raise [MissingArgument] If EXPLICIT is nil and there are no more arguments
34
+ def parse(arguments, explicit)
35
+ @type.parse(explicit || arguments.shift || raise(Ame::MissingArgument, 'missing argument: %s' % self))
36
+ end
37
+ end
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Represents an optional argument to a {Method}. It has a {#default} value
4
+ # that will be used if no more arguments are available when it gets called upon
5
+ # to process an argument before the method this argument is associated with
6
+ # gets called.
7
+ # @api developer
8
+ class Ame::Optional < Ame::Argument
9
+ # @api internal
10
+ # @param (see Argument#initialize)
11
+ # @param [Object] default
12
+ # @yield (see Argument#initialize)
13
+ # @yieldparam (see Argument#initialize)
14
+ # @raise [ArgumentError] If the type of DEFAULT isn’t one that Ame knows how
15
+ # to parse
16
+ def initialize(name, default, description, &validate)
17
+ @default = default
18
+ super
19
+ end
20
+
21
+ # @return [Object, nil] The default value of the receiver
22
+ attr_reader :default
23
+
24
+ private
25
+
26
+ # @api internal
27
+ # @return [Object] {#default} if ARGUMENTS#empty?, {super} otherwise
28
+ def parse(arguments)
29
+ arguments.empty? ? default : super
30
+ end
31
+ end
@@ -0,0 +1,68 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # The options to a method in its {Method defined state}. Does the processing
4
+ # of options to the method and also enumerates {#each} of the options to the
5
+ # method for, for example, help output.
6
+ # @api developer
7
+ class Ame::Options
8
+ include Enumerable
9
+
10
+ def initialize(options, ordered, options_must_precede_arguments)
11
+ @options, @ordered, @options_must_precede_arguments =
12
+ options, ordered, options_must_precede_arguments
13
+ end
14
+
15
+ # @api internal
16
+ # @param [Array<String>] arguments
17
+ # @raise [UnrecognizedOption] If an unrecognized option has been given
18
+ # @raise (see Flag#process)
19
+ # @return [[Hash<String,Object>, Array<String>]] The {Flag#process}ed options
20
+ # as a Hash mapping the {Flag#name} to the parsed value or the option’s
21
+ # default after filtering out any {Flag#ignored?} options and the remaining
22
+ # non-option arguments
23
+ def process(arguments)
24
+ arguments = arguments.dup
25
+ results = @ordered.reduce({}){ |d, o| d[o.name] = o.default; d }
26
+ remainder = []
27
+ until arguments.empty?
28
+ case first = arguments.shift
29
+ when '--'
30
+ break
31
+ when /\A-([^=-]{2,})\z/
32
+ combined = $1
33
+ until combined.empty?
34
+ option = self['-' + combined[0].chr]
35
+ results[option.name], combined = option.process_combined(results, arguments, $1, combined[1..-1])
36
+ end
37
+ when /\A(--[^=]+|-[^-])(?:=(.*))?\z/
38
+ option = self[$1]
39
+ results[option.name] = option.process(results, arguments, $1, $2)
40
+ else
41
+ remainder << first
42
+ break if @options_must_precede_arguments
43
+ end
44
+ end
45
+ [results.reject{ |n, _| self[n].ignored? }, remainder.concat(arguments)]
46
+ end
47
+
48
+ # @overload
49
+ # Enumerates the options.
50
+ #
51
+ # @yieldparam [Option] option
52
+ # @overload
53
+ # @return [Enumerator<Option>] An Enumerator over the options
54
+ def each
55
+ return enum_for(__method__) unless block_given?
56
+ @ordered.each do |option|
57
+ yield option
58
+ end
59
+ self
60
+ end
61
+
62
+ private
63
+
64
+ def [](name)
65
+ @options[name.sub(/\A-+/, '')] or
66
+ raise Ame::UnrecognizedOption, 'unrecognized option: %s' % name
67
+ end
68
+ end
@@ -0,0 +1,114 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # The options to a method in its {Method::Undefined undefined state}.
4
+ # @api internal
5
+ class Ame::Options::Undefined
6
+ def initialize
7
+ @options = {}
8
+ @ordered = []
9
+ @options_must_precede_arguments = ENV.include? 'POSIXLY_CORRECT'
10
+ end
11
+
12
+ # Forces options to the method about to be defined to precede any arguments,
13
+ # lest they be seen as arguments. If not given, the behaviour will depend on
14
+ # whether `ENV['POSIXLY_CORRECT']` has been set or not.
15
+ # @return [self]
16
+ def options_must_precede_arguments
17
+ @options_must_precede_arguments = true
18
+ self
19
+ end
20
+
21
+ # Adds a new {Flag} to the receiver.
22
+ # @param (see Flag#initialize)
23
+ # @yield (see Flag#initialize)
24
+ # @yieldparam (see Flag#initialize)
25
+ # @raise (see Flag#initialize)
26
+ # @raise [ArgumentError] If SHORT or LONG have already been defined
27
+ # @return [self]
28
+ def flag(short, long, default, description, &validate)
29
+ self << Ame::Flag.new(short, long, default, description, &validate)
30
+ end
31
+
32
+ # Adds a new {Flag} to the receiver. Also adds a `--no-LONG` flag that’s the
33
+ # inverse of this flag.
34
+ # @param (see Flag#initialize)
35
+ # @yield (see Flag#initialize)
36
+ # @yieldparam (see Flag#initialize)
37
+ # @raise (see Flag#initialize)
38
+ # @raise [ArgumentError] If LONG is #strip#empty?
39
+ # @raise [ArgumentError] If SHORT or LONG have already been defined
40
+ # @return [self]
41
+ def toggle(short, long, default, description, &validate)
42
+ flag = Ame::Flag.new(short, long, default, description, &validate)
43
+ raise ArgumentError, 'long can’t be empty' if flag.long.empty?
44
+ self << flag
45
+ add(Ame::Flag.new('', 'no-%s' % flag.long, nil, description){ |options, argument|
46
+ options[flag.name] = validate ? validate.call(options, !argument) : !argument
47
+ })
48
+ end
49
+
50
+ # Adds a new {Switch} to the receiver.
51
+ # @param (see Switch#initialize)
52
+ # @yield (see Switch#initialize)
53
+ # @yieldparam (see Switch#initialize)
54
+ # @raise (see Switch#initialize)
55
+ # @raise [ArgumentError] If SHORT or LONG have already been defined
56
+ # @return [self]
57
+ def switch(short, long, argument, default, argument_default, description, &validate)
58
+ self << Ame::Switch.new(short, long, argument, default, argument_default, description, &validate)
59
+ end
60
+
61
+ # Adds a new {Option} to the receiver.
62
+ # @param (see Option#initialize)
63
+ # @yield (see Option#initialize)
64
+ # @yieldparam (see Option#initialize)
65
+ # @raise (see Option#initialize)
66
+ # @raise [ArgumentError] If SHORT or LONG have already been defined
67
+ # @return [self]
68
+ def option(short, long, argument, default, description, &validate)
69
+ self << Ame::Option.new(short, long, argument, default, description, &validate)
70
+ end
71
+
72
+ # Adds a new {Multioption} to the receiver.
73
+ # @param (see Multioption#initialize)
74
+ # @yield (see Multioption#initialize)
75
+ # @yieldparam (see Multioption#initialize)
76
+ # @raise (see Multioption#initialize)
77
+ # @raise [ArgumentError] If SHORT or LONG have already been defined
78
+ # @return [self]
79
+ def multioption(short, long, argument, type, description, &validate)
80
+ self << Ame::Multioption.new(short, long, argument, type, description, &validate)
81
+ end
82
+
83
+ # @param [String] name
84
+ # @return True if the receiver has any kind of option named NAME
85
+ def include?(name)
86
+ @options.include? name
87
+ end
88
+
89
+ # @return [Options] The defined version of the receiver
90
+ def define
91
+ Ame::Options.new(@options, @ordered, @options_must_precede_arguments)
92
+ end
93
+
94
+ protected
95
+
96
+ def <<(option)
97
+ @ordered << option
98
+ add(option)
99
+ end
100
+
101
+ private
102
+
103
+ def add(option)
104
+ option.names.each do |name|
105
+ self[name] = option
106
+ end
107
+ self
108
+ end
109
+
110
+ def []=(name, option)
111
+ raise ArgumentError, 'option already defined: %s' % name if include? name
112
+ @options[name] = option
113
+ end
114
+ end
@@ -0,0 +1,174 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Root of a hierarchy of {Class}es. This class should be subclassed by the
4
+ # root of your command-line interface.
5
+ # @example An rm-like Command-line Interface with Ame
6
+ # class Rm < Ame::Root
7
+ # version '1.0.0'
8
+ #
9
+ # flag 'f', '', false, 'Do not prompt for confirmation'
10
+ # flag 'i', '', nil, 'Prompt for confirmation' do |options|
11
+ # options['f'] = false
12
+ # end
13
+ # flag 'R', '', false, 'Remove file hierarchies'
14
+ # flag 'r', '', nil, 'Equivalent to -R' do |options|
15
+ # options['r'] = true
16
+ # end
17
+ # splus 'FILE', String, 'File to remove'
18
+ # description 'Remove directory entries'
19
+ # def rm(files, options = {})
20
+ # require 'fileutils'
21
+ # FileUtils.send options['R'] ? :rm_r : :rm,
22
+ # [first] + rest, :force => options['f']
23
+ # end
24
+ # end
25
+ # Rm.process
26
+ # @example A Git-like Command-line Interface With Ame
27
+ # module Git end
28
+ # class Git::CLI < Ame::Root
29
+ # version '1.0.0'
30
+ # class Git < Ame::Class
31
+ # description 'The stupid content tracker'
32
+ # def initialize; end
33
+ #
34
+ # description 'Prepare patches for e-mail submission'
35
+ # flag ?n, 'numbered', false, 'Name output in [PATCH n/m] format'
36
+ # flag ?N, 'no-numbered', nil,
37
+ # 'Name output in [PATCH] format' do |options|
38
+ # options['numbered'] = false
39
+ # end
40
+ # toggle ?s, 'signoff', false,
41
+ # 'Add Signed-off-by: line to the commit message'
42
+ # switch '', 'thread', 'STYLE', nil,
43
+ # Ame::Types::Enumeration[:shallow, :deep],
44
+ # 'Controls addition of In-Reply-To and References headers'
45
+ # flag '', 'no-thread', nil,
46
+ # 'Disables addition of In-Reply-To and Reference headers' do |options, _|
47
+ # options.delete 'thread'
48
+ # end
49
+ # option '', 'start-number', 'N', 1,
50
+ # 'Start numbering the patches at N instead of 1'
51
+ # multioption '', 'to', 'ADDRESS', String,
52
+ # 'Add a To: header to the email headers'
53
+ # optional 'SINCE', 'N/A', 'Generate patches for commits after SINCE'
54
+ # def format_patch(since = '', options = {})
55
+ # p since, options
56
+ # end
57
+ #
58
+ # description 'Annotate file lines with commit information'
59
+ # argument 'FILE', String, 'File to annotate'
60
+ # def annotate(file)
61
+ # p file
62
+ # end
63
+ #
64
+ # description 'Add file contents to the index'
65
+ # splat 'PATHSPEC', String, 'Files to add content from'
66
+ # def add(paths)
67
+ # p paths
68
+ # end
69
+ #
70
+ # description 'Display gitattributes information'
71
+ # splus 'PATHNAME', String, 'Files to list attributes of'
72
+ # def check_attr(paths)
73
+ # p paths
74
+ # end
75
+ #
76
+ # class Remote < Ame::Class
77
+ # description 'Manage set of remote repositories'
78
+ # def initialize; end
79
+ #
80
+ # description 'Shows a list of existing remotes'
81
+ # flag 'v', 'verbose', false, 'Show remote URL after name'
82
+ # def list(options = {})
83
+ # p options
84
+ # end
85
+ #
86
+ # description 'Adds a remote named NAME for the repository at URL'
87
+ # argument 'name', String, 'Name of the remote to add'
88
+ # argument 'url', String, 'URL to the repository of the remote to add'
89
+ # def add(name, url)
90
+ # p name, url
91
+ # end
92
+ # end
93
+ # dispatch Remote, :default => 'list'
94
+ # end
95
+ # dispatch Git
96
+ # end
97
+ # Git::CLI.process
98
+ class Ame::Root < Ame::Class
99
+ class << self
100
+ # Sets the HELP object to use for displaying usage information, or returns
101
+ # it if HELP is nil. The default is to use a {Help::Terminal} object.
102
+ # @param (see Class.help)
103
+ # @return [#method, #dispatch, #error, #version]
104
+ def help(help = nil)
105
+ super if help
106
+ @help ||= Ame::Help::Terminal.new
107
+ end
108
+
109
+ # Sets or returns, depending on if VERSION is nil or not, the version of
110
+ # the receiver. The version may be used by {.help} to output version
111
+ # information.
112
+ # @param [String, nil] version
113
+ # @return [String]
114
+ def version(version = nil)
115
+ return @version = version if version
116
+ @version
117
+ end
118
+
119
+ # Process ARGUMENTS as a list of options and arguments, then call METHOD
120
+ # with the results of this processing on a new instance of the receiver.
121
+ # This method catches {AbortAllProcessing}. Any errors will be caught and
122
+ # reported using {.help}#error.
123
+ # @param (see Class.process)
124
+ # @return [self]
125
+ def process(method = File.basename($0), arguments = ARGV)
126
+ catch Ame::AbortAllProcessing do
127
+ super
128
+ end
129
+ self
130
+ rescue => e
131
+ help.error method, e
132
+ end
133
+
134
+ # Call METHOD with ARGUMENTS and OPTIONS on a new instance of the receiver.
135
+ # This method catches {AbortAllProcessing}.
136
+ # @param (see Class.call)
137
+ # @raise (see Class.call)
138
+ # @return [self]
139
+ def call(method, arguments = nil, options = nil)
140
+ catch Ame::AbortAllProcessing do
141
+ super
142
+ end
143
+ self
144
+ end
145
+
146
+ # @api developer
147
+ # @return [String] An empty string
148
+ def basename
149
+ ''
150
+ end
151
+
152
+ private
153
+
154
+ # Defines the previously undefined {.method} now that it’s been added to
155
+ # the class after adding flag “version” that’ll call {.help}#version to
156
+ # output version information and then throw {AbortAllProcessing}.
157
+ # @api internal
158
+ # @param (see Class.method_added)
159
+ # @raise (see Class.method_added)
160
+ # @raise [ArgumentError] If {.version} hasn’t been set
161
+ # @return [self]
162
+ def method_added(ruby_name)
163
+ unless method.option? 'version'
164
+ raise ArgumentError, 'version not set, set it with version VERSION', caller unless defined? @version
165
+ flag '', 'version', nil, 'Display version information' do
166
+ help.version methods[Ame::Method.name(ruby_name)], self.version
167
+ throw Ame::AbortAllProcessing
168
+ end
169
+ end
170
+ super
171
+ rescue; $!.set_backtrace(caller[1..-1]); raise
172
+ end
173
+ end
174
+ end