mobj 1.0.0 → 1.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README.md +4 -59
  2. data/lib/mobj.rb +99 -58
  3. metadata +2 -2
data/README.md CHANGED
@@ -1,71 +1,16 @@
1
- ctx
1
+ mobj
2
2
  ===
3
3
 
4
- Simple utility to limit method redefinition within the bounds of arbitrary logical scopes
4
+ Some utilities that I keep using.
5
5
 
6
6
  Example
7
7
  ===
8
8
 
9
- Here, figure it out:
10
-
11
- require 'ctx'
12
-
13
- class ::String
14
- ctx :reversaroo do
15
- def +(other)
16
- "#{other.reverse}#{self.reverse}"
17
- end
18
- end
19
- ctx :camels do
20
- def +(other)
21
- "#{self.capitalize}#{other.capitalize}"
22
- end
23
- end
24
- ctx :polite do
25
- def +(other)
26
- "I say, good day to you there '#{other}', may I introduce you to my good friend '#{self}'?"
27
- end
28
- end
29
- ctx do
30
- def +(other)
31
- "#{self} + #{other} = ?"
32
- end
33
- end
34
- end
35
-
36
- puts "hello" + "world"
37
- #=> helloworld
38
-
39
- ctx :camels do
40
- puts "hello" + "world"
41
- #=> HelloWorld
42
-
43
- ctx :polite do
44
- puts "hello" + "world"
45
- #=> I say, good day to you there 'world', may I introduce you to my good friend 'hello'?
46
- end
47
-
48
- ctx do
49
- puts "hello" + "world"
50
- #=> hello + world = ?
51
- end
52
- end
53
-
54
- ctx :reversaroo do
55
- puts "hello" + "world"
56
- #=> dlrowolleh
57
- end
58
-
59
- puts "hello" + "world"
60
- #=> helloworld
61
-
62
-
63
- There are bugs. You'll find them.
9
+ Read the code.
64
10
 
65
11
  ---
66
12
 
67
13
  Caveats and such
68
14
  ===
69
15
 
70
- For whatever goofy reason, this stuff doesn't play well with rspec all the time, particularly if you override stuff the matchers are hoping to also override, like == or =~ on String, or whatnot. Don't do that right now unless you like stuff to break in inexplicable ways. Personally, I do like that kind of stuff, makes life interesting (kind of explains my dating choices, when you get right down to it), but anywhoo, honestly, it's your call.
71
-
16
+ None. It's prefection.
data/lib/mobj.rb CHANGED
@@ -1,18 +1,29 @@
1
1
  module Mobj
2
2
 
3
- class ::BasicObject
3
+ class ::Object
4
+ alias responds_to? respond_to?
4
5
  def sym() respond_to?(:to_sym) ? to_sym : to_s.to_sym end
5
- def mparent(rent = :mparent) @mparent = rent unless rent == :mparent; @mparent end
6
- def mroot() mparent.nil? ? self : mparent.mroot end
6
+ def mroot() mparent.nil? || mparent == self ? self : mparent.mroot end
7
+ def reparent() values.each { |v| v.mparent(self); v.reparent } if respond_to? :values end
8
+ def mparent(rent = :mparent)
9
+ unless rent == :mparent
10
+ @mparent = rent == self ? nil : rent
11
+ end
12
+ @mparent
13
+ end
7
14
  end
8
15
 
9
16
  class ::Class
10
- def object_methods() (self.instance_methods - Object.instance_methods).sort end
11
- def class_methods() (self.singleton_methods - Object.singleton_methods).sort end
17
+ def object_methods() (self.instance_methods(true) - Object.instance_methods(true)).sort end
18
+ def class_methods() (self.singleton_methods(true) - Object.singleton_methods(true)).sort end
12
19
  def defined_methods() (class_methods | object_methods).sort end
13
20
  end
14
21
 
15
22
  class ::Array
23
+ alias includes? include?
24
+ alias contains? include?
25
+
26
+ def values() self end
16
27
  def sequester(lim = 1) compact.size <= lim ? compact.first : self end
17
28
  def return_first(&block)
18
29
  returned = nil
@@ -21,7 +32,7 @@ module Mobj
21
32
  end
22
33
  end
23
34
 
24
- class Moken
35
+ class Token
25
36
  def initialize(type, *args)
26
37
  @type, @path, @options = type.to_sym, nil, {}
