mobj 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []