flor 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +9 -0
  3. data/CREDITS.md +21 -0
  4. data/LICENSE.txt +4 -1
  5. data/Makefile +4 -0
  6. data/README.md +8 -0
  7. data/flor.gemspec +10 -10
  8. data/lib/flor.rb +2 -2
  9. data/lib/flor/changes.rb +3 -3
  10. data/lib/flor/colours.rb +14 -8
  11. data/lib/flor/conf.rb +63 -58
  12. data/lib/flor/core.rb +4 -4
  13. data/lib/flor/core/executor.rb +65 -29
  14. data/lib/flor/core/node.rb +37 -20
  15. data/lib/flor/core/procedure.rb +182 -40
  16. data/lib/flor/core/texecutor.rb +125 -52
  17. data/lib/flor/djan.rb +111 -82
  18. data/lib/flor/dollar.rb +31 -30
  19. data/lib/flor/flor.rb +314 -237
  20. data/lib/flor/id.rb +7 -2
  21. data/lib/flor/log.rb +250 -245
  22. data/lib/flor/parser.rb +72 -38
  23. data/lib/flor/pcore/_arr.rb +10 -10
  24. data/lib/flor/pcore/_att.rb +49 -14
  25. data/lib/flor/pcore/_coll.rb +18 -0
  26. data/lib/flor/pcore/_obj.rb +23 -7
  27. data/lib/flor/pcore/_pat_.rb +1 -1
  28. data/lib/flor/pcore/_pat_guard.rb +8 -0
  29. data/lib/flor/pcore/_pat_obj.rb +3 -3
  30. data/lib/flor/pcore/_pat_or.rb +4 -0
  31. data/lib/flor/pcore/_pat_regex.rb +24 -0
  32. data/lib/flor/pcore/_skip.rb +4 -0
  33. data/lib/flor/pcore/_val.rb +0 -1
  34. data/lib/flor/pcore/all.rb +111 -0
  35. data/lib/flor/pcore/any.rb +83 -0
  36. data/lib/flor/pcore/arith.rb +35 -6
  37. data/lib/flor/pcore/break.rb +39 -1
  38. data/lib/flor/pcore/case.rb +82 -4
  39. data/lib/flor/pcore/cmp.rb +7 -7
  40. data/lib/flor/pcore/collect.rb +50 -0
  41. data/lib/flor/pcore/cond.rb +17 -3
  42. data/lib/flor/pcore/cursor.rb +8 -2
  43. data/lib/flor/pcore/detect.rb +45 -0
  44. data/lib/flor/pcore/each.rb +52 -0
  45. data/lib/flor/pcore/empty.rb +60 -0
  46. data/lib/flor/pcore/filter.rb +94 -0
  47. data/lib/flor/pcore/find.rb +67 -0
  48. data/lib/flor/pcore/for_each.rb +65 -0
  49. data/lib/flor/pcore/includes.rb +32 -0
  50. data/lib/flor/pcore/inject.rb +55 -0
  51. data/lib/flor/pcore/iterator.rb +151 -0
  52. data/lib/flor/pcore/keys.rb +60 -0
  53. data/lib/flor/pcore/length.rb +34 -7
  54. data/lib/flor/pcore/logo.rb +18 -0
  55. data/lib/flor/pcore/loop.rb +4 -0
  56. data/lib/flor/pcore/map.rb +77 -46
  57. data/lib/flor/pcore/match.rb +8 -2
  58. data/lib/flor/pcore/matchr.rb +4 -5
  59. data/lib/flor/pcore/move.rb +3 -3
  60. data/lib/flor/pcore/noeval.rb +13 -0
  61. data/lib/flor/pcore/not.rb +16 -0
  62. data/lib/flor/pcore/on.rb +172 -0
  63. data/lib/flor/pcore/on_cancel.rb +54 -0
  64. data/lib/flor/pcore/on_error.rb +68 -0
  65. data/lib/flor/pcore/rand.rb +2 -2
  66. data/lib/flor/pcore/range.rb +2 -1
  67. data/lib/flor/pcore/reduce.rb +124 -0
  68. data/lib/flor/pcore/reverse.rb +46 -0
  69. data/lib/flor/pcore/select.rb +72 -0
  70. data/lib/flor/pcore/set.rb +8 -0
  71. data/lib/flor/pcore/stall.rb +10 -0
  72. data/lib/flor/pcore/to_array.rb +61 -0
  73. data/lib/flor/pcore/until.rb +34 -0
  74. data/lib/flor/punit/cancel.rb +30 -5
  75. data/lib/flor/punit/ccollect.rb +11 -0
  76. data/lib/flor/punit/cmap.rb +10 -5
  77. data/lib/flor/punit/concurrence.rb +42 -51
  78. data/lib/flor/punit/cron.rb +33 -0
  79. data/lib/flor/punit/do_trap.rb +42 -0
  80. data/lib/flor/punit/every.rb +48 -13
  81. data/lib/flor/punit/graft.rb +3 -3
  82. data/lib/flor/punit/on_timeout.rb +38 -0
  83. data/lib/flor/punit/schedule.rb +69 -6
  84. data/lib/flor/punit/signal.rb +54 -0
  85. data/lib/flor/punit/sleep.rb +1 -1
  86. data/lib/flor/punit/task.rb +4 -1
  87. data/lib/flor/punit/trap.rb +188 -13
  88. data/lib/flor/tools/shell.rb +408 -62
  89. data/lib/flor/tools/shell_out.rb +31 -0
  90. data/lib/flor/unit.rb +1 -1
  91. data/lib/flor/unit/caller.rb +177 -0
  92. data/lib/flor/unit/executor.rb +1 -0
  93. data/lib/flor/unit/ganger.rb +15 -21
  94. data/lib/flor/unit/hook.rb +1 -1
  95. data/lib/flor/unit/hooker.rb +22 -10
  96. data/lib/flor/unit/loader.rb +22 -22
  97. data/lib/flor/unit/logger.rb +63 -36
  98. data/lib/flor/unit/models.rb +6 -1
  99. data/lib/flor/unit/models/execution.rb +12 -1
  100. data/lib/flor/unit/models/message.rb +7 -0
  101. data/lib/flor/unit/models/trap.rb +31 -17
  102. data/lib/flor/unit/scheduler.rb +18 -10
  103. data/lib/flor/unit/storage.rb +83 -23
  104. data/lib/flor/unit/waiter.rb +1 -2
  105. metadata +96 -52
  106. data/lib/flor/deep.rb +0 -144
  107. data/lib/flor/punit/on.rb +0 -57
  108. data/lib/flor/unit/runner.rb +0 -84
  109. data/match.md +0 -22
@@ -85,8 +85,8 @@ module Flor
85
85
  def stringify(v)
86
86
 
87
87
  case v
88
- when Array, Hash then JSON.dump(v)
89
- else v.to_s
88
+ when Array, Hash then JSON.dump(v)
89
+ else v.to_s
90
90
  end
91
91
  end
92
92
 
@@ -118,21 +118,21 @@ module Flor
118
118
  l = s.length
119
119
 
120
120
  case cmp
121
- when '>' then l > len
122
- when '>=' then l >= len
123
- when '<' then l < len
124
- when '<=' then l <= len
125
- when '=', '==' then l == len
126
- when '!=', '<>' then l != len
127
- else false
121
+ when '>' then l > len
122
+ when '>=' then l >= len
123
+ when '<' then l < len
124
+ when '<=' then l <= len
125
+ when '=', '==' then l == len
126
+ when '!=', '<>' then l != len
127
+ else false
128
128
  end
129
129
  end
130
130
 
131
131
  def to_json(o)
132
132
 
133
133
  case o
134
- when Array, Hash then JSON.dump(o)
135
- else JSON.dump([ o ])[1..-2]
134
+ when Array, Hash then JSON.dump(o)
135
+ else JSON.dump([ o ])[1..-2]
136
136
  end
137
137
  end
138
138
 
@@ -142,31 +142,32 @@ module Flor
142
142
 
143
143
  case fun
144
144
 
145
- when 'u' then o.to_s.upcase
146
- when 'd' then o.to_s.downcase
147
- when 'r' then o.reverse
148
- when 'c' then o.to_s.capitalize.gsub(/\s[a-z]/) { |c| c.upcase }
149
- when 'q' then quote(o, false)
150
- when 'Q' then quote(o, true)
145
+ when 'u' then o.to_s.upcase
146
+ when 'd' then o.to_s.downcase
147
+ when 'r' then o.reverse
148
+ when 'c' then o.to_s.capitalize.gsub(/\s[a-z]/) { |c| c.upcase }
149
+ when 'q' then quote(o, false)
150
+ when 'Q' then quote(o, true)
151
+ when 'l' then o.length.to_s
151
152
 
152
- when 'json' then to_json(o)
153
+ when 'json' then to_json(o)
153
154
 
154
- when /^j(.+)/
155
- o.respond_to?(:join) ? o.join($1) : o
155
+ when /^j(.+)/
156
+ o.respond_to?(:join) ? o.join($1) : o
156
157
 
157
- when /\Am\/(.+)\/\z/
158
- match($1, o.to_s)
159
- when /\As\/(.*[^\\]\/)(.+)\/([gix]*)\z/
160
- substitute($1.chop, $2, $3, o.to_s)
158
+ when /\Am\/(.+)\/\z/
159
+ match($1, o.to_s)
160
+ when /\As\/(.*[^\\]\/)(.+)\/([gix]*)\z/
161
+ substitute($1.chop, $2, $3, o.to_s)
161
162
 
162
- when /\A-?\d+\z/ then o.to_s[fun.to_i]
163
- when /\A(-?\d+), *(-?\d+)\z/ then o.to_s[$1.to_i, $2.to_i]
164
- when /\A(-?\d+)\.\.(-?\d+)\z/ then o.to_s[$1.to_i..$2.to_i]
163
+ when /\A-?\d+\z/ then o.to_s[fun.to_i]
164
+ when /\A(-?\d+), *(-?\d+)\z/ then o.to_s[$1.to_i, $2.to_i]
165
+ when /\A(-?\d+)\.\.(-?\d+)\z/ then o.to_s[$1.to_i..$2.to_i]
165
166
 
166
- when /\A\s*l\s*([><=!]=?|<>)\s*(\d+)\z/
167
- lfilter(o.to_s, $1, $2.to_i) ? o.to_s : nil
167
+ when /\A\s*l\s*([><=!]=?|<>)\s*(\d+)\z/
168
+ lfilter(o.to_s, $1, $2.to_i) ? o.to_s : nil
168
169
 
169
- else o
170
+ else o
170
171
  end
171
172
  end
172
173
 
@@ -1,180 +1,247 @@
1
1
 
2
2
  module Flor
3
3
 
4
- def self.to_a(o)
4
+ NAME_REX = '[a-zA-Z0-9_]+'
5
+ UNIT_NAME_REX = /\A#{NAME_REX}\z/
6
+ DOMAIN_NAME_REX = /\A#{NAME_REX}(\.#{NAME_REX})*\z/
7
+ FLOW_NAME_REX = /\A(#{NAME_REX}(?:\.#{NAME_REX})*)\.([a-zA-Z0-9_-]+)\z/
5
8
 
6
- o.nil? ? nil : Array(o)
7
- end
9
+ DOMAIN_UNIT_REX = /\A(#{NAME_REX}(?:\.#{NAME_REX})*)-(#{NAME_REX})[-\z]/
8
10
 
9
- #
10
- # misc
11
- #
12
- # miscellaneous functions
11
+ SPLAT_REGEX = /\A(.*)__(_|\d+)\z/.freeze
13
12
 
14
- def self.env_i(k)
13
+ POINTS = %w[
14
+ execute receive
15
+ return
16
+ entered left
17
+ task detask
18
+ schedule trigger
19
+ signal cancel
20
+ terminated failed ceased
21
+ idle
22
+ ]
15
23
 
16
- v = ENV[k]; (v && v.match(/\A\d+\z/)) ? v.to_i : nil
17
- end
24
+ class << self
18
25
 
19
- def self.dup(o)
26
+ def to_a(o)
20
27
 
21
- Marshal.load(Marshal.dump(o))
22
- end
28
+ o.nil? ? nil : Array(o)
29
+ end
23
30
 
24
- def self.dup_and_merge(h, hh)
31
+ #
32
+ # misc
33
+ #
34
+ # miscellaneous functions
25
35
 
26
- self.dup(h).merge(hh)
27
- end
28
- def self.dupm(h, hh); self.dup_and_merge(h, hh); end
36
+ def env_i(k)
29
37
 
30
- def self.deep_freeze(o)
38
+ v = ENV[k]; (v && v.match(/\A\d+\z/)) ? v.to_i : nil
39
+ end
31
40
 
32
- if o.is_a?(Array)
33
- o.each { |e| e.freeze }
34
- elsif o.is_a?(Hash)
35
- o.each { |k, v| k.freeze; v.freeze }
41
+ def dup(o)
42
+
43
+ Marshal.load(Marshal.dump(o))
36
44
  end
37
45
 
38
- o.freeze
39
- end
46
+ def dup_and_merge(h, hh)
40
47
 
41
- def self.false?(o)
48
+ self.dup(h).merge(hh)
49
+ end
50
+ def dupm(h, hh); self.dup_and_merge(h, hh); end
42
51
 
43
- o == nil || o == false
44
- end
52
+ def deep_freeze(o)
45
53
 
46
- def self.true?(o)
54
+ if o.is_a?(Array)
55
+ o.each { |e| e.freeze }
56
+ elsif o.is_a?(Hash)
57
+ o.each { |k, v| k.freeze; v.freeze }
58
+ end
47
59
 
48
- o != nil && o != false
49
- end
60
+ o.freeze
61
+ end
62
+
63
+ def false?(o)
64
+
65
+ o == nil || o == false
66
+ end
50
67
 
51
- def self.to_error(o)
68
+ def true?(o)
52
69
 
53
- h = {}
54
- h['kla'] = o.class.to_s
55
- t = nil
70
+ o != nil && o != false
71
+ end
56
72
 
57
- if o.is_a?(::Exception)
73
+ def to_error(o)
58
74
 
59
- h['msg'] = o.message
75
+ h = {}
76
+ h['kla'] = o.class.to_s
60
77
 
61
- t = o.backtrace
78
+ m, t =
79
+ if o.is_a?(::Exception)
80
+ [ o.message, o.backtrace ]
81
+ else
82
+ [ o.to_s, caller[1..-1] ]
83
+ end
62
84
 
63
85
  if n = o.respond_to?(:node) && o.node
86
+ h['prc'] = n.tree[0]
64
87
  h['lin'] = n.tree[2]
65
- #h['tre'] = n.tree
66
88
  end
67
89
 
68
- else
90
+ h['msg'] = m
91
+ h['trc'] = t[0..(t.rindex { |l| l.match(/\/lib\/flor\//) }) + 1] if t
92
+ h['cwd'] = Dir.pwd
93
+ h['rlp'] = $: if o.is_a?(::LoadError)
94
+
95
+ h
96
+ end
69
97
 
70
- h['msg'] = o.to_s
98
+ def const_lookup(s)
71
99
 
72
- t = caller[1..-1]
100
+ s.split('::')
101
+ .select { |ss| ss.length > 0 }
102
+ .inject(Kernel) { |k, sk| k.const_get(sk, k == Kernel) }
73
103
  end
74
104
 
75
- h['trc'] = t[0..(t.rindex { |l| l.match(/\/lib\/flor\//) }) + 1] if t
76
- h['cwd'] = Dir.pwd
77
- h['rlp'] = $: if o.is_a?(::LoadError)
105
+ def to_coll(o)
78
106
 
79
- h
80
- end
107
+ #o.respond_to?(:to_a) ? o.to_a : [ a ]
108
+ Array(o)
109
+ end
81
110
 
82
- def self.const_lookup(s)
111
+ def relativize_path(path, from=Dir.getwd)
83
112
 
84
- s.split('::').inject(Kernel) { |k, sk| k.const_get(sk) }
85
- end
113
+ path = File.absolute_path(path)
86
114
 
87
- def self.to_coll(o)
115
+ path = path[from.length + 1..-1] if path[0, from.length] == from
88
116
 
89
- #o.respond_to?(:to_a) ? o.to_a : [ a ]
90
- Array(o)
91
- end
117
+ path || '.'
118
+ end
92
119
 
93
- def self.relativize_path(path, from=Dir.getwd)
120
+ def is_array_of_messages?(o)
94
121
 
95
- path = File.absolute_path(path)
122
+ o.is_a?(Array) &&
123
+ o.all? { |e|
124
+ e.is_a?(Hash) &&
125
+ e['point'].is_a?(String) &&
126
+ e.keys.all? { |k| k.is_a?(String) } }
127
+ end
96
128
 
97
- path = path[from.length + 1..-1] if path[0, from.length] == from
129
+ def h_fetch(h, *keys)
98
130
 
99
- path || '.'
100
- end
131
+ k = keys.find { |k| h.has_key?(k) }
132
+ k ? h[k] : nil
133
+ end
101
134
 
102
- def self.is_array_of_messages?(o)
135
+ def h_fetch_a(h, *keys)
103
136
 
104
- o.is_a?(Array) &&
105
- o.all? { |e|
106
- e.is_a?(Hash) &&
107
- e['point'].is_a?(String) &&
108
- e.keys.all? { |k| k.is_a?(String) } }
109
- end
137
+ default = keys.last.is_a?(String) ? [] : keys.pop
110
138
 
111
- def self.h_fetch_a(h, *keys)
139
+ k = keys.find { |k| h.has_key?(k) }
140
+ v = k ? h[k] : nil
112
141
 
113
- default = keys.last.is_a?(String) ? [] : keys.pop
142
+ v_to_a(v) || default
143
+ end
114
144
 
115
- k = keys.find { |k| h.has_key?(k) }
116
- v = k ? h[k] : nil
145
+ def v_to_a(o)
117
146
 
118
- v_to_a(v) || default
119
- end
147
+ return o if o.is_a?(Array)
148
+ return o.split(',') if o.is_a?(String)
149
+ return nil if o.nil?
120
150
 
121
- def self.v_to_a(o)
151
+ fail ArgumentError.new("cannot turn instance of #{o.class} into an array")
152
+ end
122
153
 
123
- return o if o.is_a?(Array)
124
- return o.split(',') if o.is_a?(String)
125
- return nil if o.nil?
154
+ def is_regex_string?(s)
126
155
 
127
- fail ArgumentError.new("cannot turn instance of #{o.class} into an array")
128
- end
156
+ !! (
157
+ s.is_a?(String) &&
158
+ s[0] == '/' &&
159
+ s.match(/\/[imxouesn]*\z/)
160
+ )
161
+ end
129
162
 
130
- #
131
- # functions about time
163
+ def to_regex(o)
132
164
 
133
- def self.isostamp(show_date, show_time, show_usec, time)
165
+ s =
166
+ case o
167
+ when String then o
168
+ when Array then o[1].to_s # hopefully regex tree
169
+ else o.to_s
170
+ end
134
171
 
135
- t = (time || Time.now).utc
136
- s = StringIO.new
172
+ m = s.match(/\A\/(.*)\/([imxouesn]*)\z/)
137
173
 
138
- s << t.strftime('%Y-%m-%d') if show_date
139
- s << t.strftime('T%H:%M:%S') if show_time
140
- s << sprintf('.%06d', t.usec) if show_time && show_usec
141
- s << 'Z' if show_time
174
+ return Regexp.new(s) unless m
142
175
 
143
- s.string
144
- end
176
+ m1 = m[1]
177
+ e = (m[2].match(/[uesn]/) || [])[0]
145
178
 
146
- def self.tstamp(t=Time.now)
179
+ m1 =
180
+ case e
181
+ when 'u' then m1.encode('UTF-8')
182
+ when 'e' then m1.encode('EUC-JP')
183
+ when 's' then m1.encode('Windows-31J')
184
+ when 'n' then m1.encode('ASCII-8BIT')
185
+ else m1
186
+ end
147
187
 
148
- isostamp(true, true, true, t)
149
- end
188
+ flags = 0
189
+ flags = flags | Regexp::EXTENDED if m[2].index('x')
190
+ flags = flags | Regexp::IGNORECASE if m[2].index('i')
191
+ #flags = flags | Regexp::MULTILINE if m[2].index('m')
192
+ flags = flags | Regexp::FIXEDENCODING if e
150
193
 
151
- def self.ststamp(t=Time.now)
194
+ Regexp.new(m1, flags)
195
+ end
152
196
 
153
- isostamp(true, true, false, t)
154
- end
197
+ #
198
+ # functions about time
155
199
 
156
- def self.dstamp(t=Time.now)
200
+ def isostamp(show_date, show_time, show_usec, time)
157
201
 
158
- isostamp(true, false, false, t)
159
- end
202
+ t = (time || Time.now).utc
203
+ s = StringIO.new
160
204
 
161
- def self.tamp(t=Time.now)
205
+ s << t.strftime('%Y-%m-%d') if show_date
206
+ s << t.strftime('T%H:%M:%S') if show_time
207
+ s << sprintf('.%06d', t.usec) if show_time && show_usec
208
+ s << 'Z' if show_time
162
209
 
163
- t = t.utc
164
- s = StringIO.new
165
- s << t.strftime('%Y%m%dT%H%M%S') << sprintf('.%06dZ', t.usec)
210
+ s.string
211
+ end
166
212
 
167
- s.string
168
- end
213
+ def tstamp(t=Time.now)
169
214
 
170
- # hour stamp
171
- #
172
- def self.hstamp(t=Time.now)
215
+ isostamp(true, true, true, t)
216
+ end
173
217
 
174
- isostamp(false, true, true, t)
175
- end
218
+ def ststamp(t=Time.now)
219
+
220
+ isostamp(true, true, false, t)
221
+ end
222
+
223
+ def dstamp(t=Time.now)
224
+
225
+ isostamp(true, false, false, t)
226
+ end
227
+
228
+ def tamp(t=Time.now)
229
+
230
+ t = t.utc
231
+ s = StringIO.new
232
+ s << t.strftime('%Y%m%dT%H%M%S') << sprintf('.%06dZ', t.usec)
233
+
234
+ s.string
235
+ end
176
236
 
177
- # def self.to_time(ts)
237
+ # hour stamp
238
+ #
239
+ def hstamp(t=Time.now)
240
+
241
+ isostamp(false, true, true, t)
242
+ end
243
+
244
+ # def to_time(ts)
178
245
  #
179
246
  # m = ts.match(/\A(\d{4})(\d{2})(\d{2})\.(\d{2})(\d{2})(\d{2})(\d+)([uU]?)\z/)
180
247
  # fail ArgumentError.new("cannot parse timestamp #{ts.inspect}") unless m
@@ -183,194 +250,204 @@ module Flor
183
250
  # Time.local(*m[1, 7].collect(&:to_i))
184
251
  # end
185
252
 
186
- #
187
- # functions about domains and units
188
-
189
- NAME_REX = '[a-zA-Z0-9_]+'
190
- UNIT_NAME_REX = /\A#{NAME_REX}\z/
191
- DOMAIN_NAME_REX = /\A#{NAME_REX}(\.#{NAME_REX})*\z/
192
- FLOW_NAME_REX = /\A(#{NAME_REX}(?:\.#{NAME_REX})*)\.([a-zA-Z0-9_-]+)\z/
253
+ #
254
+ # functions about domains and units
193
255
 
194
- def self.potential_unit_name?(s)
256
+ def potential_unit_name?(s)
195
257
 
196
- s.is_a?(String) && s.match(UNIT_NAME_REX)
197
- end
258
+ s.is_a?(String) && !! s.match(UNIT_NAME_REX)
259
+ end
198
260
 
199
- def self.potential_domain_name?(s)
261
+ def potential_domain_name?(s)
200
262
 
201
- s.is_a?(String) && s.match(DOMAIN_NAME_REX)
202
- end
263
+ s.is_a?(String) && !! s.match(DOMAIN_NAME_REX)
264
+ end
203
265
 
204
- def self.split_flow_name(s)
266
+ def split_flow_name(s)
205
267
 
206
- if s.is_a?(String) && m = s.match(FLOW_NAME_REX)
207
- [ m[1], m[2] ]
208
- else
209
- nil
268
+ if s.is_a?(String) && m = s.match(FLOW_NAME_REX)
269
+ [ m[1], m[2] ]
270
+ else
271
+ nil
272
+ end
210
273
  end
211
- end
212
-
213
- def self.is_sub_domain?(dom, sub)
214
274
 
215
- fail ArgumentError.new(
216
- "not a domain #{dom.inspect}"
217
- ) unless potential_domain_name?(dom)
275
+ def is_sub_domain?(dom, sub)
218
276
 
219
- fail ArgumentError.new(
220
- "not a sub domain #{sub.inspect}"
221
- ) unless potential_domain_name?(sub)
277
+ fail ArgumentError.new(
278
+ "not a domain #{dom.inspect}"
279
+ ) unless potential_domain_name?(dom)
222
280
 
223
- sub == dom || sub[0, dom.length + 1] == dom + '.'
224
- end
281
+ fail ArgumentError.new(
282
+ "not a sub domain #{sub.inspect}"
283
+ ) unless potential_domain_name?(sub)
225
284
 
226
- DOMAIN_UNIT_REX = /\A(#{NAME_REX}(?:\.#{NAME_REX})*)-(#{NAME_REX})[-\z]/
285
+ sub == dom || sub[0, dom.length + 1] == dom + '.'
286
+ end
227
287
 
228
- def self.split_domain_unit(s)
288
+ def split_domain_unit(s)
229
289
 
230
- if m = DOMAIN_UNIT_REX.match(s)
231
- [ m[1], m[2] ]
232
- else
233
- []
290
+ if m = DOMAIN_UNIT_REX.match(s)
291
+ [ m[1], m[2] ]
292
+ else
293
+ []
294
+ end
234
295
  end
235
- end
236
296
 
237
- def self.domain(s)
297
+ def domain(s)
238
298
 
239
- split_domain_unit(s).first
240
- end
299
+ split_domain_unit(s).first
300
+ end
241
301
 
242
- def self.unit(s)
302
+ def unit(s)
243
303
 
244
- split_domain_unit(s).last
245
- end
304
+ split_domain_unit(s).last
305
+ end
246
306
 
247
- def self.to_pretty_s(o, twidth=79)
307
+ def to_pretty_s(o, twidth=79)
248
308
 
249
- sio = StringIO.new
250
- PP.pp(o, sio, twidth)
309
+ sio = StringIO.new
310
+ PP.pp(o, sio, twidth)
251
311
 
252
- sio.string
253
- end
312
+ sio.string
313
+ end
254
314
 
255
315
 
256
- #
257
- # tree
316
+ #
317
+ # tree
258
318
 
259
- def self.is_tree?(t)
319
+ def is_tree?(t)
260
320
 
261
- t.is_a?(Array) &&
262
- t.size > 2 &&
263
- (t[0].is_a?(String) || Flor.is_tree?(t[0])) &&
264
- t[2].is_a?(Integer)
265
- end
321
+ t.is_a?(Array) &&
322
+ t.size > 2 &&
323
+ (t[0].is_a?(String) || Flor.is_tree?(t[0])) &&
324
+ t[2].is_a?(Integer)
325
+ end
266
326
 
267
- def self.is_string_tree?(t, s=nil)
327
+ def is_string_tree?(t, s=nil)
268
328
 
269
- t.is_a?(Array) &&
270
- t[2].is_a?(Integer) &&
271
- %w[ _sqs _dqs ].include?(t[0]) &&
272
- (s ? (t[1] == s) : t[1].is_a?(String))
273
- end
329
+ t.is_a?(Array) &&
330
+ t[2].is_a?(Integer) &&
331
+ %w[ _sqs _dqs ].include?(t[0]) &&
332
+ (s ? (t[1] == s) : t[1].is_a?(String))
333
+ end
274
334
 
275
- def self.is_att_tree?(t)
335
+ def is_att_tree?(t)
276
336
 
277
- t.is_a?(Array) &&
278
- t[2].is_a?(Integer) &&
279
- t[0] == '_att' &&
280
- t[1].is_a?(Array)
281
- end
337
+ t.is_a?(Array) &&
338
+ t[2].is_a?(Integer) &&
339
+ t[0] == '_att' &&
340
+ t[1].is_a?(Array)
341
+ end
282
342
 
283
- def self.is_array_of_trees?(o)
343
+ def is_array_of_trees?(o)
284
344
 
285
- o.is_a?(Array) &&
286
- o.all? { |e| Flor.is_tree?(e) }
287
- end
345
+ o.is_a?(Array) &&
346
+ o.all? { |e| Flor.is_tree?(e) }
347
+ end
288
348
 
289
349
  # # Array, object or atom tree
290
350
  # #
291
- # def self.is_value_tree?(o)
351
+ # def is_value_tree?(o)
292
352
  #
293
353
  # o.is_a?(Array) &&
294
354
  # %w[ _num _boo _sqs _dqs _rxs _nul _arr _obj ].include?(o[0]) &&
295
355
  # o[2].is_a?(Integer)
296
356
  # end
297
357
 
298
- def self.is_proc_tree?(o)
299
-
300
- o.is_a?(Array) &&
301
- o[0] == '_proc' &&
302
- o[2].is_a?(Integer) &&
303
- o[1].is_a?(Hash) &&
304
- o[1]['proc'].is_a?(String)
305
- end
306
-
307
- def self.is_func_tree?(o)
358
+ def is_proc_tree?(o)
308
359
 
309
- o.is_a?(Array) &&
310
- o[0] == '_func' &&
311
- o[2].is_a?(Integer) &&
312
- o[1].is_a?(Hash) && (o[1].keys & %w[ nid cnid fun ]).size == 3
313
- end
360
+ o.is_a?(Array) &&
361
+ o[0] == '_proc' &&
362
+ o[2].is_a?(Integer) &&
363
+ o[1].is_a?(Hash) &&
364
+ o[1]['proc'].is_a?(String)
365
+ end
314
366
 
315
- def self.is_task_tree?(o)
367
+ def is_func_tree?(o)
316
368
 
317
- o.is_a?(Array) &&
318
- o[0] == '_task' &&
319
- o[2].is_a?(Integer) &&
320
- o[1].is_a?(Hash) &&
321
- o[1]['task'].is_a?(String)
322
- end
369
+ o.is_a?(Array) &&
370
+ o[0] == '_func' &&
371
+ o[2].is_a?(Integer) &&
372
+ o[1].is_a?(Hash) && (o[1].keys & %w[ nid cnid fun ]).size == 3
373
+ end
323
374
 
324
- # Returns [ st, i ], the parent subtree for the final i index of the nid
325
- # Used when inserting updated subtrees.
326
- #
327
- def self.parent_tree_locate(t, nid)
375
+ # def is_task_tree?(o)
376
+ #
377
+ # o.is_a?(Array) &&
378
+ # o[0] == '_task' &&
379
+ # o[2].is_a?(Integer) &&
380
+ # o[1].is_a?(Hash) &&
381
+ # o[1]['task'].is_a?(String)
382
+ # end
383
+
384
+ def is_regex_tree?(o)
385
+
386
+ o.is_a?(Array) &&
387
+ o[0] == '_rxs' &&
388
+ o[2].is_a?(Integer) &&
389
+ o[1].is_a?(String) &&
390
+ o[1].match(/\A\/.*\/[a-zA-Z]*\z/)
391
+ end
328
392
 
329
- return nil if t == nil
393
+ # Returns [ st, i ], the parent subtree for the final i index of the nid
394
+ # Used when inserting updated subtrees.
395
+ #
396
+ def parent_tree_locate(t, nid)
330
397
 
331
- n, i, d = nid.split('_', 3)
398
+ return nil if t == nil
332
399
 
333
- return [ t, nil ] if i == nil
334
- return [ t, i.to_i ] if ! d
335
- parent_tree_locate(t[1][i.to_i], [ i, d ].join('_'))
336
- end
400
+ n, i, d = nid.split('_', 3)
337
401
 
338
- # Returns the subtree down at the given nid
339
- #
340
- def self.tree_locate(t, nid)
402
+ return [ t, nil ] if i == nil
403
+ return [ t, i.to_i ] if ! d
404
+ parent_tree_locate(t[1][i.to_i], [ i, d ].join('_'))
405
+ end
341
406
 
342
- st, i = parent_tree_locate(t, nid)
407
+ # Returns the subtree down at the given nid
408
+ #
409
+ def tree_locate(t, nid)
343
410
 
344
- return nil if st == nil
345
- return st if i == nil
346
- st[1][i]
347
- end
411
+ st, i = parent_tree_locate(t, nid)
348
412
 
413
+ return nil if st == nil
414
+ return st if i == nil
415
+ st[1][i]
416
+ end
349
417
 
350
- #
351
- # splat
352
418
 
353
- SPLAT_REGEX = /\A(.*)__(_|\d+)\z/.freeze
419
+ #
420
+ # splat
354
421
 
355
- def self.splat(keys, array)
422
+ def splat(keys, array)
356
423
 
357
- ks = keys.dup
358
- a = array.dup
359
- h = {}
424
+ ks = keys.dup
425
+ a = array.dup
426
+ h = {}
360
427
 
361
- while k = ks.shift
428
+ while k = ks.shift
362
429
 
363
- if m = SPLAT_REGEX.match(k)
364
- r, l = m[1, 2]
365
- l = (l == '_') ? a.length - ks.length : l.to_i
366
- h[r] = a.take(l) if r.length > 0
367
- a = a.drop(l)
368
- else
369
- h[k] = a.shift
430
+ if m = SPLAT_REGEX.match(k)
431
+ r, l = m[1, 2]
432
+ l = (l == '_') ? a.length - ks.length : l.to_i
433
+ h[r] = a.take(l) if r.length > 0
434
+ a = a.drop(l)
435
+ else
436
+ h[k] = a.shift
437
+ end
370
438
  end
439
+
440
+ h
371
441
  end
372
442
 
373
- h
443
+
444
+ #
445
+ # misc
446
+
447
+ def point?(s)
448
+
449
+ POINTS.include?(s)
450
+ end
374
451
  end
375
452
  end
376
453