27
38
  tokens = []
@@ -40,29 +51,33 @@ module Mobj
40
51
  def to_s() "#{@type.to_s.upcase}(#@path#{ " => #@options" unless @options.empty?})" end
41
52
 
42
53
  def extract(obj, path)
43
- if obj.is_a?(Array)
44
- if path == :*
45
- obj
46
- else
47
- obj.map { |o| extract(o, path)}
48
- end
54
+ obj.reparent
55
+ if path == :*
56
+ obj
57
+ elsif obj.is_a?(Array)
58
+ obj.map { |o| extract(o, path) }
59
+ elsif path.is_a?(Array)
60
+ path.map { |pth| obj[pth.sym] }
49
61
  else
50
- if path.is_a?(Array)
51
- path.map { |pth| obj[pth.sym] }
52
- else
53
- obj[path.sym]
54
- end
62
+ obj[path.sym]
55
63
  end
56
64
  end
57
65
 
58
66
  def walk(obj, root = obj)
67
+ obj, root = Circle.wrap(obj), Circle.wrap(root)
59
68
  val = case @type
60
69
  when :literal
61
70
  @path.to_s
62
71
  when :path
63
72
  extract(obj, @path)
64
73
  when :regex
65
- obj.keys.map { |key| key if key.match(@path) }.compact.map{|key| obj[key]}
74
+ obj.keys.map { |key| key if key.match(@path) }.compact.map{|key| obj[key] }
75
+ when :up
76
+ if obj.respond_to? :parent
77
+ obj.mparent || obj.parent
78
+ else
79
+ obj.mparent
80
+ end
66
81
  when :any
67
82
  @path.return_first { |token| token.walk(obj, root) }
68
83
  when :all
@@ -78,7 +93,7 @@ module Mobj
78
93
  lookup.tokenize.walk(root)
79
94
  end
80
95
  when :inverse
81
- raise "not implemented yet. not sure how to implement yet, actually. please continue to hold. your call is important to us."
96
+ raise "not implemented yet. not sure how to implement yet, actually. please continue to hold. your call is important to us."
82
97
  when :root
83
98
  tree = [@path].flatten
84
99
  while (path = tree.shift)
@@ -87,7 +102,8 @@ module Mobj
87
102
  obj.is_a?(Array) ? obj.flatten : obj
88
103
  end
89
104
 
90
- @options[:indexes] ? val.values_at(*@options[:indexes]) : val
105
+ val = @options[:indexes] ? val.values_at(*@options[:indexes]) : val
106
+ val
91
107
  end
92
108
  end
93
109
 
@@ -96,23 +112,25 @@ module Mobj
96
112
 
97
113
  def tokenize
98
114
  tokens = []
