mobj 1.0.0

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 +71 -0
  2. data/lib/mobj.rb +181 -0
  3. metadata +94 -0
data/README.md ADDED
@@ -0,0 +1,71 @@
1
+ ctx
2
+ ===
3
+
4
+ Simple utility to limit method redefinition within the bounds of arbitrary logical scopes
5
+
6
+ Example
7
+ ===
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.
64
+
65
+ ---
66
+
67
+ Caveats and such
68
+ ===
69
+
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
+
data/lib/mobj.rb ADDED
@@ -0,0 +1,181 @@
1
+ module Mobj
2
+
3
+ class ::BasicObject
4
+ 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
7
+ end
8
+
9
+ 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
12
+ def defined_methods() (class_methods | object_methods).sort end
13
+ end
14
+
15
+ class ::Array
16
+ def sequester(lim = 1) compact.size <= lim ? compact.first : self end
17
+ def return_first(&block)
18
+ returned = nil
19
+ each { |item| break if (returned = block.call(item)) }
20
+ returned
21
+ end
22
+ end
23
+
24
+ class Moken
25
+ def initialize(type, *args)
26
+ @type, @path, @options = type.to_sym, nil, {}
27
+ tokens = []
28
+ args.each do |arg|
29
+ if arg.is_a? Hash
30
+ @options.merge!(arg)
31
+ elsif arg.is_a? String
32
+ tokens << arg.sym
33
+ else
34
+ tokens << arg
35
+ end
36
+ end
37
+ @path = tokens.sequester
38
+ end
39
+
40
+ def to_s() "#{@type.to_s.upcase}(#@path#{ " => #@options" unless @options.empty?})" end
41
+
42
+ 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
49
+ else
50
+ if path.is_a?(Array)
51
+ path.map { |pth| obj[pth.sym] }
52
+ else
53
+ obj[path.sym]
54
+ end
55
+ end
56
+ end
57
+
58
+ def walk(obj, root = obj)
59
+ val = case @type
60
+ when :literal
61
+ @path.to_s
62
+ when :path
63
+ extract(obj, @path)
64
+ when :regex
65
+ obj.keys.map { |key| key if key.match(@path) }.compact.map{|key| obj[key]}
66
+ when :any
67
+ @path.return_first { |token| token.walk(obj, root) }
68
+ when :all
69
+ matches = @path.map { |token| token.walk(obj, root) }
70
+ matches.compact.size == @path.size ? matches : nil
71
+ when :each
72
+ @path.map { |token| token.walk(obj, root) }
73
+ when :lookup
74
+ lookup = @path.walk(obj)
75
+ if lookup.is_a?(Array)
76
+ lookup.flatten.map { |lu| lu.tokenize.walk(root) }.flatten(1)
77
+ else
78
+ lookup.tokenize.walk(root)
79
+ end
80
+ when :inverse
81
+ raise "not implemented yet. not sure how to implement yet, actually. please continue to hold. your call is important to us."
82
+ when :root
83
+ tree = [@path].flatten
84
+ while (path = tree.shift)
85
+ obj = path.walk(obj)
86
+ end
87
+ obj.is_a?(Array) ? obj.flatten : obj
88
+ end
89
+
90
+ @options[:indexes] ? val.values_at(*@options[:indexes]) : val
91
+ end
92
+ end
93
+
94
+ class ::String
95
+ def ~@() "~#{self}" end
96
+
97
+ def tokenize
98
+ tokens = []
99
+ scan(/\~([^\.]+)|\/(.*?)\/|\{\{(.*?)\}\}|([^\.\[]+)(?:\[([\d\+\.,-]+)\])?/).each do |literal, regex, lookup, path, indexes|
100
+ if literal
101
+ tokens << Moken.new(:literal, literal)
102
+ elsif lookup
103
+ tokens << Moken.new(:lookup, lookup.tokenize)
104
+ elsif regex
105
+ tokens << Moken.new(:regex, Regexp.new(regex))
106
+ elsif path
107
+ eachs = path.split(",")
108
+ ors = path.split("|")
109
+ ands = path.split("&")
110
+ if eachs.size > 1
111
+ tokens << Moken.new(:each, eachs.map { |token| token.tokenize() })
112
+ elsif ands.size > 1
113
+ tokens << Moken.new(:all, ands.map { |token| token.tokenize() })
114
+ elsif ors.size > 1
115
+ tokens << Moken.new(:any, ors.map { |token| token.tokenize() })
116
+ end
117
+
118
+ unless ands.size + ors.size + eachs.size > 3
119
+ options = {}
120
+ options[:indexes] = indexes.scan(/(\d+)(?:(?:\.\.(\.)?|-?)(-?\d+|\+))?/).map do |start, exc, len|
121
+ len.nil? ? start.to_i : (Range.new(start.to_i, (len == "+" ? -1 : len.to_i), !exc.nil?))
122
+ end if indexes
123
+
124
+ if path[0] == '!'
125
+ tokens << Moken.new(:inverse, Moken.new(:path, path[1..-1].sym, options))
126
+ else
127
+ tokens << Moken.new(:path, path.sym, options)
128
+ end
129
+ end
130
+ end
131
+ end
132
+ tokens.size == 1 ? tokens.first : Moken.new(:root, tokens)
133
+ end
134
+ end
135
+
136
+ class Circle < Hash
137
+
138
+ def initialize
139
+ super
140
+ @index = 0
141
+ end
142
+
143
+ def <<(val)
144
+ self[@index] = val
145
+ @index += 1
146
+ end
147
+
148
+ def []=(*keys, val)
149
+ 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
158
+ end
159
+
160
+ alias_method :lookup, :[]
161
+ def [](*keys) keys.map { |key| self.lookup(key.sym) }.sequester
162
+ end
163
+
164
+ def method_missing(name, *args, &block)
165
+ self.has_key?(name) ? self[name] : super(name, *args, &block)
166
+ end
167
+
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
176
+ end
177
+ circle
178
+ end
179
+ end
180
+
181
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mobj
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mason
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rr
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: awesome_print
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Utils and extentions for various ruby objects
63
+ email: mobj@chipped.net
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files: []
67
+ files:
68
+ - lib/mobj.rb
69
+ - README.md
70
+ homepage: https://github.com/gnovos/mobj
71
+ licenses: []
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 1.8.24
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: Helpful utils and extentions
94
+ test_files: []