mobj 2.2.1 → 2.4.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 +1 -1
- data/lib/ext/array.rb +40 -0
- data/lib/ext/basic_object.rb +32 -0
- data/lib/ext/class.rb +17 -0
- data/lib/ext/fixnum.rb +9 -0
- data/lib/ext/float.rb +9 -0
- data/lib/ext/hash.rb +74 -0
- data/lib/ext/match_data.rb +22 -0
- data/lib/ext/nil.rb +56 -0
- data/lib/ext/object.rb +88 -0
- data/lib/ext/string.rb +80 -0
- data/lib/ext/symbol.rb +9 -0
- data/lib/mobj.rb +7 -345
- metadata +13 -2
data/README.md
CHANGED
data/lib/ext/array.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Mobj
|
2
|
+
|
3
|
+
class ::Array
|
4
|
+
alias includes? include?
|
5
|
+
alias contains? include?
|
6
|
+
|
7
|
+
def unempty?()
|
8
|
+
!empty?
|
9
|
+
end
|
10
|
+
|
11
|
+
alias_method :notempty?, :unempty?
|
12
|
+
|
13
|
+
def msum(initial = 0.0, op = :+, &block)
|
14
|
+
map(&:to_f).inject(initial, block ? block : op)
|
15
|
+
end
|
16
|
+
|
17
|
+
def mavg(&block)
|
18
|
+
msum(&block) / size
|
19
|
+
end
|
20
|
+
|
21
|
+
def values()
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def sequester(crush = true)
|
26
|
+
if crush
|
27
|
+
compact.size <= 1 ? compact.first : self
|
28
|
+
else
|
29
|
+
size <= 1 ? first : self
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def return_first(&block)
|
34
|
+
returned = nil
|
35
|
+
each { |item| break if (returned = block.call(item)) }
|
36
|
+
returned
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Mobj
|
2
|
+
|
3
|
+
class ::BasicObject
|
4
|
+
def class
|
5
|
+
klass = class << self;
|
6
|
+
self
|
7
|
+
end
|
8
|
+
klass.superclass
|
9
|
+
end
|
10
|
+
|
11
|
+
def null!(*)
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def nil!(*)
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def itself()
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def wrap(*args, &block)
|
24
|
+
instance_exec(*args, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
alias_method :alter, :wrap
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
end
|
data/lib/ext/class.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Mobj
|
2
|
+
|
3
|
+
class ::Class
|
4
|
+
def object_methods()
|
5
|
+
(self.instance_methods(true) - Object.instance_methods(true)).sort
|
6
|
+
end
|
7
|
+
|
8
|
+
def class_methods()
|
9
|
+
(self.singleton_methods(true) - Object.singleton_methods(true)).sort
|
10
|
+
end
|
11
|
+
|
12
|
+
def defined_methods()
|
13
|
+
(class_methods | object_methods).sort
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/lib/ext/fixnum.rb
ADDED
data/lib/ext/float.rb
ADDED
data/lib/ext/hash.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
module Mobj
|
2
|
+
|
3
|
+
module HashEx
|
4
|
+
|
5
|
+
def ki(name)
|
6
|
+
name.to_s[/(.*?)[?!=]?$/, 1]
|
7
|
+
end
|
8
|
+
|
9
|
+
def ki?(name)
|
10
|
+
[name.sym, name.to_s, ki(name).sym, ki(name).to_s].any? { |k| key?(k) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def symvert(key_converter = :itself, value_converter = key_converter)
|
14
|
+
each.with_object({}) do |(k, v), o|
|
15
|
+
key = if key_converter.is_a?(Proc)
|
16
|
+
key_converter.call(k, v)
|
17
|
+
elsif k.respond_to?(key_converter.sym)
|
18
|
+
k.__send__(key_converter.sym)
|
19
|
+
else
|
20
|
+
k
|
21
|
+
end
|
22
|
+
|
23
|
+
value = if value_converter.is_a?(Proc)
|
24
|
+
value_converter.arity == 1 ? value_converter.call(v) : value_converter.call(k, v)
|
25
|
+
elsif v.respond_to?(value_converter.sym)
|
26
|
+
v.__send__(value_converter.sym)
|
27
|
+
else
|
28
|
+
v
|
29
|
+
end
|
30
|
+
|
31
|
+
o[key] = value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def symvert!(key_converter = :itself, value_converter = key_converter)
|
36
|
+
replace(symvert(key_converter, value_converter))
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(name, *args, &block)
|
40
|
+
value = if name[-1] == '=' && args.size == 1
|
41
|
+
key = name[0...-1].sym
|
42
|
+
key = key.to_s if key?(key.to_s)
|
43
|
+
self[key] = args.sequester
|
44
|
+
elsif name[-1] == '?'
|
45
|
+
key = name[0...-1].sym
|
46
|
+
!!self[key, key.to_s]
|
47
|
+
elsif name[-1] == '!'
|
48
|
+
key = name[0...-1].sym
|
49
|
+
val = self[key.sym] || self[key.to_s]
|
50
|
+
if !val && (block || args.unempty?)
|
51
|
+
self[key] = val = (block ? block.call(*args) : args.sequester)
|
52
|
+
end
|
53
|
+
super unless val
|
54
|
+
else
|
55
|
+
self[name.sym] || self[name.to_s]
|
56
|
+
end
|
57
|
+
value ||= args.sequester unless args.empty?
|
58
|
+
|
59
|
+
return block ? block[value] : value
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class ::Hash
|
64
|
+
include HashEx
|
65
|
+
|
66
|
+
alias :mlookup :[]
|
67
|
+
alias :mdef :default
|
68
|
+
|
69
|
+
def [](*fkeys)
|
70
|
+
fkeys.map { |key| mlookup(key) || fetch(key.sym) { fetch(key.to_s) { fetch(ki(key).sym) { fetch(ki(key).to_s) { mdef(key) } } } } }.sequester
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Mobj
|
2
|
+
|
3
|
+
module MatchEx
|
4
|
+
def to_h
|
5
|
+
Hash[names.map(&:sym).zip(captures)]
|
6
|
+
end
|
7
|
+
|
8
|
+
def method_missing(name, *args, &block)
|
9
|
+
if name[-1] == '?' && names.includes?(name[0...-1])
|
10
|
+
return to_h[name[0...-1].sym]
|
11
|
+
elsif names.includes?(name.to_s)
|
12
|
+
return to_h[name.sym]
|
13
|
+
end
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class ::MatchData
|
19
|
+
include MatchEx
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/lib/ext/nil.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Mobj
|
2
|
+
|
3
|
+
class ::NilClass
|
4
|
+
MOBJ_NULL_REGION_BEGIN = __LINE__
|
5
|
+
|
6
|
+
def __mobj__caller()
|
7
|
+
caller.find do |frame|
|
8
|
+
(file, line) = frame.split(":")
|
9
|
+
file != __FILE__ || !(MOBJ_NULL_REGION_BEGIN..MOBJ_NULL_REGION_END).cover?(line.to_i)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def null?(*)
|
14
|
+
@@null ||= nil
|
15
|
+
@@null && @@null == __mobj__caller
|
16
|
+
end
|
17
|
+
|
18
|
+
def null!(*)
|
19
|
+
@@null = __mobj__caller
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def nil!(*)
|
24
|
+
@@null = nil
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def method_missing(name, *args, &block)
|
29
|
+
if null?
|
30
|
+
self
|
31
|
+
else
|
32
|
+
nil!
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
alias_method :try?, :null!
|
38
|
+
|
39
|
+
MOBJ_NULL_REGION_END = __LINE__
|
40
|
+
|
41
|
+
def attempt(value=true)
|
42
|
+
Forwarder.new do |name, *args, &block|
|
43
|
+
if self.methods(true).include? name
|
44
|
+
self.__send__(name, *args, &block)
|
45
|
+
elsif value.is_a?(Proc)
|
46
|
+
value.call([name] + args, &block)
|
47
|
+
elsif value.is_a?(Hash) && value.ki?(name)
|
48
|
+
value[name].when.is_a?(Proc).call(*args, &block)
|
49
|
+
else
|
50
|
+
value
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
data/lib/ext/object.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
module Mobj
|
2
|
+
|
3
|
+
class ::Object
|
4
|
+
alias responds_to? respond_to?
|
5
|
+
|
6
|
+
def sym()
|
7
|
+
respond_to?(:to_sym) ? to_sym : to_s.to_sym
|
8
|
+
end
|
9
|
+
|
10
|
+
def __mobj__root()
|
11
|
+
__mobj__parent.nil? || __mobj__parent == self ? self : __mobj__parent.__mobj__root
|
12
|
+
end
|
13
|
+
|
14
|
+
def __mobj__reparent()
|
15
|
+
values.each { |v| v.__mobj__parent(self); v.__mobj__reparent } if respond_to? :values
|
16
|
+
end
|
17
|
+
|
18
|
+
def __mobj__parent?()
|
19
|
+
!@__mobj__parent.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
def __mobj__parent(rent = :"__mobj__parent")
|
23
|
+
unless rent == :"__mobj__parent"
|
24
|
+
@__mobj__parent = rent == self ? nil : rent
|
25
|
+
end
|
26
|
+
@__mobj__parent
|
27
|
+
end
|
28
|
+
|
29
|
+
def attempt(value=:root)
|
30
|
+
Forwarder.new do |name, *args, &block|
|
31
|
+
if self.methods(true).include? name ##//use respond to?
|
32
|
+
self.__send__(name, *args, &block)
|
33
|
+
elsif value.is_a?(Proc)
|
34
|
+
value.call([name] + args, &block)
|
35
|
+
elsif value.is_a?(Hash) && value.ki?(name)
|
36
|
+
value[name].when.is_a?(Proc).call(*args, &block)
|
37
|
+
else
|
38
|
+
value == :root ? self : value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def try?(default=nil, &block)
|
44
|
+
Forwarder.new do |name, *args, &fblock|
|
45
|
+
if methods(true).include?(name)
|
46
|
+
__send__(name, *args, &fblock)
|
47
|
+
elsif is_a?(Hash) && ki?(name)
|
48
|
+
self[name]
|
49
|
+
end || (block ? instance_exec(*[*default], &block) : default) || nil.null!
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
alias_method :ifnil, :try?
|
54
|
+
|
55
|
+
def when
|
56
|
+
Forwarder.new do |name, *args, &block|
|
57
|
+
if methods.include?(name) && __send__(name, *args, &block)
|
58
|
+
thn = Forwarder.new do |name, *args, &block|
|
59
|
+
if name.sym == :then
|
60
|
+
thn
|
61
|
+
else
|
62
|
+
ret = __send__(name, *args, &block)
|
63
|
+
ret.define_singleton_method(:else) { Forwarder.new { ret } }
|
64
|
+
ret
|
65
|
+
end
|
66
|
+
end
|
67
|
+
else
|
68
|
+
Forwarder.new do |name|
|
69
|
+
if name.sym == :then
|
70
|
+
els = Forwarder.new do |name|
|
71
|
+
if name.sym == :else
|
72
|
+
Forwarder.new { |name, *args, &block| __send__(name, *args, &block) }
|
73
|
+
else
|
74
|
+
els
|
75
|
+
end
|
76
|
+
end
|
77
|
+
else
|
78
|
+
self
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
alias_method :if?, :when
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
data/lib/ext/string.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'mobj'
|
2
|
+
|
3
|
+
module Mobj
|
4
|
+
|
5
|
+
class ::String
|
6
|
+
|
7
|
+
def matches(regexp)
|
8
|
+
start = 0
|
9
|
+
matches = []
|
10
|
+
while (match = match(regexp, start))
|
11
|
+
start = match.end(0)
|
12
|
+
matches << match
|
13
|
+
yield match if block_given?
|
14
|
+
end
|
15
|
+
matches
|
16
|
+
end
|
17
|
+
|
18
|
+
def walk(obj)
|
19
|
+
tokenize.walk(obj)
|
20
|
+
end
|
21
|
+
|
22
|
+
def tokenize
|
23
|
+
tokens = []
|
24
|
+
|
25
|
+
lit = /\~(?<literal>[^\.]+)/
|
26
|
+
regex = /\/(?<regex>.*?(?<!\\))\//
|
27
|
+
lookup = /\{\{(?<lookup>.*?)\}\}/
|
28
|
+
up = /(?<up>\^)/
|
29
|
+
path = /(?<path>[^\.\[]+)/
|
30
|
+
indexes = /(?<indexes>[\d\+\.,\s-]+)/
|
31
|
+
|
32
|
+
matcher = /#{lit}|#{regex}|#{lookup}|#{up}|#{path}(?:\[#{indexes}\])?/
|
33
|
+
|
34
|
+
matches(matcher) do |match|
|
35
|
+
if match.literal?
|
36
|
+
tokens << Mobj::Token.new(:literal, match.literal)
|
37
|
+
elsif match.lookup?
|
38
|
+
tokens << Mobj::Token.new(:lookup, match.lookup.tokenize)
|
39
|
+
elsif match.regex?
|
40
|
+
tokens << Mobj::Token.new(:regex, Regexp.new(match.regex))
|
41
|
+
elsif match.up?
|
42
|
+
tokens << Mobj::Token.new(:up)
|
43
|
+
elsif match.path?
|
44
|
+
eachs = match.path.split(/\s*,\s*/)
|
45
|
+
ors = match.path.split(/\s*\|\s*/)
|
46
|
+
ands = match.path.split(/\s*\&\s*/)
|
47
|
+
if eachs.size > 1
|
48
|
+
tokens << Mobj::Token.new(:each, eachs.map { |token| token.tokenize() })
|
49
|
+
elsif ands.size > 1
|
50
|
+
tokens << Mobj::Token.new(:all, ands.map { |token| token.tokenize() })
|
51
|
+
elsif ors.size > 1
|
52
|
+
tokens << Mobj::Token.new(:any, ors.map { |token| token.tokenize() })
|
53
|
+
end
|
54
|
+
|
55
|
+
unless ands.size + ors.size + eachs.size > 3
|
56
|
+
options = {}
|
57
|
+
index_matcher = /\s*(?<low>\d+)\s*(?:(?:\.\s*\.\s*(?<ex>\.)?\s*|-?)\s*(?<high>-?\d+|\+))?\s*/
|
58
|
+
|
59
|
+
options[:indexes] = match.indexes.matches(index_matcher).map do |index|
|
60
|
+
if index.high?
|
61
|
+
Range.new(index.low.to_i, (index.high == "+" ? -1 : index.high.to_i), index.ex?)
|
62
|
+
else
|
63
|
+
index.low.to_i
|
64
|
+
end
|
65
|
+
end if match.indexes?
|
66
|
+
|
67
|
+
if match.path[0] == '!'
|
68
|
+
tokens << Mobj::Token.new(:inverse, Token.new(:path, match.path[1..-1].sym, options))
|
69
|
+
else
|
70
|
+
tokens << Mobj::Token.new(:path, match.path.sym, options)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
tokens.size == 1 ? tokens.first : Mobj::Token.new(:root, tokens)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
data/lib/ext/symbol.rb
ADDED
data/lib/mobj.rb
CHANGED
@@ -1,29 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
klass = class << self; self end
|
6
|
-
klass.superclass
|
7
|
-
end
|
8
|
-
def null!(*) self end
|
9
|
-
def nil!(*) self end
|
10
|
-
def itself() self end
|
11
|
-
def alter(*args, &block) instance_exec(*args, &block) end
|
12
|
-
alias_method :o!, :alter
|
13
|
-
|
14
|
-
end
|
15
|
-
|
16
|
-
class ::Fixnum
|
17
|
-
def delimit(delim = ',')
|
18
|
-
to_s.split('').reverse.each_slice(3).to_a.map(&:join).join(delim).reverse
|
19
|
-
end
|
20
|
-
end
|
1
|
+
Dir["#{File.dirname(__FILE__)}/ext/*.rb"].each do |f|
|
2
|
+
exclude = ENV['MOBJ_EXCLUDE']
|
3
|
+
require f unless (exclude && f.match(exclude))
|
4
|
+
end
|
21
5
|
|
22
|
-
|
23
|
-
def delimit(delim = ',')
|
24
|
-
"#{to_i.delimit(delim)}.#{to_s.to_s[/\.(\d+)$/, 1]}"
|
25
|
-
end
|
26
|
-
end
|
6
|
+
module Mobj
|
27
7
|
|
28
8
|
class Forwarder < ::BasicObject
|
29
9
|
attr_accessor :root, :handler
|
@@ -31,248 +11,6 @@ module Mobj
|
|
31
11
|
def method_missing(name, *args, &block) handler.call(name, *args, &block) end
|
32
12
|
end
|
33
13
|
|
34
|
-
class ::Object
|
35
|
-
alias responds_to? respond_to?
|
36
|
-
def sym() respond_to?(:to_sym) ? to_sym : to_s.to_sym end
|
37
|
-
def __mobj__root() __mobj__parent.nil? || __mobj__parent == self ? self : __mobj__parent.__mobj__root end
|
38
|
-
def __mobj__reparent() values.each { |v| v.__mobj__parent(self); v.__mobj__reparent } if respond_to? :values end
|
39
|
-
def __mobj__parent?() !@__mobj__parent.nil? end
|
40
|
-
def __mobj__parent(rent = :"__mobj__parent")
|
41
|
-
unless rent == :"__mobj__parent"
|
42
|
-
@__mobj__parent = rent == self ? nil : rent
|
43
|
-
end
|
44
|
-
@__mobj__parent
|
45
|
-
end
|
46
|
-
def attempt(value=:root)
|
47
|
-
Forwarder.new do |name, *args, &block|
|
48
|
-
if self.methods(true).include? name ##//use respond to?
|
49
|
-
self.__send__(name, *args, &block)
|
50
|
-
elsif value.is_a?(Proc)
|
51
|
-
value.call([name] + args, &block)
|
52
|
-
elsif value.is_a?(Hash) && value.ki?(name)
|
53
|
-
value[name].when.is_a?(Proc).call(*args, &block)
|
54
|
-
else
|
55
|
-
value == :root ? self : value
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def try?(default=nil, &block)
|
61
|
-
Forwarder.new do |name, *args, &fblock|
|
62
|
-
if methods(true).include?(name)
|
63
|
-
__send__(name, *args, &fblock)
|
64
|
-
elsif is_a?(Hash) && ki?(name)
|
65
|
-
self[name]
|
66
|
-
end || (block ? instance_exec(*[*default], &block) : default) || nil.null!
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
alias_method :ifnil, :try?
|
71
|
-
|
72
|
-
def when
|
73
|
-
Forwarder.new do |name, *args, &block|
|
74
|
-
if methods.include?(name) && __send__(name, *args, &block)
|
75
|
-
thn = Forwarder.new do |name, *args, &block|
|
76
|
-
if name.sym == :then
|
77
|
-
thn
|
78
|
-
else
|
79
|
-
ret = __send__(name, *args, &block)
|
80
|
-
ret.define_singleton_method(:else) { Forwarder.new { ret } }
|
81
|
-
ret
|
82
|
-
end
|
83
|
-
end
|
84
|
-
else
|
85
|
-
Forwarder.new do |name|
|
86
|
-
if name.sym == :then
|
87
|
-
els = Forwarder.new do |name|
|
88
|
-
if name.sym == :else
|
89
|
-
Forwarder.new { |name, *args, &block| __send__(name, *args, &block) }
|
90
|
-
else
|
91
|
-
els
|
92
|
-
end
|
93
|
-
end
|
94
|
-
else
|
95
|
-
self
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
alias_method :if?, :when
|
102
|
-
end
|
103
|
-
|
104
|
-
class ::NilClass
|
105
|
-
MOBJ_NULL_REGION_BEGIN = __LINE__
|
106
|
-
def __mobj__caller()
|
107
|
-
caller.find do |frame|
|
108
|
-
(file, line) = frame.split(":")
|
109
|
-
file != __FILE__ || !(MOBJ_NULL_REGION_BEGIN..MOBJ_NULL_REGION_END).cover?(line.to_i)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
def null?(*)
|
113
|
-
@@null ||= nil
|
114
|
-
@@null && @@null == __mobj__caller
|
115
|
-
end
|
116
|
-
def null!(*)
|
117
|
-
@@null = __mobj__caller
|
118
|
-
self
|
119
|
-
end
|
120
|
-
def nil!(*)
|
121
|
-
@@null = nil
|
122
|
-
self
|
123
|
-
end
|
124
|
-
def method_missing(name, *args, &block)
|
125
|
-
if null?
|
126
|
-
self
|
127
|
-
else
|
128
|
-
nil!
|
129
|
-
super
|
130
|
-
end
|
131
|
-
end
|
132
|
-
alias_method :try?, :null!
|
133
|
-
|
134
|
-
MOBJ_NULL_REGION_END = __LINE__
|
135
|
-
|
136
|
-
def attempt(value=true)
|
137
|
-
Forwarder.new do |name, *args, &block|
|
138
|
-
if self.methods(true).include? name
|
139
|
-
self.__send__(name, *args, &block)
|
140
|
-
elsif value.is_a?(Proc)
|
141
|
-
value.call([name] + args, &block)
|
142
|
-
elsif value.is_a?(Hash) && value.ki?(name)
|
143
|
-
value[name].when.is_a?(Proc).call(*args, &block)
|
144
|
-
else
|
145
|
-
value
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
class ::Class
|
152
|
-
def object_methods() (self.instance_methods(true) - Object.instance_methods(true)).sort end
|
153
|
-
def class_methods() (self.singleton_methods(true) - Object.singleton_methods(true)).sort end
|
154
|
-
def defined_methods() (class_methods | object_methods).sort end
|
155
|
-
end
|
156
|
-
|
157
|
-
class ::Array
|
158
|
-
alias includes? include?
|
159
|
-
alias contains? include?
|
160
|
-
|
161
|
-
def unempty?() !empty? end
|
162
|
-
alias_method :notempty?, :unempty?
|
163
|
-
|
164
|
-
def msum(initial = 0.0, op = :+, &block)
|
165
|
-
map(&:to_f).inject(initial, block ? block : op)
|
166
|
-
end
|
167
|
-
|
168
|
-
def mavg(&block)
|
169
|
-
msum(&block) / size
|
170
|
-
end
|
171
|
-
|
172
|
-
def values() self end
|
173
|
-
def sequester(crush = true)
|
174
|
-
if crush
|
175
|
-
compact.size <= 1 ? compact.first : self
|
176
|
-
else
|
177
|
-
size <= 1 ? first : self
|
178
|
-
end
|
179
|
-
end
|
180
|
-
def return_first(&block)
|
181
|
-
returned = nil
|
182
|
-
each { |item| break if (returned = block.call(item)) }
|
183
|
-
returned
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
module HashEx
|
188
|
-
|
189
|
-
def ki(name)
|
190
|
-
name.to_s[/(.*?)[?!=]?$/, 1]
|
191
|
-
end
|
192
|
-
|
193
|
-
def ki?(name)
|
194
|
-
[name.sym, name.to_s, ki(name).sym, ki(name).to_s].any?{ |k| key?(k) }
|
195
|
-
end
|
196
|
-
|
197
|
-
def symvert(key_converter = :itself, value_converter = key_converter)
|
198
|
-
each.with_object({}) do |(k,v),o|
|
199
|
-
key = if key_converter.is_a?(Proc)
|
200
|
-
key_converter.call(k, v)
|
201
|
-
elsif k.respond_to?(key_converter.sym)
|
202
|
-
k.__send__(key_converter.sym)
|
203
|
-
else
|
204
|
-
k
|
205
|
-
end
|
206
|
-
|
207
|
-
value = if value_converter.is_a?(Proc)
|
208
|
-
value_converter.arity == 1 ? value_converter.call(v) : value_converter.call(k, v)
|
209
|
-
elsif v.respond_to?(value_converter.sym)
|
210
|
-
v.__send__(value_converter.sym)
|
211
|
-
else
|
212
|
-
v
|
213
|
-
end
|
214
|
-
|
215
|
-
o[key] = value
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
def symvert!(key_converter = :itself, value_converter = key_converter)
|
220
|
-
replace(symvert(key_converter, value_converter))
|
221
|
-
end
|
222
|
-
|
223
|
-
def method_missing(name, *args, &block)
|
224
|
-
value = if name[-1] == '=' && args.size == 1
|
225
|
-
key = name[0...-1].sym
|
226
|
-
key = key.to_s if key?(key.to_s)
|
227
|
-
self[key] = args.sequester
|
228
|
-
elsif name[-1] == '?'
|
229
|
-
key = name[0...-1].sym
|
230
|
-
!!self[key, key.to_s]
|
231
|
-
elsif name[-1] == '!'
|
232
|
-
key = name[0...-1].sym
|
233
|
-
val = self[key.sym] || self[key.to_s]
|
234
|
-
if !val && (block || args.unempty?)
|
235
|
-
self[key] = val = (block ? block.call(*args) : args.sequester)
|
236
|
-
end
|
237
|
-
super unless val
|
238
|
-
else
|
239
|
-
self[name.sym] || self[name.to_s]
|
240
|
-
end
|
241
|
-
value ||= args.sequester unless args.empty?
|
242
|
-
|
243
|
-
return block ? block[value] : value
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
class ::Hash
|
248
|
-
include HashEx
|
249
|
-
|
250
|
-
alias :mlookup :[]
|
251
|
-
alias :mdef :default
|
252
|
-
def [](*fkeys)
|
253
|
-
fkeys.map { |key| mlookup(key) || fetch(key.sym) { fetch(key.to_s) { fetch(ki(key).sym) { fetch(ki(key).to_s) { mdef(key) }}}}}.sequester
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
module MatchEx
|
258
|
-
def to_hash
|
259
|
-
Hash[ names.map(&:sym).zip( captures ) ]
|
260
|
-
end
|
261
|
-
|
262
|
-
def method_missing(name, *args, &block)
|
263
|
-
if name[-1] == '?' && names.includes?(name[0...-1])
|
264
|
-
return to_hash[name[0...-1].sym]
|
265
|
-
elsif names.includes?(name.to_s)
|
266
|
-
return to_hash[name.sym]
|
267
|
-
end
|
268
|
-
super
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
class ::MatchData
|
273
|
-
include MatchEx
|
274
|
-
end
|
275
|
-
|
276
14
|
class Token
|
277
15
|
def initialize(type, *args)
|
278
16
|
@type, @path, @options = type.to_sym, nil, {}
|
@@ -335,7 +73,7 @@ module Mobj
|
|
335
73
|
if map.is_a?(Array)
|
336
74
|
map << obj[key]
|
337
75
|
else
|
338
|
-
named = m.
|
76
|
+
named = m.to_h.invert
|
339
77
|
name = if named.empty?
|
340
78
|
m.captures.empty? ? key : m.captures.sequester
|
341
79
|
else
|
@@ -396,83 +134,6 @@ module Mobj
|
|
396
134
|
end
|
397
135
|
end
|
398
136
|
|
399
|
-
class ::Symbol
|
400
|
-
def walk(obj) to_s.walk(obj) end
|
401
|
-
end
|
402
|
-
|
403
|
-
class ::String
|
404
|
-
|
405
|
-
def matches(regexp)
|
406
|
-
start = 0
|
407
|
-
matches = []
|
408
|
-
while (match = match(regexp, start))
|
409
|
-
start = match.end(0)
|
410
|
-
matches << match
|
411
|
-
yield match if block_given?
|
412
|
-
end
|
413
|
-
matches
|
414
|
-
end
|
415
|
-
|
416
|
-
def walk(obj) tokenize.walk(obj) end
|
417
|
-
|
418
|
-
def tokenize
|
419
|
-
tokens = []
|
420
|
-
|
421
|
-
lit = /\~(?<literal>[^\.]+)/
|
422
|
-
regex = /\/(?<regex>.*?(?<!\\))\//
|
423
|
-
lookup = /\{\{(?<lookup>.*?)\}\}/
|
424
|
-
up = /(?<up>\^)/
|
425
|
-
path = /(?<path>[^\.\[]+)/
|
426
|
-
indexes = /(?<indexes>[\d\+\.,\s-]+)/
|
427
|
-
|
428
|
-
matcher = /#{lit}|#{regex}|#{lookup}|#{up}|#{path}(?:\[#{indexes}\])?/
|
429
|
-
|
430
|
-
matches(matcher) do |match|
|
431
|
-
if match.literal?
|
432
|
-
tokens << Token.new(:literal, match.literal)
|
433
|
-
elsif match.lookup?
|
434
|
-
tokens << Token.new(:lookup, match.lookup.tokenize)
|
435
|
-
elsif match.regex?
|
436
|
-
tokens << Token.new(:regex, Regexp.new(match.regex))
|
437
|
-
elsif match.up?
|
438
|
-
tokens << Token.new(:up)
|
439
|
-
elsif match.path?
|
440
|
-
eachs = match.path.split(/\s*,\s*/)
|
441
|
-
ors = match.path.split(/\s*\|\s*/)
|
442
|
-
ands = match.path.split(/\s*\&\s*/)
|
443
|
-
if eachs.size > 1
|
444
|
-
tokens << Token.new(:each, eachs.map { |token| token.tokenize() })
|
445
|
-
elsif ands.size > 1
|
446
|
-
tokens << Token.new(:all, ands.map { |token| token.tokenize() })
|
447
|
-
elsif ors.size > 1
|
448
|
-
tokens << Token.new(:any, ors.map { |token| token.tokenize() })
|
449
|
-
end
|
450
|
-
|
451
|
-
unless ands.size + ors.size + eachs.size > 3
|
452
|
-
options = {}
|
453
|
-
index_matcher = /\s*(?<low>\d+)\s*(?:(?:\.\s*\.\s*(?<ex>\.)?\s*|-?)\s*(?<high>-?\d+|\+))?\s*/
|
454
|
-
|
455
|
-
options[:indexes] = match.indexes.matches(index_matcher).map do |index|
|
456
|
-
if index.high?
|
457
|
-
Range.new(index.low.to_i, (index.high == "+" ? -1 : index.high.to_i), index.ex?)
|
458
|
-
else
|
459
|
-
index.low.to_i
|
460
|
-
end
|
461
|
-
end if match.indexes?
|
462
|
-
|
463
|
-
if match.path[0] == '!'
|
464
|
-
tokens << Token.new(:inverse, Token.new(:path, match.path[1..-1].sym, options))
|
465
|
-
else
|
466
|
-
tokens << Token.new(:path, match.path.sym, options)
|
467
|
-
end
|
468
|
-
end
|
469
|
-
end
|
470
|
-
end
|
471
|
-
|
472
|
-
tokens.size == 1 ? tokens.first : Token.new(:root, tokens)
|
473
|
-
end
|
474
|
-
end
|
475
|
-
|
476
137
|
class Circle
|
477
138
|
def self.wrap(wrapped)
|
478
139
|
return wrapped if wrapped.is_a?(CircleHash) || wrapped.is_a?(CircleRay)
|
@@ -531,5 +192,6 @@ module Mobj
|
|
531
192
|
alias_method :lookup, :[]
|
532
193
|
def [](*keys) keys.map { |key| self.lookup(key) }.sequester end
|
533
194
|
end
|
195
|
+
|
534
196
|
end
|
535
197
|
|
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: 2.
|
4
|
+
version: 2.4.0
|
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: 2013-03-
|
12
|
+
date: 2013-03-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -65,6 +65,17 @@ executables: []
|
|
65
65
|
extensions: []
|
66
66
|
extra_rdoc_files: []
|
67
67
|
files:
|
68
|
+
- lib/ext/array.rb
|
69
|
+
- lib/ext/basic_object.rb
|
70
|
+
- lib/ext/class.rb
|
71
|
+
- lib/ext/fixnum.rb
|
72
|
+
- lib/ext/float.rb
|
73
|
+
- lib/ext/hash.rb
|
74
|
+
- lib/ext/match_data.rb
|
75
|
+
- lib/ext/nil.rb
|
76
|
+
- lib/ext/object.rb
|
77
|
+
- lib/ext/string.rb
|
78
|
+
- lib/ext/symbol.rb
|
68
79
|
- lib/mobj.rb
|
69
80
|
- README.md
|
70
81
|
homepage: https://github.com/gnovos/mobj
|