map 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README +39 -3
  2. data/lib/map.rb +2 -1
  3. data/lib/map/options.rb +151 -0
  4. metadata +4 -6
data/README CHANGED
@@ -5,6 +5,12 @@ SYNOPSIS
5
5
  the ruby container you've always wanted: a string/symbol indifferent ordered
6
6
  hash that works in all rubies
7
7
 
8
+ maps are rad ordered hashes that are both ordered, string/symbol
9
+ indifferent, and have all sorts of sweetness like recursive convertsion,
10
+ more robust implementation than HashWithIndifferentAccess, support for
11
+ struct like (map.foo) access, and support for option/keyword access which
12
+ avoids several nasty classes of errors in many ruby libraries
13
+
8
14
  INSTALL
9
15
  gem install map
10
16
 
@@ -13,8 +19,8 @@ URI
13
19
 
14
20
  DESCRIPTION
15
21
 
16
- # maps are ordered. constructing them in an ordered fashion builds them that
17
- # way
22
+ # maps are always ordered. constructing them in an ordered fashion builds
23
+ # them that way, although the normal hash contructor is also supported
18
24
  #
19
25
  m = Map[:k, :v, :key, :val]
20
26
  m = Map(:k, :v, :key, :val)
@@ -51,5 +57,35 @@ DESCRIPTION
51
57
  s = m.struct
52
58
  p s.foo.bar #=> 42
53
59
 
60
+ # because option parsing is such a common use case for needing string/symbol
61
+ # indifference map.rb comes out of the box for option support
62
+ #
63
+ def foo(*args, &block)
64
+ opts = Map.options(args)
65
+ a = opts.getopt(:a)
66
+ b = opts.getopt(:b, :default => false)
67
+ end
68
+
69
+
70
+ opts = Map.options(:a => 42, :b => nil, :c => false)
71
+ opts.getopt(:a) #=> 42
72
+ opts.getopt(:b) #=> nil
73
+ opts.getopt(:b, :default => 42) #=> 42
74
+ opts.getopt(:c) #=> false
75
+ opts.getopt(:d, :default => false) #=> false
76
+
77
+ # this avoids such bugs as
78
+ #
79
+ options = {:read_only => true}
80
+ read_only = options[:read_only] || true # should be false but is true
81
+
82
+ # with options this becomes
83
+ #
84
+ options = Map.options(:read_only => true)
85
+ read_only = options.getopt(:read_only, :default => false) #=> true
86
+
87
+ # tons more goodness, see test/map_test.rb
88
+ #
89
+
54
90
  USAGE
55
- test/map_test.rb
91
+ again, see test/map_test.rb
data/lib/map.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  class Map < Hash
2
- Version = '1.4.0' unless defined?(Version)
2
+ Version = '1.5.0' unless defined?(Version)
3
3
  Load = Kernel.method(:load) unless defined?(Load)
4
4
 
5
5
  class << Map
@@ -452,3 +452,4 @@ private
452
452
  end
453
453
 
454
454
  Map.load('struct.rb')
