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,16 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Represents a splat argument to a {Method}, which works just like a {Splus},
4
+ # except that it won’t fail if there are no more arguments left.
5
+ # @api developer
6
+ class Ame::Splat < Ame::Splus
7
+ # Processes each argument in ARGUMENTS via {Argument#process}.
8
+ # @api internal
9
+ # @param (see Argument#process)
10
+ # @raise [Ame::MalformedArgument] If the receiver couldn’t be parsed or
11
+ # validated
12
+ # @return [Array<Object>]
13
+ def process(options, processed, arguments)
14
+ arguments.empty? ? [] : super
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Represents a splus argument to a {Method}, which works just like a normal
4
+ # {Argument}, except that it’ll process all remaining arguments.
5
+ # @api developer
6
+ class Ame::Splus < Ame::Argument
7
+ # Processes each argument in ARGUMENTS via {Argument#process}.
8
+ # @api internal
9
+ # @param (see Argument#process)
10
+ # @raise [Ame::MissingArgument] If ARGUMENTS#empty?
11
+ # @raise [Ame::MalformedArgument] If the receiver couldn’t be parsed or
12
+ # validated
13
+ # @return [Array<Object>]
14
+ def process(options, processed, arguments)
15
+ super options, processed, arguments if arguments.empty?
16
+ [].tap{ |r|
17
+ until arguments.empty?
18
+ r << super(options, processed, arguments)
19
+ end
20
+ }
21
+ end
22
+ end
@@ -0,0 +1,39 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Represents an option to a {Method} that takes an optional argument. If an
4
+ # explicit (‘=’-separated) argument is given, it’ll be used, otherwise a
5
+ # default value, which differs from the default value used if the option isn’t
6
+ # given at all, will be used.
7
+ # @api developer
8
+ class Ame::Switch < Ame::Flag
9
+ # @api internal
10
+ # @param (see Flag#initialize)
11
+ # @param [String] argument
12
+ # @param [Object] default
13
+ # @param [Object] argument_default
14
+ # @yield (see Flag#initialize)
15
+ # @yieldparam [Hash<String, Object>] options
16
+ # @yieldparam [Object] value
17
+ # @raise (see Flag#initialize)
18
+ # @raise [ArgumentError] If the type of ARGUMENT_DEFAULT or, if
19
+ # ARGUMENT_DEFAULT is nil, DEFAULT isn’t one that Ame knows how to parse
20
+ def initialize(short, long, argument, default, argument_default, description, &validate)
21
+ @argument = argument.upcase
22
+ @type = Ame::Types[[argument_default, default, String].reject(&:nil?).first]
23
+ @argument_default = @type.respond_to?(:default) ? @type.default : argument_default
24
+ super short, long, default, description, &validate
25
+ end
26
+
27
+ # @return [String] The name of the argument to the receiver
28
+ attr_reader :argument
29
+
30
+ private
31
+
32
+ # @api internal
33
+ # @param (see Flag#parse)
34
+ # @return [Object] The parsed value of EXPLICIT, if non-nil, the default
35
+ # argument value otherwise
36
+ def parse(arguments, explicit)
37
+ explicit ? @type.parse(explicit) : @argument_default
38
+ end
39
+ end
@@ -0,0 +1,60 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Types registered with Ame for parsing command-line arguments into Ruby
4
+ # values. By default, Ruby classes TrueClass, FalseClass, Float, Integer,
5
+ # String, and Symbol are registered, as well as an {Enumeration} type for
6
+ # limiting a Symbol to one of a fixed set.
7
+ module Ame::Types
8
+ @types = {}
9
+
10
+ class << self
11
+ # Registers TYPE for parsing command-line arguments for Ruby values whose
12
+ # class is any of CLASSES. The TYPE should respond to #parse(String),
13
+ # which should convert its String argument into a Ruby value, and may
14
+ # optionally respond to #default, which should return the default value of
15
+ # the TYPE, if any.
16
+ # @param [#parse, #default] type
17
+ # @param [::Class, …] classes
18
+ # @return [self]
19
+ # @example Registering a New Type
20
+ # require 'pathname'
21
+ #
22
+ # module My::Pathname
23
+ # Ame::Types.register self, Pathname
24
+ #
25
+ # def parse(argument)
26
+ # Pathname(argument)
27
+ # end
28
+ # end
29
+ # @example Using a New Type as a Type
30
+ # class Rm < Ame::Root
31
+ # …
32
+ # splus 'FILE', My::Pathname, 'File to remove'
33
+ # def rm(pathnames)
34
+ # pathnames.each do |e| e.rmtree end
35
+ # end
36
+ # end
37
+ # @example Using a New Types as a Default
38
+ # class My < Ame::Root
39
+ # optional 'CONFIG', Pathname('/etc/my/config'), 'Configuration file to use'
40
+ def register(type, *classes)
41
+ classes.each do |c|
42
+ @types[c] = type
43
+ end
44
+ self
45
+ end
46
+
47
+ # @api developer
48
+ # @return [Object] The type registered to parse arguments into values of
49
+ # CLASS_OR_VALUE or of the class of CLASS_OR_VALUE, alternatively using
50
+ # CLASS_OR_VALUE itself if it responds to #parse
51
+ # @raise [ArgumentError] If a type that handles CLASS_OR_VALUE hasn’t been
52
+ # registered
53
+ def [](class_or_value)
54
+ type = @types[class_or_value] and return type
55
+ pair = @types.find{ |c, t| class_or_value.is_a? c } and return pair.last
56
+ class_or_value.respond_to? :parse and return class_or_value
57
+ raise ArgumentError, 'unknown type: %p' % [class_or_value]
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,13 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Ame::Types::Boolean
4
+ Ame::Types.register self, TrueClass, FalseClass
5
+
6
+ def self.parse(argument)
7
+ case argument
8
+ when 'true', 'yes', 'on' then true
9
+ when 'false', 'no', 'off' then false
10
+ else raise Ame::MalformedArgument, 'not a boolean: %s' % argument
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,40 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Enumeration type for limiting a Symbol argument to one in a fixed set. It
4
+ # also has a {#default}, which will be the first symbol passed to its
5
+ # constructor.
6
+ # @example Using an Enumeration
7
+ # class Git::CLI::Git::FormatPatch < Ame::Class
8
+ # switch '', 'thread', 'STYLE', nil,
9
+ # Ame::Types::Enumeration[:shallow, :deep],
10
+ # 'Controls addition of In-Reply-To and References headers'
11
+ class Ame::Types::Enumeration
12
+ class << self
13
+ # Alias for .new.
14
+ alias [] new
15
+ end
16
+
17
+ # Creates an Enumeration of valid Symbols FIRST, SECOND, and REST for an
18
+ # argument and sets {#default} to FIRST.
19
+ # @param [#to_sym] first
20
+ # @param [#to_sym] second
21
+ # @param [#to_sym, …] rest
22
+ def initialize(first, second, *rest)
23
+ @default = first
24
+ @names = ([first, second] + rest).map(&:to_sym)
25
+ end
26
+
27
+ # @api internal
28
+ # @param [String] argument
29
+ # @return [Symbol] The result of ARGUMENT#to_sym
30
+ # @raise [MalformedArgument] If ARGUMENT#to_sym isn’t included among the
31
+ # valid Symbols
32
+ def parse(argument)
33
+ @names.include?(s = argument.to_sym) ? s :
34
+ raise(Ame::MalformedArgument, 'must be one of %s, not %s' %
35
+ [@names.join(', '), argument])
36
+ end
37
+
38
+ # @return [Symbol] The Symbol to use if no argument has been given
39
+ attr_reader :default
40
+ end
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Ame::Types::Float
4
+ Ame::Types.register self, Float
5
+
6
+ def self.parse(argument)
7
+ Float(argument)
8
+ rescue ArgumentError
9
+ raise Ame::MalformedArgument, 'not a float: %s' % argument
10
+ end
11
+ end
@@ -3,9 +3,9 @@
3
3
  module Ame::Types::Integer
