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.
- data/README.md +71 -0
- data/lib/mobj.rb +181 -0
- 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: []
|