455
+ Map.load('options.rb')
@@ -0,0 +1,151 @@
1
+ class Map
2
+ module Options
3
+ class << Options
4
+ def for(arg)
5
+ hash =
6
+ case arg
7
+ when Hash
8
+ arg
9
+ when Array
10
+ parse(arg)
11
+ when String, Symbol
12
+ {arg => true}
13
+ else
14
+ raise(ArgumentError, arg.inspect) unless arg.respond_to?(:to_hash)
15
+ arg.to_hash
16
+ end
17
+ map = Map.coerce(hash)
18
+ ensure
19
+ map.extend(Options) unless map.is_a?(Options)
20
+ end
21
+
22
+ def parse(arg)
23
+ case arg
24
+ when Array
25
+ arg.extend(Arguments) unless arg.is_a?(Arguments)
26
+ arg.options
27
+ when Hash
28
+ Options.for(arg)
29
+ else
30
+ raise(ArgumentError, "`arg` should be an Array or Hash")
31
+ end
32
+ end
33
+ end
34
+
35
+ attr_accessor :arguments
36
+
37
+ %w( to_options stringify_keys ).each do |method|
38
+ module_eval <<-__, __FILE__, __LINE__
39
+ def #{ method }() dup end
40
+ def #{ method }!() self end
41
+ __
42
+ end
43
+
44
+ def get_opt(opts, options = {})
45
+ options = Map.for(options.is_a?(Hash) ? options : {:default => options})
46
+ default = options[:default]
47
+ [ opts ].flatten.each do |opt|
48
+ return fetch(opt) if has_key?(opt)
49
+ end
50
+ default
51
+ end
52
+ alias_method('getopt', 'get_opt')
53
+
54
+ def get_opts(*opts)
55
+ opts.flatten.map{|opt| getopt(opt)}
56
+ end
57
+ alias_method('getopts', 'get_opts')
58
+
59
+ def has_opt(opts)
60
+ [ opts ].flatten.each do |opt|
61
+ return true if has_key?(opt)
62
+ end
63
+ false
64
+ end
65
+ alias_method('hasopt', 'has_opt')
66
+ alias_method('hasopt?', 'has_opt')
67
+ alias_method('has_opt?', 'has_opt')
68
+
69
+ def has_opts(*opts)
70
+ opts.flatten.all?{|opt| hasopt(opt)}
71
+ end
72
+ alias_method('hasopts?', 'has_opts')
73
+ alias_method('has_opts?', 'has_opts')
74
+
75
+ def del_opt(opts)
76
+ [ opts ].flatten.each do |opt|
77
+ return delete(opt) if has_key?(opt)
78
+ end
79
+ nil
80
+ end
81
+ alias_method('delopt', 'del_opt')
82
+
83
+ def del_opts(*opts)
84
+ opts.flatten.map{|opt| delopt(opt)}
85
+ opts
86
+ end
87
+ alias_method('delopts', 'del_opts')
88
+ alias_method('delopts!', 'del_opts')
89
+
90
+ def set_opt(opts, value = nil)
91
+ [ opts ].flatten.each do |opt|
92
+ return self[opt]=value
93
+ end
94
+ return value
95
+ end
96
+ alias_method('setopt', 'set_opt')
97
+ alias_method('setopt!', 'set_opt')
98
+
99
+ def set_opts(opts)
100
+ opts.each{|key, value| setopt(key, value)}
101
+ opts
102
+ end
103
+ alias_method('setopts', 'set_opts')
104
+ alias_method('setopts!', 'set_opts')
105
+
106
+ def pop
107
+ pop! unless popped?
108
+ self
109
+ end
110
+
111
+ def popped?
112
+ defined?(@popped) and @popped
113
+ end
114
+
115
+ def pop!
116
+ if arguments.last.is_a?(Hash)
117
+ @popped = arguments.pop
118
+ else
119
+ @popped = true
120
+ end
121
+ end
122
+ end
123
+
124
+ module Arguments
125
+ def options
126
+ @options ||= Options.for(last.is_a?(Hash) ? last : {})
127
+ ensure
128
+ @options.arguments = self
129
+ end
130
+
131
+ class << Arguments
132
+ def for(args)
133
+ args.extend(Arguments) unless args.is_a?(Arguments)
134
+ args
135
+ end
136
+
137
+ def parse(args)
138
+ [args, Options.parse(args)]
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+
145
+ def Map.options(*args, &block)
146
+ Map::Options.for(*args, &block)
147
+ end
148
+
149
+ def Map.opts(*args, &block)
150
+ Map::Options.for(*args, &block)
151
+ end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: map
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
5
4
  prerelease: false
6
5
  segments:
7
6
  - 1
8
- - 4
7
+ - 5
9
8
  - 0
10
- version: 1.4.0
9
+ version: 1.5.0
11
10
  platform: ruby
12
11
  authors:
13
12
  - Ara T. Howard
@@ -15,7 +14,7 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-10-21 00:00:00 -06:00
17
+ date: 2010-10-28 00:00:00 -06:00
19
18
  default_executable:
20
19
  dependencies: []
21
20
 
@@ -29,6 +28,7 @@ extra_rdoc_files: []
29
28
 
30
29
  files:
31
30
  - a.rb
31
+ - lib/map/options.rb
32
32
  - lib/map/struct.rb
33
33
  - lib/map.rb
34
34
  - Rakefile
@@ -50,7 +50,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- hash: 3
54
53
  segments:
55
54
  - 0
56
55
  version: "0"
@@ -59,7 +58,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
59
58
  requirements:
60
59
  - - ">="
61
60
  - !ruby/object:Gem::Version
62
- hash: 3
63
61
  segments:
64
62
  - 0
65
63
  version: "0"