4
4
  Ame::Types.register self, Integer
5
5
 
6
- def self.parse(value)
7
- Integer(value)
6
+ def self.parse(argument)
7
+ Integer(argument)
8
8
  rescue ArgumentError
9
- raise Ame::MalformedArgument, 'not an integer: %s' % value
9
+ raise Ame::MalformedArgument, 'not an integer: %s' % argument
10
10
  end
11
11
  end
@@ -3,7 +3,7 @@
3
3
  module Ame::Types::String
4
4
  Ame::Types.register self, String
5
5
 
6
- def self.parse(value)
7
- value
6
+ def self.parse(argument)
7
+ argument
8
8
  end
9
9
  end
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Ame::Types::Symbol
4
+ Ame::Types.register self, Symbol
5
+
6
+ def self.parse(argument)
7
+ argument.to_sym
8
+ end
9
+ end
@@ -0,0 +1,62 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'inventory-1.0'
4
+
5
+ module Ame
6
+ Version = Inventory.new(1, 0, 1){
7
+ authors{
8
+ author 'Nikolai Weibull', 'now@disu.se'
9
+ }
10
+
11
+ homepage 'http://disu.se/software/ame-1.0/'
12
+
13
+ licenses{
14
+ license 'LGPLv3+',
15
+ 'GNU Lesser General Public License, version 3 or later',
16
+ 'http://www.gnu.org/licenses/'
17
+ }
18
+
19
+ def dependencies
20
+ super + Inventory::Dependencies.new{
21
+ development 'inventory-rake', 1, 6, 0
22
+ development 'inventory-rake-tasks-yard', 1, 4, 0
23
+ development 'lookout', 3, 0, 0
24
+ development 'lookout-rake', 3, 1, 0
25
+ development 'yard', 0, 8, 0
26
+ development 'yard-heuristics', 1, 2, 0
27
+ }
28
+ end
29
+
30
+ def package_libs
31
+ %w[argument.rb
32
+ arguments.rb
33
+ arguments/undefined.rb
34
+ arguments/optional.rb
35
+ arguments/complete.rb
36
+ class.rb
37
+ flag.rb
38
+ help.rb
39
+ help/terminal.rb
40
+ help/delegate.rb
41
+ method.rb
42
+ method/undefined.rb
43
+ methods.rb
44
+ switch.rb
45
+ option.rb
46
+ multioption.rb
47
+ optional.rb
48
+ options.rb
49
+ options/undefined.rb
50
+ root.rb
51
+ splus.rb
52
+ splat.rb
53
+ types.rb
54
+ types/boolean.rb
55
+ types/enumeration.rb
56
+ types/float.rb
57
+ types/integer.rb
58
+ types/string.rb
59
+ types/symbol.rb]
60
+ end
61
+ }
62
+ end
@@ -0,0 +1,4 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Expectations do
4
+ end
@@ -0,0 +1,46 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Expectations do
4
+ expect 'a' do Ame::Argument.new('a', String, 'd').name end
5
+
6
+ expect 'd' do Ame::Argument.new('a', String, 'd').description end
7
+
8
+ expect 'A' do Ame::Argument.new('a', String, 'd').to_s end
9
+
10
+ expect Ame::MissingArgument do Ame::Argument.new('a', String, 'd').process({}, [], []) end
11
+ expect 'string' do Ame::Argument.new('a', String, 'd').process({}, [], ['string']) end
12
+
13
+ expect 1 do Ame::Argument.new('a', Integer, 'd').process({}, [], ['1']) end
14
+ expect Ame::MalformedArgument.new('A: not an integer: junk') do
15
+ Ame::Argument.new('a', Integer, 'd').process({}, [], ['junk'])
16
+ end
17
+
18
+ expect TrueClass do Ame::Argument.new('a', TrueClass, 'd').process({}, [], ['true']) end
19
+ expect Ame::MalformedArgument.new('A: not a boolean: junk') do
20
+ Ame::Argument.new('a', TrueClass, 'd').process({}, [], ['junk'])
21
+ end
22
+
23
+ expect FalseClass do Ame::Argument.new(:a, FalseClass, 'd').process({}, [], ['false']) end
24
+ expect Ame::MalformedArgument.new('A: not a boolean: junk') do
25
+ Ame::Argument.new('a', FalseClass, 'd').process({}, [], ['junk'])
26
+ end
27
+
28
+ expect :a => 1 do
29
+ options = nil
30
+ Ame::Argument.new('a', Integer, 'd'){ |o, p, a| options = o }.process({:a => 1}, [1], ['2'])
31
+ options
32
+ end
33
+ expect [1] do
34
+ processed = nil
35
+ Ame::Argument.new('a', Integer, 'd'){ |o, p, a| processed = p }.process({:a => 1}, [1], ['2'])
36
+ processed
37
+ end
38
+ expect 2 do
39
+ argument = nil
40
+ Ame::Argument.new('a', Integer, 'd'){ |o, p, a| argument = a }.process({:a => 1}, [1], ['2'])
41
+ argument
42
+ end
43
+ expect 3 do
44
+ Ame::Argument.new('a', Integer, 'd'){ |o, p, a| 3 }.process({:a => 1}, [1], ['2'])
45
+ end
46
+ end
@@ -0,0 +1,63 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Expectations do
4
+ expect Enumerable do Ame::Arguments::Undefined.new.define end
5
+
6
+ expect Ame::MissingArgument do
7
+ Ame::Arguments::Undefined.new.
8
+ argument('a', String, 'd').
9
+ define.
10
+ process({}, [])
11
+ end
12
+
13
+ expect [] do
14
+ Ame::Arguments::Undefined.new.
15
+ define.
16
+ process({}, [])
17
+ end
18
+
19
+ expect [1] do
20
+ Ame::Arguments::Undefined.new.
21
+ argument('a', Integer, 'd').
22
+ define.
23
+ process({}, %w[1])
24
+ end
25
+
26
+ expect [1, TrueClass] do
27
+ Ame::Arguments::Undefined.new.
28
+ argument('a', Integer, 'd').
29
+ argument('b', FalseClass, 'd').
30
+ define.
31
+ process({}, %w[1 true])
32
+ end
33
+
34
+ expect Ame::MissingArgument do
35
+ Ame::Arguments::Undefined.new.
36
+ argument('a', 'd', :type => Integer).
37
+ splus('b', String, 'd').
38
+ define.
39
+ process({}, %w[1])
40
+ end
41
+
42
+ expect [1, []] do
43
+ Ame::Arguments::Undefined.new.
44
+ argument('a', Integer, 'd').
45
+ splat('b', String, 'd').
46
+ define.
47
+ process({}, %w[1])
48
+ end
49
+
50
+ expect [1, [2, 3]] do
51
+ Ame::Arguments::Undefined.new.
52
+ argument('a', Integer, 'd').
53
+ splus('b', Integer, 'd').
54
+ define.
55
+ process({}, %w[1 2 3])
56
+ end
57
+
58
+ expect Ame::SuperfluousArgument do
59
+ Ame::Arguments::Undefined.new.
60
+ define.
61
+ process({}, %w[1])
62
+ end
63
+ end
@@ -0,0 +1,4 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Expectations do
4
+ end
@@ -0,0 +1,4 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Expectations do
4
+ end
@@ -0,0 +1,63 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Expectations do
4
+ expect ArgumentError.new("argument 'b', … may not follow optional 'a', …") do
5
+ Ame::Arguments::Undefined.new.
6
+ optional('a', nil, 'd').
7
+ argument('b', String, 'd')
8
+ end
9
+
10
+ expect ArgumentError.new("splus 'b', … may not follow optional 'a', …") do
11
+ Ame::Arguments::Undefined.new.
12
+ optional('a', nil, 'd').
13
+ splus('b', String, 'd')
14
+ end
15
+
16
+ expect ArgumentError.new("argument 'b', … may not follow splat 'a', …") do
17
+ Ame::Arguments::Undefined.new.
18
+ splat('a', String, 'd').
19
+ argument('b', String, 'd')
20
+ end
21
+
22
+ expect ArgumentError.new("optional 'b', … may not follow splat 'a', …") do
23
+ Ame::Arguments::Undefined.new.
24
+ splat('a', String, 'd').
25
+ optional('b', String, 'd')
26
+ end
27
+
28
+ expect ArgumentError.new("splat 'b', … may not follow splat 'a', …") do
29
+ Ame::Arguments::Undefined.new.
30
+ splat('a', String, 'd').
31
+ splat('b', String, 'd')
32
+ end
33
+
34
+ expect ArgumentError.new("splus 'b', … may not follow splat 'a', …") do
35
+ Ame::Arguments::Undefined.new.
36
+ splat('a', String, 'd').
37
+ splus('b', String, 'd')
38
+ end
39
+
40
+ expect ArgumentError.new("argument 'b', … may not follow splus 'a', …") do
41
+ Ame::Arguments::Undefined.new.
42
+ splus('a', String, 'd').
43
+ argument('b', String, 'd')
44
+ end
45
+
46
+ expect ArgumentError.new("optional 'b', … may not follow splus 'a', …") do
47
+ Ame::Arguments::Undefined.new.
48
+ splus('a', String, 'd').
49
+ optional('b', String, 'd')
50
+ end
51
+
52
+ expect ArgumentError.new("splat 'b', … may not follow splus 'a', …") do
53
+ Ame::Arguments::Undefined.new.
54
+ splus('a', String, 'd').
55
+ splat('b', String, 'd')
56
+ end
57
+
58
+ expect ArgumentError.new("splus 'b', … may not follow splus 'a', …") do
59
+ Ame::Arguments::Undefined.new.
60
+ splus('a', String, 'd').
61
+ splus('b', String, 'd')
62
+ end
63
+ end