99
- scan(/\~([^\.]+)|\/(.*?)\/|\{\{(.*?)\}\}|([^\.\[]+)(?:\[([\d\+\.,-]+)\])?/).each do |literal, regex, lookup, path, indexes|
115
+ scan(/\~([^\.]+)|\/(.*?)\/|\{\{(.*?)\}\}|(\^)|([^\.\[]+)(?:\[([\d\+\.,-]+)\])?/).each do |literal, regex, lookup, up, path, indexes|
100
116
  if literal
101
- tokens << Moken.new(:literal, literal)
117
+ tokens << Token.new(:literal, literal)
102
118
  elsif lookup
103
- tokens << Moken.new(:lookup, lookup.tokenize)
119
+ tokens << Token.new(:lookup, lookup.tokenize)
104
120
  elsif regex
105
- tokens << Moken.new(:regex, Regexp.new(regex))
121
+ tokens << Token.new(:regex, Regexp.new(regex))
122
+ elsif up
123
+ tokens << Token.new(:up)
106
124
  elsif path
107
125
  eachs = path.split(",")
108
126
  ors = path.split("|")
109
127
  ands = path.split("&")
110
128
  if eachs.size > 1
111
- tokens << Moken.new(:each, eachs.map { |token| token.tokenize() })
129
+ tokens << Token.new(:each, eachs.map { |token| token.tokenize() })
112
130
  elsif ands.size > 1
113
- tokens << Moken.new(:all, ands.map { |token| token.tokenize() })
131
+ tokens << Token.new(:all, ands.map { |token| token.tokenize() })
114
132
  elsif ors.size > 1
115
- tokens << Moken.new(:any, ors.map { |token| token.tokenize() })
133
+ tokens << Token.new(:any, ors.map { |token| token.tokenize() })
116
134
  end
117
135
 
118
136
  unless ands.size + ors.size + eachs.size > 3
@@ -122,59 +140,82 @@ module Mobj
122
140
  end if indexes
123
141
 
124
142
  if path[0] == '!'
125
- tokens << Moken.new(:inverse, Moken.new(:path, path[1..-1].sym, options))
143
+ tokens << Token.new(:inverse, Token.new(:path, path[1..-1].sym, options))
126
144
  else
127
- tokens << Moken.new(:path, path.sym, options)
145
+ tokens << Token.new(:path, path.sym, options)
128
146
  end
129
147
  end
130
148
  end
131
149
  end
132
- tokens.size == 1 ? tokens.first : Moken.new(:root, tokens)
150
+ tokens.size == 1 ? tokens.first : Token.new(:root, tokens)
133
151
  end
134
152
  end
135
153
 
136
- class Circle < Hash
154
+ class Circle
155
+ def self.wrap(wrapped)
156
+ return wrapped if wrapped.is_a?(CircleHash) || wrapped.is_a?(CircleRay)
137
157
 
138
- def initialize
139
- super
140
- @index = 0
158
+ if wrapped.is_a?(Array)
159
+ circle = CircleRay.new
160
+ wrapped.each_with_index { |item, i| circle[i] = wrap(item) }
161
+ circle
162
+ elsif wrapped.is_a?(Hash)
163
+ circle = CircleHash.new
164
+ wrapped.each_pair { |key, val| circle[key] = wrap(val) }
165
+ circle
166
+ else
167
+ wrapped
168
+ end
141
169
  end
170
+ end
142
171
 
143
- def <<(val)
144
- self[@index] = val
145
- @index += 1
172
+ class CircleHash < Hash
173
+ def *(&block)
174
+ if block.nil?
175
+ self
176
+ else
177
+ map = CircleHash.new
178
+ self.each_pair do |key, val|
179
+ map.merge!(block.call(key, val))
180
+ end
181
+ map
182
+ end
146
183
  end
147
184
 
148
185
  def []=(*keys, val)
149
186
  val.mparent(self)
150
- keys.each do |key|
151
- if key.is_a?(Range)
152
- key.to_a.each{ |k| self[k]= val }
153
- else
154
- @index = key + 1 if key.is_a?(Fixnum) && key >= @index
155
- store(key.sym, val)
156
- end
157
- end
187
+ keys.each { |key| store(key.sym, val) }
158
188
  end
159
189
 
160
190
  alias_method :lookup, :[]
161
- def [](*keys) keys.map { |key| self.lookup(key.sym) }.sequester
162
- end
191
+ def [](*keys) keys.map { |key| self.lookup(key.sym) }.sequester end
163
192
 
164
- def method_missing(name, *args, &block)
165
- self.has_key?(name) ? self[name] : super(name, *args, &block)
193
+ def method_missing(name, *args, &block) self.has_key?(name) ? self[name] : super(name, *args, &block) end
194
+ end
195
+
196
+ class CircleRay < Array
197
+ alias_method :*, :map
198
+
199
+ alias_method :set, :[]=
200
+ def []=(*keys, val)
201
+ val.mparent(self)
202
+ set(*keys, val)
166
203
  end
167
204
 
168
- def self.wrap(wrapped)
169
- circle = self.new
170
- if wrapped.is_a?(Array)
171
- wrapped.each_with_index { |item, i| circle[i] = wrap(item) }
172
- elsif wrapped.is_a?(Hash)
173
- wrapped.each_pair { |key, val| circle[key] = wrap(val) }
174
- else
175
- return wrapped
205
+ alias_method :append, :<<
206
+ def <<(*vals)
207
+ vals.each do |val|
208
+ val.mparent(self)
209
+ self.append(val)
176
210
  end
177
- circle
211
+ self
212
+ end
213
+
214
+ alias_method :lookup, :[]
215
+ def [](*keys)
216
+ keys.map do |key|
217
+ self.lookup(key)
218
+ end.sequester
178
219
  end
179
220
  end
180
221
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mobj
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.5.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-10 00:00:00.000000000 Z
12
+ date: 2012-11-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec