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
@@ -1,30 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- class Ame::Methods
4
- include Enumerable
5
-
6
- def initialize
7
- @methods = {}
8
- end
9
-
10
- def <<(method)
11
- @methods[method.name] = method
12
- self
13
- end
14
-
15
- def [](name)
16
- @methods[name.to_sym] or
17
- raise Ame::UnrecognizedMethod, 'unrecognized method: %s' % name
18
- end
19
-
20
- def include?(name)
21
- @methods.include? name.to_sym
22
- end
23
-
24
- def each
25
- @methods.each_value do |method|
26
- yield method
27
- end
28
- self
29
- end
30
- end
@@ -1,50 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- class Ame::Option < Ame::Argument
4
- def initialize(name, description, options = {}, &validate)
5
- is_boolean_type = [TrueClass, FalseClass].include? options[:type]
6
- options[:default] = false unless options.include? :default or options.include? :type
7
- if is_boolean_type and not options.include? :default
8
- options[:default] = options[:type] == FalseClass
9
- end
10
- is_boolean = [true, false].include? options[:default]
11
- raise ArgumentError,
12
- 'optional arguments to options are only allowed for booleans' if
13
- options[:optional] and not(is_boolean_type or is_boolean)
14
- options[:optional] = is_boolean
15
- raise ArgumentError,
16
- 'boolean options cannot have argument descriptions' if
17
- is_boolean and options[:argument]
18
- @argument_name = is_boolean ? "" : (options[:argument] || name).to_s
19
- @aliases = Array(options[:alias]) + Array(options[:aliases])
20
- @ignored = options[:ignore]
21
- super
22
- end
23
-
24
- def to_s
25
- (name.to_s.length > 1 ? '--%s' : '-%s') % name
26
- end
27
-
28
- attr_reader :argument_name, :aliases
29
-
30
- def short
31
- [name, *aliases].find{ |a| a.to_s.length == 1 }
32
- end
33
-
34
- def long
35
- [name, *aliases].find{ |a| a.to_s.length > 1 }
36
- end
37
-
38
- def ignored?
39
- @ignored
40
- end
41
-
42
- private
43
-
44
- def set_default(value, type)
45
- saved_optional, @optional = @optional, true
46
- super
47
- ensure
48
- @optional = saved_optional
49
- end
50
- end
@@ -1,102 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- class Ame::Options
4
- include Enumerable
5
-
6
- def initialize
7
- @options = {}
8
- @ordered = []
9
- @options_must_precede_arguments = ENV.include? 'POSIXLY_CORRECT'
10
- end
11
-
12
- def option(name, description, options = {}, &block)
13
- option = Ame::Option.new(name, description, options, &block)
14
- self[option.name] = option
15
- option.aliases.each do |a|
16
- self[a] = option
17
- end
18
- @ordered << option
19
- self
20
- end
21
-
22
- def options_must_precede_arguments
23
- @options_must_precede_arguments = true
24
- self
25
- end
26
-
27
- def process(arguments)
28
- process!(defaults, arguments.dup)
29
- end
30
-
31
- def each
32
- @ordered.each do |option|
33
- yield option
34
- end
35
- self
36
- end
37
-
38
- def include?(name)
39
- @options.include? name.to_s
40
- end
41
-
42
- private
43
-
44
- def []=(name, option)
45
- raise ArgumentError,
46
- 'option already defined: %s' % name if include? name
47
- @options[name.to_s] = option
48
- end
49
-
50
- def [](name)
51
- @options[name.to_s.sub(/^-+/, "")] or
52
- raise Ame::UnrecognizedOption, 'unrecognized option: %s' % name
53
- end
54
-
55
- def defaults
56
- @ordered.reduce({}){ |d, o| d[o.name] = o.default; d }
57
- end
58
-
59
- def process!(results, arguments)
60
- remainder = []
61
- until arguments.empty?
62
- case first = arguments.shift
63
- when '--'
64
- break
65
- when /^-([^=-]{2,})$/
66
- process_combined results, arguments, $1
67
- when /^(--[^=]+|-[^-])(?:=(.*))?$/
68
- process1 results, arguments, self[$1], $2
69
- else
70
- remainder << first
71
- break if @options_must_precede_arguments
72
- end
73
- end
74
- [results.reject{ |n, _| self[n].ignored? }, remainder.concat(arguments)]
75
- end
76
-
77
- def process_combined(results, arguments, combined)
78
- combined.each_char.with_index do |c, i|
79
- option = self['-' + c]
80
- if option.optional?
81
- process1 results, [], option, nil
82
- elsif i == combined.length - 1
83
- process1 results, arguments, option, nil
84
- else
85
- process1 results, [], option, combined[i+1..-1]
86
- break
87
- end
88
- end
89
- end
90
-
91
- def process1(results, arguments, option, arg)
92
- results[option.name] = option.process(results, [], argument(arguments, option, arg))
93
- end
94
-
95
- def argument(arguments, option, argument)
96
- case
97
- when argument then argument
98
- when option.optional? then (!option.default).to_s
99
- else arguments.shift
100
- end
101
- end
102
- end
@@ -1,57 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- class Ame::Root < Ame::Class
4
- class << self
5
- def basename
6
- ''
7
- end
8
-
9
- def process(method = File.basename($0), arguments = ARGV)
10
- new.process(method, arguments)
11
- rescue => e
12
- help_for_error method, e
13
- end
14
-
15
- def help(help = nil)
16
- return @help = help if help
17
- @help ||= Ame::Help::Console.new
18
- end
19
-
20
- def help_for_dispatch(method, subclass)
21
- help.for_dispatch method, subclass
22
- end
23
-
24
- def help_for_method(method)
25
- help.for_method method
26
- end
27
-
28
- private
29
-
30
- def help_for_error(method, error)
31
- help.for_error method, error
32
- end
33
-
34
- def method_added(name)
35
- m = method
36
- option :version, 'Display version information', :ignore => true do
37
- help.version self, m
38
- throw Ame::AbortAllProcessing
39
- end unless method.options.include? :version
40
- super
41
- end
42
- end
43
-
44
- def process(name, arguments = [])
45
- catch Ame::AbortAllProcessing do
46
- super
47
- end
48
- self
49
- end
50
-
51
- def call(name, arguments = nil, options = nil)
52
- catch Ame::AbortAllProcessing do
53
- super
54
- end
55
- self
56
- end
57
- end
@@ -1,12 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- class Ame::Splat < Ame::Argument
4
- def arity
5
- -1
6
- end
7
-
8
- def process(options, processed, arguments)
9
- super options, processed, nil if required? and arguments.empty?
10
- arguments.map{ |argument| super(options, processed, argument) }.tap{ arguments.clear }
11
- end
12
- end
@@ -1,29 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- module Ame::Types
4
- class << self
5
- def register(type, *classes)
6
- classes.each do |c|
7
- types[c] = type
8
- end
9
- end
10
-
11
- def [](class_or_value)
12
- type = types[class_or_value] and return type
13
- pair = types.find{ |c, t| class_or_value.is_a? c } and return pair.last
14
- class_or_value.respond_to? :parse and return class_or_value
15
- raise ArgumentError, 'unknown type: %p' % class_or_value
16
- end
17
-
18
- private
19
-
20
- def types
21
- @types ||= {}
22
- end
23
- end
24
-
25
- autoload :Array, 'ame/types/array'
26
- require 'ame/types/boolean'
27
- require 'ame/types/integer'
28
- require 'ame/types/string'
29
- end
@@ -1,16 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- class Ame::Types::Array
4
- class << self
5
- alias_method :[], :new
6
- end
7
-
8
- def initialize(type)
9
- @type = Ame::Types[type]
10
- @contents = []
11
- end
12
-
13
- def parse(value)
14
- @contents << @type.parse(value)
15
- end
16
- end
@@ -1,16 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- module Ame::Types::Boolean
4
- Ame::Types.register self, TrueClass, FalseClass
5
-
6
- def self.parse(value)
7
- case value
8
- when 'true', 'yes', 'on'
9
- true
10
- when 'false', 'no', 'off'
11
- false
12
- else
13
- raise Ame::MalformedArgument, 'not a boolean: %s' % value
14
- end
15
- end
16
- end
@@ -1,5 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- module Ame
4
- Version = '0.1.1'
5
- end
@@ -1,13 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- Expectations do
4
- expect Ame::Types::Array do Ame::Types::Array[String] end
5
- expect [''] do Ame::Types::Array[String].parse('') end
6
- expect [1] do Ame::Types::Array[Integer].parse('1') end
7
- expect [1, 2, 3] do
8
- ary = Ame::Types::Array[Integer]
9
- ary.parse('1')
10
- ary.parse('2')
11
- ary.parse('3')
12
- end
13
- end
@@ -1,66 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- Expectations do
4
- expect :a do Ame::Argument.new(:a, 'd').name end
5
-
6
- expect 'd' do Ame::Argument.new(:a, 'd').description end
7
-
8
- expect 1 do Ame::Argument.new(:a, 'd').arity end
9
-
10
- expect Ame::Argument.new(:a, 'd').not.to.be.optional?
11
- expect Ame::Argument.new(:a, 'd', :optional => true).to.be.optional?
12
-
13
- expect Ame::Argument.new(:a, 'd').to.be.required?
14
- expect Ame::Argument.new(:a, 'd', :optional => true).not.to.be.required?
15
-
16
- expect 'A' do Ame::Argument.new(:a, 'd').to_s end
17
-
18
- expect ArgumentError do Ame::Argument.new(:a, 'd', :default => 1) end
19
- expect 1 do Ame::Argument.new(:a, 'd', :optional => true, :default => 1).default end
20
-
21
- expect ArgumentError do Ame::Argument.new(:a, 'd', :optional => true, :type => String, :default => 1) end
22
- expect 1 do Ame::Argument.new(:a, 'd', :optional => true, :type => Integer, :default => 1).default end
23
- expect ArgumentError do Ame::Argument.new(:a, 'd', :optional => true, :type => TrueClass, :default => false) end
24
-
25
- expect Ame::MissingArgument do Ame::Argument.new(:a, 'd').process({}, [], nil) end
26
- expect nil do Ame::Argument.new(:a, 'd', :optional => true).process({}, [], nil) end
27
- expect 'default' do Ame::Argument.new(:a, 'd', :optional => true, :default => 'default').process({}, [], nil) end
28
- expect 'string' do Ame::Argument.new(:a, 'd').process({}, [], 'string') end
29
-
30
- expect 1 do Ame::Argument.new(:a, 'd', :type => Integer).process({}, [], '1') end
31
- expect 2 do Ame::Argument.new(:a, 'd', :optional => true, :default => 1).process({}, [], '2') end
32
- expect Ame::MalformedArgument.new('A: not an integer: junk') do
33
- Ame::Argument.new(:a, 'd', :type => Integer).process({}, [], 'junk')
34
- end
35
-
36
- expect TrueClass do Ame::Argument.new(:a, 'd', :type => TrueClass).process({}, [], 'true') end
37
- expect TrueClass do Ame::Argument.new(:a, 'd', :optional => true, :default => true).process({}, [], nil) end
38
- expect Ame::MalformedArgument.new('A: not a boolean: junk') do
39
- Ame::Argument.new(:a, 'd', :type => TrueClass).process({}, [], 'junk')
40
- end
41
-
42
- expect FalseClass do Ame::Argument.new(:a, 'd', :type => FalseClass).process({}, [], 'false') end
43
- expect FalseClass do Ame::Argument.new(:a, 'd', :optional => true, :default => false).process({}, [], nil) end
44
- expect Ame::MalformedArgument.new('A: not a boolean: junk') do
45
- Ame::Argument.new(:a, 'd', :type => FalseClass).process({}, [], 'junk')
46
- end
47
-
48
- expect :a => 1 do
49
- options = nil
50
- Ame::Argument.new(:a, 'd', :type => Integer){ |o, p, a| options = o }.process({:a => 1}, [1], '2')
51
- options
52
- end
53
- expect [1] do
54
- processed = nil
55
- Ame::Argument.new(:a, 'd', :type => Integer){ |o, p, a| processed = p }.process({:a => 1}, [1], '2')
56
- processed
57
- end
58
- expect 2 do
59
- argument = nil
60
- Ame::Argument.new(:a, 'd', :type => Integer){ |o, p, a| argument = a }.process({:a => 1}, [1], '2')
61
- argument
62
- end
63
- expect 3 do
64
- Ame::Argument.new(:a, 'd', :type => Integer){ |o, p, a| 3 }.process({:a => 1}, [1], '2')
65
- end
66
- end
@@ -1,106 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- Expectations do
4
- expect Enumerable do Ame::Arguments.new end
5
-
6
- expect 0 do
7
- Ame::Arguments.new.arity
8
- end
9
- expect 1 do
10
- Ame::Arguments.new.argument(:a, 'd').arity
11
- end
12
- expect(-1) do
13
- Ame::Arguments.new.argument(:a, 'd', :optional => true).arity
14
- end
15
- expect 2 do
16
- Ame::Arguments.new.argument(:a, 'd').argument(:b, 'd').arity
17
- end
18
- expect(-2) do
19
- Ame::Arguments.new.argument(:a, 'd').
20
- argument(:b, 'd', :optional => true).arity
21
- end
22
- expect(-3) do
23
- Ame::Arguments.new.argument(:a, 'd').
24
- argument(:b, 'd').
25
- argument(:c, 'd', :optional => true).arity
26
- end
27
- expect(-4) do
28
- Ame::Arguments.new.argument(:a, 'd').
29
- argument(:b, 'd').
30
- splat(:c, 'd').arity
31
- end
32
- expect(-3) do
33
- Ame::Arguments.new.argument(:a, 'd').
34
- argument(:b, 'd').
35
- splat(:c, 'd', :optional => true).arity
36
- end
37
- expect(-3) do
38
- Ame::Arguments.new.argument(:a, 'd').
39
- argument(:b, 'd').
40
- argument(:c, 'd', :optional => true).
41
- argument(:d, 'd', :optional => true).arity
42
- end
43
- expect(-3) do
44
- Ame::Arguments.new.argument(:a, 'd').splat(:b, 'd').arity
45
- end
46
-
47
- expect ArgumentError.new('argument b must come before splat argument a') do
48
- Ame::Arguments.new.splat(:a, 'd').argument(:b, 'd')
49
- end
50
-
51
- expect ArgumentError.new('optional argument a may not precede required argument b') do
52
- Ame::Arguments.new.argument(:a, 'd', :optional => true).argument(:b, 'd')
53
- end
54
-
55
- expect ArgumentError.new('splat argument a already defined: b') do
56
- Ame::Arguments.new.splat(:a, 'd').splat(:b, 'd')
57
- end
58
-
59
- expect ArgumentError.new('optional argument a may not precede required splat argument b') do
60
- Ame::Arguments.new.argument(:a, 'd', :optional => true).splat(:b, 'd')
61
- end
62
-
63
- expect Ame::MissingArgument do
64
- Ame::Arguments.new.argument(:a, 'd').process({}, [])
65
- end
66
-
67
- expect [] do
68
- Ame::Arguments.new.process({}, [])
69
- end
70
-
71
- expect [1] do
72
- Ame::Arguments.new.argument(:a, 'd', :type => Integer).process({}, %w[1])
73
- end
74
-
75
- expect [1, TrueClass] do
76
- Ame::Arguments.new.argument(:a, 'd', :type => Integer).
77
- argument(:b, 'd', :type => FalseClass).
78
- process({}, %w[1 true])
79
- end
80
-
81
- expect Ame::MissingArgument do
82
- Ame::Arguments.new.argument(:a, 'd', :type => Integer).
83
- splat(:b, 'd').
84
- process({}, %w[1])
85
- end
86
-
87
- expect [1, []] do
88
- Ame::Arguments.new.argument(:a, 'd', :type => Integer).
89
- splat(:b, 'd', :optional => true).
90
- process({}, %w[1])
91
- end
92
-
93
- expect [1, [2, 3]] do
94
- Ame::Arguments.new.argument(:a, 'd', :type => Integer).
95
- splat(:b, 'd', :type => Integer).
96
- process({}, %w[1 2 3])
97
- end
98
-
99
- expect Ame::Splat do
100
- Ame::Arguments.new.splat(:a, 'd').splat
101
- end
102
-
103
- expect Ame::SuperfluousArgument do
104
- Ame::Arguments.new.process({}, %w[1])
105
- end
106
- end