module Flor
Constants
- COLS
- DOMAIN_NAME_REX
- DOMAIN_UNIT_REX
- FLOW_NAME_REX
- MODELS
- NAME_REX
- NID_REX
- POINTS
- SPLAT_REGEX
- START_NID_REX
- TO_ERROR_MESSAGE_KEYS
- UNIT_NAME_REX
- Unit
- VERSION
Public Class Methods
# File lib/flor/unit/models.rb, line 136 def self.add_model(key, parent_module=Flor, table_prefix='flor_') Flor::Storage.send(:define_method, key) do s = self c = Flor.to_camel_case(key.to_s[0..-2]) @models[key] ||= parent_module.const_set( "#{c}#{self.object_id.to_s.gsub('-', 'M')}", Class.new(parent_module.const_get(c)) do self.dataset = s.db["#{table_prefix}#{key}".to_sym] self.unit = s.unit end) end Flor::Scheduler.send(:define_method, key) do @storage.send(key) end end
# File lib/flor/flor.rb, line 768 def caller_fname caller .find { |l| ! l.match(/\/lib\/flor\//) } .match(/\A([^:]+:\d+)/)[1] .strip end
# File lib/flor/id.rb, line 34 def child_id(nid) nid ? nid.split('_').last.split('-').first.to_i : nil end
# File lib/flor/id.rb, line 76 def child_nid(nid, i, sub=nil) nid, subnid = nid.split('-') subnid = sub if sub && sub > 0 "#{nid}_#{i}#{subnid ? "-#{subnid}" : ''}" end
# File lib/flor/colours.rb, line 61 def self.colours(opts={}) #opts = # case opts # when Hash then opts # when Colours, NoColours then { color: opts } # else { out: opts } # end c = nil; [ :color, :colour, :colors, :colours ].each do |k| if opts.has_key?(k); c = opts[k]; break; end end return @colours if c == true return @no_colours if c == false o = opts[:out] || $stdout return @colours if ( (o.respond_to?(:log_colours?) ? o.log_colours? : o.tty?) || ($0[-6..-1] == '/rspec' && (ARGV.include?('--tty') || ARGV.include?('--color')))) @no_colours end
# File lib/flor/flor.rb, line 165 def const_lookup(s) s.split('::') .select { |ss| ss.length > 0 } .inject(Kernel) { |k, sk| k.const_get(sk, k == Kernel) } end
# File lib/flor/colours.rb, line 88 def self.decolour(s) s.gsub(/\x1b\[\d+(;\d+)?m/, '') end
# File lib/flor/flor.rb, line 55 def deep_merge(o0, o1, in_place=false) t0 = type(o0) t1 = type(o1) return o1 if t1 != t0 if t0 == :array o1.each_with_index.inject(in_place ? o0 : o0.dup) { |a, (e1, i)| a[i] = deep_merge(o0[i], e1, in_place) a } elsif t0 == :object o1.inject(in_place ? o0 : o0.dup) { |h, (k, v1)| h[k] = deep_merge(o0[k], v1, in_place) h } else o1 end end
# File lib/flor/flor.rb, line 75 def deep_merge!(o0, o1) deep_merge(o0, o1, true) end
# File lib/flor/flor.rb, line 405 def domain(s) split_domain_unit(s).first end
# File lib/flor/flor.rb, line 381 def dot_join(*elts) elts.collect(&:to_s).select { |e| e.length > 0 }.join('.') end
# File lib/flor/flor.rb, line 311 def dstamp(t=Time.now) isostamp(true, false, false, t) end
See Scheduler#dump
for the details
# File lib/flor/unit/dump.rb, line 9 def dump(db_or_unit_or_uri, io=nil, opts=nil, &block) derive_unit(db_or_unit_or_uri) .dump(io, opts, &block) end
Returns a new, complete (not shallow), copy of the target instance.
# File lib/flor/flor.rb, line 44 def dup(o) Marshal.load(Marshal.dump(o)) end
# File lib/flor/flor.rb, line 49 def dup_and_merge(h, hh) self.dup(h).merge!(hh) end
# File lib/flor/flor.rb, line 80 def dup_message(m) tc = m.delete('tconf') m1 = Flor.dup(m) m1['tconf'] = tc .inject({}) { |h, (k, v)| h[k] = case k when 'class' then v else Flor.dup(v) end h } if tc m1 end
# File lib/flor/flor.rb, line 53 def dupm(h, hh); self.dup_and_merge(h, hh); end
misc
miscellaneous functions
# File lib/flor/flor.rb, line 37 def env_i(k) v = ENV[k]; (v && v.match(/\A\d+\z/)) ? v.to_i : nil end
# File lib/flor/id.rb, line 24 def exid(fei) split_fei(fei).first end
Returns [ exid, nid ]
# File lib/flor/id.rb, line 128 def extract_exid_and_nid(s) m = s.match(/(\d{8}\.\d{4}\.[a-z]+)-(\d+(?:_\d+)*)(-\d+)?/) m ? [ m[1], [ m[2], m[3] ].compact.join ] : nil end
# File lib/flor/flor.rb, line 97 def false?(o) o == nil || o == false end
# File lib/flor/unit/storage.rb, line 964 def from_blob(content); ::Flor::Storage.from_blob(content); end
# File lib/flor/core.rb, line 5 def self.generate_exid(domain, unit) @exid_counter ||= 0 @exid_mutex ||= Mutex.new t = Time.now.utc sus = @exid_mutex.synchronize do sus = t.sec * 100000000 + t.usec * 100 + @exid_counter @exid_counter = @exid_counter + 1 @exid_counter = 0 if @exid_counter > 99 Munemo.to_s(sus) end t = t.strftime('%Y%m%d.%H%M') "#{domain}-#{unit}-#{t}.#{sus}" end
# File lib/flor/flor.rb, line 205 def h_fetch(h, *keys) k = keys.find { |kk| h.has_key?(kk) } k ? h[k] : nil end
# File lib/flor/flor.rb, line 211 def h_fetch_a(h, *keys) default = keys.last.is_a?(String) ? [] : keys.pop k = keys.find { |kk| h.has_key?(kk) } v = k ? h[k] : nil v_to_a(v) || default end
hour stamp
# File lib/flor/flor.rb, line 327 def hstamp(t=Time.now) isostamp(false, true, true, t) end
# File lib/flor/flor.rb, line 199 def is_array_of_messages?(o) o.is_a?(Array) && o.all? { |e| is_message?(e) } end
# File lib/flor/flor.rb, line 490 def is_array_of_trees?(o) o.is_a?(Array) && o.all? { |e| Flor.is_tree?(e) } end
# File lib/flor/flor.rb, line 468 def is_att_tree?(t) t.is_a?(Array) && t[2].is_a?(Integer) && t[0] == '_att' && t[1].is_a?(Array) end
# File lib/flor/flor.rb, line 172 def is_collection?(o) o.is_a?(Array) || o.is_a?(Hash) end
# Array, object or atom tree # def is_value_tree?(o)
o.is_a?(Array) && %w[ _num _boo _sqs _dqs _rxs _nul _arr _obj ].include?(o[0]) && o[2].is_a?(Integer)
end
# File lib/flor/flor.rb, line 460 def is_collection_tree?(t) t.is_a?(Array) && (t[0] == '_arr' || t[0] == '_obj') && t[1].is_a?(Array) end
# File lib/flor/flor.rb, line 484 def is_def_tree?(t) is_definition_tree?(t) && t[0] != 'define' end
# File lib/flor/flor.rb, line 476 def is_definition_tree?(t) t.is_a?(Array) && Flor::Pro::Define.names.include?(t[0]) && t[2].is_a?(Integer) && t[1].is_a?(Array) end
# File lib/flor/id.rb, line 121 def is_exid?(s) !! split_exid(s) end
# File lib/flor/flor.rb, line 510 def is_func_tree?(o) o.is_a?(Array) && o[0] == '_func' && o[2].is_a?(Integer) && o[1].is_a?(Hash) && (o[1].keys & %w[ nid cnid fun ]).size == 3 end
# File lib/flor/flor.rb, line 443 def is_leaf_tree?(t) t.is_a?(Array) && t[2].is_a?(Integer) && Flor::Pro::Atom.names.include?(t[0]) end
# File lib/flor/flor.rb, line 192 def is_message?(o) o.is_a?(Hash) && o['point'].is_a?(String) && o.keys.all? { |k| k.is_a?(String) } end
# File lib/flor/id.rb, line 103 def is_nid?(s) !! (s.is_a?(String) && s.match(NID_REX)) end
# File lib/flor/flor.rb, line 546 def is_num_tree?(o) o.is_a?(Array) && o[0] == '_num' && o[2].is_a?(Integer) && o[1].is_a?(Numeric) end
# File lib/flor/flor.rb, line 501 def is_proc_tree?(o) o.is_a?(Array) && o[0] == '_proc' && o[2].is_a?(Integer) && o[1].is_a?(Hash) && o[1]['proc'].is_a?(String) end
# File lib/flor/flor.rb, line 554 def is_ref_tree?(o) o.is_a?(Array) && Flor::Pro::Ref.names.include?(o[0]) && o[2].is_a?(Integer) && o[1].is_a?(Array) && o[1].all? { |e| is_sqs_tree?(e) || is_num_tree?(e) } end
# File lib/flor/flor.rb, line 230 def is_regex_string?(s) !! ( s.is_a?(String) && s[0] == '/' && s.match(/\/[imxouesn]*\z/) ) end
# File lib/flor/flor.rb, line 529 def is_regex_tree?(o) o.is_a?(Array) && o[0] == '_rxs' && o[2].is_a?(Integer) && o[1].is_a?(String) && o[1].match(/\A\/.*\/[a-zA-Z]*\z/) end
# File lib/flor/flor.rb, line 496 def is_single_ref_tree?(t) t.is_a?(Array) && t[0].is_a?(String) && t[0] != '_' && t[1] == [] end
# File lib/flor/flor.rb, line 538 def is_sqs_tree?(o) o.is_a?(Array) && o[0] == '_sqs' && o[2].is_a?(Integer) && o[1].is_a?(String) end
# File lib/flor/flor.rb, line 435 def is_string_tree?(t, s=nil) t.is_a?(Array) && t[2].is_a?(Integer) && %w[ _sqs _dqs ].include?(t[0]) && (s ? (t[1] == s) : t[1].is_a?(String)) end
# File lib/flor/flor.rb, line 368 def is_sub_domain?(dom, sub) fail ArgumentError.new( "not a domain #{dom.inspect}" ) unless potential_domain_name?(dom) fail ArgumentError.new( "not a sub domain #{sub.inspect}" ) unless potential_domain_name?(sub) sub_domain?(dom, sub) end
# File lib/flor/flor.rb, line 518 def is_tasker_tree?(o) # [ '_tasker', { 'tasker' => 'alan' }, -1 ] o.is_a?(Array) && o[0] == '_tasker' && o[2].is_a?(Integer) && o[1].is_a?(Hash) && o[1]['tasker'].is_a?(String) end
tree
# File lib/flor/flor.rb, line 427 def is_tree?(t) t.is_a?(Array) && t.size > 2 && (t[0].is_a?(String) || Flor.is_tree?(t[0])) && t[2].is_a?(Integer) end
# File lib/flor/flor.rb, line 288 def isostamp(show_date, show_time, show_usec, time) t = (time || Time.now).utc s = StringIO.new s << t.strftime('%F') if show_date # YYYY-mm-dd s << t.strftime('T%T') if show_time # THH:MM:SS s << sprintf('.%06d', t.usec) if show_time && show_usec s << 'Z' if show_time s.string end
See Scheduler#load
for the details
# File lib/flor/unit/dump.rb, line 17 def load(db_or_unit_or_uri, string_or_io, opts={}, &block) derive_unit(db_or_unit_or_uri) .load(string_or_io, opts, &block) end
# File lib/flor/core.rb, line 69 def self.load_procedures(dir) dirpath = if dir.match(/\A[.\/]/) File.join(dir, '*.rb') else File.join(File.dirname(__FILE__), dir, '*.rb') end Dir[dirpath].sort.each { |path| require(path) } end
# File lib/flor/core.rb, line 28 def self.make_launch_msg(exid, tree, opts) t = tree.is_a?(String) ? Flor.parse(tree, opts[:fname] || opts[:path], opts) : tree unless t #h = opts.merge(prune: false, rewrite: false, debug: 0) #Raabro.pp(Flor.parse(tree, h[:fname], h)) # TODO re-parse and indicate what went wrong... fail ArgumentError.new( "flow parsing failed: " + tree.inspect[0, 35] + '...') end pl = opts[:payload] || opts[:fields] || {} vs = opts[:variables] || opts[:vars] || {} fail ArgumentError.new( "given launch payload should be a Hash, but it's a #{pl.class}" ) unless pl.is_a?(Hash) fail ArgumentError.new( "given launch variables should come in a Hash, but it's a #{vs.class}" ) unless vs.is_a?(Hash) msg = { 'point' => 'execute', 'exid' => exid, 'nid' => '0', 'tree' => t, 'payload' => pl, 'vars' => vs } msg['vdomain'] = opts[:vdomain] \ if opts.has_key?(:vdomain) msg end
Remove the sub_nid
if any.
# File lib/flor/id.rb, line 71 def master_nid(nid) nid.split('-').first end
Turns a flor message into a one line string. Used when logging messages.
# File lib/flor/log.rb, line 9 def message_to_one_line_s(executor, m, opts={}) _c = colours(opts) nid = m['nid'] nd = executor.node(nid) a = [ ' ' ] n = Time.now.utc a << opts[:date] ? n.strftime('%Y%m%d.%H:%M:%S') + sprintf('.%06d', n.usec)[0, 4] : n.strftime('%H:%M:%S') + sprintf('.%06d', n.usec)[0, 4] a << ' ' << _c.dg if ex = (m['exid'] || '').split('.').last a << ex[-4..-1] << ' ' end a << "#{nd ? _c.dg : _c.dim + _c.dg}#{nid}#{_c.rs}#{_c.dg} " if nid pt = m['point'][0, 3] _pt = case pt when 'tri', 'sig' then _c.gr when 'cea', 'ter' then _c.lg when 'can' then _c.ma else _c.bl end a << "#{_pt}#{pt}#{_c.dg}" fla = m['flavour'] a << " #{_c.lg}#{fla}#{_c.dg}" if fla st = nd && nd['status'].last a << " #{_c.dim}#{_c.lg}#{st['status']}:#{st['flavour']}#{_c.rs}#{_c.dg}"\ if st && st['status'] t = m['tree'] rw = (t && m['rewritten']) ? 'rw->' : '' nt = t || Node.new(executor, nd, m).lookup_tree(nid) a << if t " [#{rw}#{_c.yl}#{Flor.to_d(t[0], compact: true)}#{_c.dg} L#{t[2]}]" elsif nt " [#{_c.dg}#{Flor.to_d(nt[0], compact: true)}#{_c.dg} L#{nt[2]}]" else '' end a << (m['on_error'] ? " #{_c.rd}on_error" : '') tmi = m['timer_id'] tmi = tmi ? " #{_c.dg}tmi:#{tmi}" : '' a << tmi # tri = m['trap_id'] tri = tri ? " #{_c.dg}tri:#{tri}" : '' a << tri cn = t ? " #{_c.dg}#{Flor.to_d(t[1], compact: true, inner: true)}" : '' cn = Flor.truncate_string(cn, 49, "#{_c.dg}...#{_c.rs}") a << cn hp = nd && nd['heap'] hp = (hp && (hp != (t || [])[0])) ? " #{_c.dg}hp:#{nd['heap']}" : '' a << hp msr = " #{_c.dg}m#{m['m']}s#{m['sm'] || '_'}" msr += "r#{m['er']}>#{m['pr']}" if m['er'] && m['er'] > -1 a << msr a << (m['from'] ? " from #{m['from']}" : '') if cs = m['cause'] a << " <" << cs .collect { |c| [ c['cause'][0, 2], c['nid'], "m#{c['m']}", c['type'] ] .compact.join(':') } .join('<') end rt = ret_to_s(executor, m, _c) rt = rt.length > 0 ? " #{_c.lg}f.ret #{rt}" : '' a << rt a << ( (m['point'] == 'entered' || m['point'] == 'left') ? " #{_c.dg}tags:#{_c.gr}#{m['tags'].join(',')}" : nil) a << ( (nd && nd['vars']) ? " #{_c.dg}vars:#{_c.gr}#{nd['vars'].keys.join("#{_c.dg},#{_c.gr}")}" : '') %w[ fpoint dbg ].each do |k| a << " #{_c.dg}#{k}:#{m[k]}" if m.has_key?(k) end #a << " #{_c.dim}#{_c.dg}" #a << "pl#{Flor.to_d(m['payload'], compact: true, colors: false)}" # # keep that around for when debugging payload shifts # eventually consider FLOR_DEBUG flag a << _c.rs a.join end
# File lib/flor/to_string.rb, line 28 def self.message_to_s(m) s = StringIO.new s << '(msg ' << m['nid'] << ' ' << m['point'] %w[ from flavour ].each { |k| s << ' ' << k << ':' << m[k].to_s if m.has_key?(k) } s << ')' s.string end
Available as ‘Flor.migration_dir`
# File lib/flor/flor.rb, line 763 def migration_dir File.join(__dir__, 'migrations') end
# File lib/flor/flor.rb, line 332 def monow Process.clock_gettime(Process::CLOCK_MONOTONIC) end
# File lib/flor/log.rb, line 324 def msg_to_detail_s(executor, m, opts={}) return if m['_detail_msg_flag'] # m['_detail_msg_flag'] = true if opts[:flag] o = StringIO.new _c = colours(opts) nid = m['nid'] n = executor.execution['nodes'][nid] node = n ? Flor::Node.new(executor, n, m) : nil o.puts "#{_c.rs}#{_c.dg}<Flor.msg_to_detail_s>" o.puts "#{_c.dg}message:#{_c.yl}" #o.puts YAML.dump(m) o.puts(Flor.to_djan(m, indent: 2, width: true)) o.puts "#{_c.dg}tree:#{_c.yl}" o.puts(tree_to_s(node.lookup_tree(nid), nid, out: o)) if node o.puts "#{_c.dg}node:#{_c.yl}" #o.puts n ? YAML.dump(n.merge('tree' => '(above)')) : 'nil' o.puts( n ? Flor.to_djan(n.merge('tree' => '(above)'), indent: 2, width: true) : 'nil') o.puts "#{_c.dg}nodes:#{_c.yl}" o.puts nods_to_s(executor, m, opts) z = executor.execution['nodes'].size o.puts "#{_c.yl}#{z} node#{z == 1 ? '' : 's'}." o.puts "#{_c.dg}</Flor.msg_to_detail_s>#{_c.rs}" o.string end
# File lib/flor/log.rb, line 291 def ncns_to_s(executor, ncn, msg, opts, sio, ind, seen) n, cn = ncn nid = n['nid'] return if seen.include?(nid) seen << nid sio.print(ind) sio.print(nod_to_s(executor, n, opts, nid == msg['nid'])) sio.print("\n") cn.each { |c| ncns_to_s(executor, c, msg, opts, sio, ind + ' ', seen) } end
# File lib/flor/id.rb, line 39 def next_child_id(nid) child_id(nid) + 1 end
# File lib/flor/flor.rb, line 114 def no?(o) oo = o.respond_to?(:downcase) ? o.downcase : o [ 'n', 'no', 'false', false ].include?(o) end
# File lib/flor/colours.rb, line 93 def self.no_colour_length(s) decolour(s).length end
# File lib/flor/colours.rb, line 56 def self.no_colours @no_colours end
# File lib/flor/log.rb, line 259 def nod_to_s(executor, n, opts, here=false) _c = colours(opts) t = n['tree'] || Node.new(executor, n, nil).lookup_tree(n['nid']) if t t = Flor.to_d(t, compact: true) t = Flor.truncate_string(t, 42) end h = n.select { |k, _| [ 'parent' 'cnid' 'dbg' 'replyto', 'noreply' # "for backward compatibility ].include?(k) } #dbg = n['dbg'] ? "dbg:#{n['dbg']}" : nil #nr = n.has_key?('noreply') ? "nr:#{n['noreply']}" : nil h = h.collect { |k, v| "#{k}:#{v}" }.join(' ') vs = n['vars'] vs = 'vars:' + vs.keys.join(',') if vs ts = n['tags'] ts = 'tags:' + ts.join(',') if ts flr = n['failure'] ? "#{_c.rd}flre" : '' here = here ? "#{_c.dg}<---msg['nid']" : nil [ _c.yl + n['nid'], t, h, ts, vs, flr, here ].compact.join(' ') end
# File lib/flor/to_string.rb, line 39 def self.node_status_to_s(n) stas = n['status'].reverse s = StringIO.new while sta = stas.shift s << '(status ' << (sta['status'] || 'o') # o for open s << ' pt:' << sta['point'] if f = sta['flavour']; s << ' fla:' << f; end if f = sta['from']; s << ' fro:' << f; end if m = sta['m']; s << ' m:' << m; end s << ')' s << "\n" if stas.any? end s.string end
# File lib/flor/to_string.rb, line 57 def self.node_to_s(n) # there is already a .node_to_s in log.rb n.inspect end
# File lib/flor/log.rb, line 305 def nods_to_s(executor, msg, opts) nodes = executor.execution['nodes'].values nodes = nodes.inject({}) { |h, n| h[n['nid']] = [ n, [] ]; h } nodes.values.each { |ncn| pa = ncn.first['parent']; next unless pa _, pacn = nodes[pa] pacn << ncn if pacn } sio = StringIO.new seen = [] nodes.values.each do |ncn| ncns_to_s(executor, ncn, msg, opts, sio, ' ', seen) end sio.string end
# File lib/flor/id.rb, line 85 def parent_id(nid) if i = nid.rindex('_') nid[0, i] else nil end end
# File lib/flor/id.rb, line 94 def parent_nid(nid, remove_subnid=false) _, sub = nid.split('-') i = nid.rindex('_') return nil unless i "#{nid[0, i]}#{remove_subnid || sub.nil? ? nil : "-#{sub}"}" end
Returns [ st, i ], the parent subtree for the final i index of the nid Used when inserting updated subtrees.
# File lib/flor/flor.rb, line 571 def parent_tree_locate(t, nid) return nil if t == nil _, i, d = nid.split('_', 3) return [ t, nil ] if i == nil return [ t, i.to_i ] if d == nil parent_tree_locate(t[1][i.to_i], [ i, d ].join('_')) end
# File lib/flor/parser.rb, line 5 def self.parse(input, fname=nil, opts={}) #Raabro.pp(Flor::Parser.parse(input, debug: 2), colours: true) #Raabro.pp(Flor::Parser.parse(input, debug: 3), colours: true) # # turn one or the other when debugging the parser... opts = fname if fname.is_a?(Hash) && opts.empty? if r = Flor::Parser.parse(input, opts) r << fname if fname r else r = Flor::Parser.parse(input, opts.merge(error: true)) fail Flor::ParseError.new(r, fname) end end
# File lib/flor/flor.rb, line 704 def path_elt_to_dense_path_elt(elt) case elt #when String then elt #when Integer then elt when { 'dot' => true } then :dot when { 'star' => true } then :star when { 'dotstar' => true } then :star when Array then elt.collect { |e| path_elt_to_dense_path_elt(e) } # TODO regexes else elt end end
# File lib/flor/flor.rb, line 699 def path_to_dense_path(path) Dense::Path.make(path.collect { |e| path_elt_to_dense_path_elt(e) }) end
Dense paths
# File lib/flor/flor.rb, line 694 def path_to_s(path) path_to_dense_path(path).to_s end
misc
# File lib/flor/flor.rb, line 672 def point?(s) POINTS.include?(s) end
# File lib/flor/flor.rb, line 354 def potential_domain_name?(s) s.is_a?(String) && !! s.match(DOMAIN_NAME_REX) end
functions about domains and units
# File lib/flor/flor.rb, line 349 def potential_unit_name?(s) s.is_a?(String) && !! s.match(UNIT_NAME_REX) end
# File lib/flor/flor.rb, line 563 def ref_to_path(t) t[1].collect { |tt| tt[1].to_s }.join('.') end
# File lib/flor/flor.rb, line 183 def relativize_path(path, from=Dir.getwd) path = File.absolute_path(path) path = path[from.length + 1..-1] if path[0, from.length] == from path || '.' end
# File lib/flor/log.rb, line 238 def ret_to_s(executor, m, c) case pl = m['payload'] when NilClass, Hash ret = (pl || {})['ret'] Flor.truncate_string( Flor.to_d(ret, compact: true), 35, Proc.new { |x| "#{c.dg}... (ln#{x})#{c.rs}" }) else s = "#{c.rd}(/!\\ payload is an instance of #{pl.class}: " + Flor.truncate_string( Flor.to_d(pl, compact: true, color: false), 35, Proc.new { |x| "... (ln#{x})" }) + ")#{c.rs}" s end end
# File lib/flor/id.rb, line 59 def same_branch?(nid0, nid1) return false unless same_sub?(nid0, nid1) n0, n1 = [ nid0, nid1 ].collect { |i| Flor.master_nid(i) }.sort n = n1[0, n0.length] n == n0 end
# File lib/flor/id.rb, line 54 def same_sub?(nid0, nid1) sub_nid(nid0) == sub_nid(nid1) end
# File lib/flor/flor.rb, line 396 def split_domain_unit(s) if m = DOMAIN_UNIT_REX.match(s) [ m[1], m[2] ] else [] end end
# File lib/flor/id.rb, line 108 def split_exid(s) return nil unless s.is_a?(String) _, d, u, t = s .match(/\A([^-\s]+)-([^-\s]+)-(\d{8,9}\.\d{4}\.[a-z]+)\z/) .to_a return nil unless d && u && t [ d, u, t ] end
ids
functions about exids, nids, sub_nids, …
# File lib/flor/id.rb, line 15 def split_fei(fei) if m = fei.match(/\A([^-]+-[^-]+-\d+\.\d+\.[^-]+)-(.*)\z/) [ m[1], m[2] ] else [ nil ] end end
# File lib/flor/flor.rb, line 359 def split_flow_name(s) if s.is_a?(String) && m = s.match(FLOW_NAME_REX) [ m[1], m[2] ] else nil end end
# File lib/flor/id.rb, line 29 def split_nid(nid) nid.split('-') end
# File lib/flor/log.rb, line 121 def src_to_s(src, launch_opts, opts={}) o = StringIO.new _c = colours(opts) o.puts "#{_c.dg}+---#{_c.rs}" if launch_opts.any? o.puts "#{_c.dg}| #{Flor.to_d(launch_opts, compact: true)}#{_c.rs}" o.puts "#{_c.dg}|#{_c.rs}" end lines = (src.is_a?(String) ? src : Flor.to_pretty_s(src)) .split("\n") min = lines .select { |l| l.strip.length > 0 } .collect { |l| l.match(/\A(\s*)/)[1].length } .min lines .each_with_index { |l, i| o.puts "#{_c.dg}|#{"%4d" % (i + 1)} #{_c.yl}#{l[min..-1]}#{_c.rs}" } o.puts "#{_c.dg}.#{_c.rs}" o.string end
# File lib/flor/flor.rb, line 306 def ststamp(t=Time.now) isostamp(true, true, false, t) end
# File lib/flor/flor.rb, line 386 def sub_domain?(dom, sub) d = dom.is_a?(Array) ? dot_join(*dom) : dom.to_s d == '' || sub == d || sub[0, d.length + 1] == d + '.' end
# File lib/flor/id.rb, line 44 def sub_nid(nid, subid=nil) if subid "#{nid.split('-').first}-#{subid}" else ss = nid.split('-') ss.length > 1 ? ss.last.to_i : 0 end end
# File lib/flor/flor.rb, line 316 def tamp(t=Time.now) t = t.utc s = StringIO.new s << t.strftime('%Y%m%dT%H%M%S') << sprintf('.%06dZ', t.usec) s.string end
# File lib/flor/flor.rb, line 27 def to_a(o) o.nil? ? nil : Array(o) end
# File lib/flor/unit/storage.rb, line 963 def to_blob(h); ::Flor::Storage.to_blob(h); end
# File lib/flor/flor.rb, line 756 def to_camel_case(s) s.sub(/\A[a-z]/) { |m| m.upcase }.gsub(/_[a-z]/) { |m| m[1, 1].upcase } end
# File lib/flor/flor.rb, line 177 def to_coll(o) #o.respond_to?(:to_a) ? o.to_a : [ a ] Array(o) end
# File lib/flor/log.rb, line 195 def to_compact_tree_s(tree, nid='0', opts={}) close = opts[:close] opts.merge!(close: false) o = StringIO.new _c = colours(opts) #is_root = opts[:s].nil? ind = ' ' * (opts[:ind] || 0) atts, natts = tree[1].is_a?(Array) ? tree[1].partition { |t| Flor.is_att_tree?(t) } : [ [], [] ] if t = opts.delete(:title) o << ind << _c.dg << '+--- ' << t << "\n" end o << ind << _c.dg << '| ' << nid << ' ' << _c.yl << Flor.to_d(tree[0], opts.merge(compact: true)) << _c.dg << ' L' << tree[2] atts.each_with_index do |ct, i| o << to_flat_tree_s(ct, "_#{i}", opts) end natts.each_with_index do |ct, i| i = atts.size + i o << "\n" << to_compact_tree_s(ct, "#{nid}_#{i}", opts) end o << "\n" << ind << _c.dg << '\---' if close o << _c.rs #opts[:out].puts(s.string) if is_root o.string end
# File lib/flor/djan.rb, line 10 def to_djan(x, opts={}) out = StringIO.new out.set_encoding('UTF-8') opts[:c] = Flor.colours(opts) if [ :console, true ].include?(opts[:width]) opts[:width] = IO.console.winsize[1] rescue 80 #elsif opts[:width].is_a?(Integer) # let it go elsif mw = (opts[:mw] || opts[:maxwidth] || opts[:max_width]) opts[:width] = [ (IO.console.winsize[1] rescue 80), mw ].min end opts[:indent] ||= 0 if opts[:width] opts[:str_escape] ||= [] Djan.to_d(x, out, opts) out.string end
to_d
, but without colours
# File lib/flor/djan.rb, line 37 def to_dnc(x) to_d(x, colours: false) end
# File lib/flor/flor.rb, line 121 def to_error(o) h = {} h['kla'] = o.class == String ? 'Flor::FlorError' : o.class.to_s m, t = if o.is_a?(::Exception) [ o.message, o.backtrace ] else [ o.to_s, caller[1..-1] ] end if n = o.respond_to?(:node) && o.node h['prc'] = n.tree[0] h['lin'] = n.tree[2] end h['msg'] = m h['trc'] = t[0..(t.rindex { |l| l.match(/\/lib\/flor\//) }) + 1] if t h['cwd'] = Dir.pwd h['rlp'] = $: if o.is_a?(::LoadError) h['details'] = o.details if o.respond_to?(:details) h['details'] = o.flor_details if o.respond_to?(:flor_details) h end
# File lib/flor/flor.rb, line 151 def to_error_message(message, error) #puts "---" #puts caller m = message.select { |k, v| TO_ERROR_MESSAGE_KEYS.include?(k) } m['point'] = 'failed' m['fpoint'] = message['point'] m['fm'] = message['m'] m['error'] = to_error(error) m end
# File lib/flor/log.rb, line 177 def to_flat_tree_s(tree, nid, opts) o = StringIO.new _c = colours(opts) o << ' ' << nid << ' ' << _c.yl << tree[0] << _c.dg if tree[1].is_a?(Array) tree[1].each_with_index do |t, i| o << to_flat_tree_s(t, "#{nid}_#{i}", opts) end else o << ' ' << tree[1] end o.string end
# File lib/flor/flor.rb, line 415 def to_pretty_s(o, twidth=79) sio = StringIO.new PP.pp(o, sio, twidth) sio.string end
# File lib/flor/flor.rb, line 239 def to_regex(o) s = if o.is_a?(String) o elsif o.is_a?(Array) if (o[0] == '_rxs' || o[0] == 'regex') && o[2].is_a?(Integer) o[1].to_s else "/#{o[0..-2].join}/#{o[-1]}" end else o.to_s end m = s.match(/\A\/(.*)\/([imxouesn]*)\z/) return Regexp.new(s) unless m m1 = m[1] e = (m[2].match(/[uesn]/) || [])[0] m1 = case e when 'u' then m1.encode('UTF-8') when 'e' then m1.encode('EUC-JP') when 's' then m1.encode('Windows-31J') when 'n' then m1.encode('ASCII-8BIT') else m1 end flags = 0 flags = flags | Regexp::EXTENDED if m[2].index('x') flags = flags | Regexp::IGNORECASE if m[2].index('i') #flags = flags | Regexp::MULTILINE if m[2].index('m') flags = flags | Regexp::FIXEDENCODING if e Regexp.new(m1, flags) end
used in procedure, cancel, until, cursor specs when “walking” and “stepping”
# File lib/flor/to_string.rb, line 8 def self.to_s(o=nil, k=nil) return 'Flor' if o == nil && k == nil # should it emerge somewhere... return o.collect { |e| Flor.to_s(e, k) }.join("\n") if o.is_a?(Array) if o.is_a?(Hash) return send("message_#{k}_to_s", o) if k && o['point'].is_a?(String) return message_to_s(o) if o['point'].is_a?(String) return send("node_#{k}_to_s", o) if k && o.has_key?('parent') return node_to_s(o) if o['parent'].is_a?(String) end return [ o, k ].inspect if k o.inspect end
# File lib/flor/flor.rb, line 744 def to_string_keyed_hash(o) case o when Array o.collect { |e| to_string_keyed_hash(e) } when Hash o.inject({}) { |h, (k, v)| h[k.to_s] = to_string_keyed_hash(v); h } else o end end
# File lib/flor/tt.rb, line 10 def to_tt(o, opts={}) h = o.is_a?(Hash) ? o : nil if h && h['status'].is_a?(Array) && h['nid'].is_a?(String) node_tt(h, opts) elsif h && h['point'].is_a?(String) && h['sm'].is_a?(Integer) message_tt(h, opts) elsif h djan_tt(h, opts) else pp_tt(o, opts) end end
Returns the subtree down at the given nid
# File lib/flor/flor.rb, line 584 def tree_locate(t, nid) st, i = parent_tree_locate(t, nid) return nil if st == nil return st if i == nil st[1][i] end
Given a tree returns the equivalent flor piece of code
# File lib/flor/flor.rb, line 599 def tree_to_flor(t, opts={}) o = opts[:o] ||= StringIO.new opts[:ind] ||= '' t_to_flor(t, opts) o.string end
# File lib/flor/flor.rb, line 718 def tree_to_pp_s(t, out=StringIO.new, indent='') out.print("#{indent}[ '#{t[0]}', ") if t[1] == [] out.print("[]") elsif t[1].is_a?(Array) out.print("[\n") t[1].each_with_index do |ct, i| tree_to_pp_s(ct, out, indent + ' ') if i < t[1].length - 1 out.print(",\n") else out.print("\n#{indent}") end end out.print("]") else out.print(t[1].inspect) end out.print(", #{t[2]}") out.print(", '#{t[3]}'") if t[3] out.print(" ]") indent == '' ? out.string : nil end
# File lib/flor/log.rb, line 149 def tree_to_s(tree, nid='0', opts={}) t0, t1, t2 = (tree || []) o = StringIO.new _c = colours(opts) ind = ' ' * (opts[:ind] || 0) headers = opts[:headers]; headers = true if headers.nil? headers = true if opts[:title] h = "#{_c.yl}#{Flor.to_d(t0, opts.merge(compact: true))}" c = t1.is_a?(Array) ? '' : " #{_c.yl}#{t1}" l = " #{_c.dg}L#{t2}" o.puts "#{ind}#{_c.dg}+--- #{opts[:title]}#{_c.rs}" \ if headers && nid == '0' o.puts "#{ind}#{_c.dg}| #{nid} #{h}#{c}#{l}#{_c.rs}" t1.each_with_index { |ct, i| o.puts tree_to_s(ct, Flor.child_nid(nid, i), opts) } \ if t1.is_a?(Array) o.puts "#{ind}#{_c.dg}.#{_c.rs}" \ if headers && nid == '0' o.string end
# File lib/flor/flor.rb, line 102 def true?(o) o != nil && o != false end
# File lib/flor/colours.rb, line 98 def self.truncate_string(s, maxlen, post='...') ncl = no_colour_length(s) r = StringIO.new l = 0 s.scan(/(\x1b\[\d+(?:;\d+)?m|[^\x1b]+)/) do |ss, _| if ss[0, 1] == "" r << ss else #p({ r: r.string, l: l, ssl: ss.length, maxlen: maxlen, reml: maxlen - l }) ss = ss[0, maxlen - l] r << ss l += ss.length break if l >= maxlen end end return r.string if l < maxlen if post.is_a?(String) r << post elsif post.is_a?(Proc) r << post.call(ncl, maxlen, s) end r.string end
Used by the storage in its next_time endeavours
# File lib/flor/flor.rb, line 284 def tstam Time.now.utc.strftime('%FT%T') end
# File lib/flor/flor.rb, line 301 def tstamp(t=Time.now) isostamp(true, true, true, t) end
# File lib/flor/tt.rb, line 25 def tt(o, opts={}) puts(to_tt(o, opts)) end
# File lib/flor/flor.rb, line 677 def type(o) case o when Array then :array when Hash then :object when String then :string when true, false then :boolean when Numeric then :number when nil then :null else nil end end
# File lib/flor/parser.rb, line 707 def self.unescape(s) sio = StringIO.new cs = s.each_char loop do c = cs.next break unless c if c == '\\' case cn = cs.next when 'u' then sio.print(unescape_u(cs)) when '\\', '"', '\'' then sio.print(cn) when 'b' then sio.print("\b") when 'f' then sio.print("\f") when 'n' then sio.print("\n") when 'r' then sio.print("\r") when 't' then sio.print("\t") else sio.print("\\#{cn}") end else sio.print(c) end end sio.string end
# File lib/flor/parser.rb, line 700 def self.unescape_u(cs) s = ''; 4.times { s << cs.next } [ s.to_i(16) ].pack('U*') end
# File lib/flor/flor.rb, line 410 def unit(s) split_domain_unit(s).last end
# File lib/flor/flor.rb, line 221 def v_to_a(o) return o if o.is_a?(Array) return o.split(',') if o.is_a?(String) return nil if o.nil? fail ArgumentError.new("cannot turn instance of #{o.class} into an array") end
# File lib/flor/flor.rb, line 107 def yes?(o) oo = o.respond_to?(:downcase) ? o.downcase : o [ 'y', 'yes', 'true', true ].include?(o) end
Protected Class Methods
# File lib/flor/flor.rb, line 647 def c_to_flor(t, opts) o = opts[:o] bs = (t[0] == '_arr') ? %w[ [ ] ] : %w[ { } ] o << bs[0] # opening atts, ctrees = t[1].partition { |ct| is_att_tree?(ct) } ctrees.each_with_index do |ct, i| o << ' ' t_to_flor(ct, opts) o << ':' if bs[0] == '{' && i.even? end o << (ctrees.any? ? ' ' : '') << bs[1] # closing end
def columns; ‘tput cols`.to_i rescue 80; end
# File lib/flor/tt.rb, line 33 def columns; IO.console.winsize[1] rescue 80; end
# File lib/flor/unit/dump.rb, line 25 def derive_unit(db_or_unit_or_uri) case o = db_or_unit_or_uri when Flor::Unit then o when Sequel::Database then Flor::Unit.new(sto_db: o) when String then Flor::Unit.new(sto_uri: o) else fail ArgumentError.new("cannot derive flor Unit out of #{o.inspect}") end end
# File lib/flor/tt.rb, line 84 def djan_tt(o, opts) make_tt_table(opts) { |t| t.add_row([ Flor.to_d(o) ]) }.to_s end
# File lib/flor/tt.rb, line 35 def make_tt_table(opts, &block) c = Flor.colours(opts) table = Terminal::Table.new table.style.border_x = opts[:border_x] || c.dg('-') table.style.border_i = opts[:border_i] || c.dg('.') table.style.border_y = opts[:border_y] || c.dg('|') block.call(table) if block table end
# File lib/flor/tt.rb, line 49 def message_tt(m, opts) cols = columns.to_f w = (cols * 0.49).to_i west = "** message **\n\n" + Flor.to_d(m.select { |k, _| k != 'cause' }, width: w) east = "cause:\n\n" + Flor.to_d(m['cause'], width: w) make_tt_table(opts) { |t| t.add_row([ west, east ]) }.to_s end
# File lib/flor/tt.rb, line 64 def node_tt(n, opts) cols = columns.to_f w = (cols * 0.49).to_i west = "** node **\n\n" + Flor.to_d(n.select { |k, _| k != 'status' && k != 'tree' }, width: w) east = "status:\n\n" + Flor.to_d(n['status'], width: w) make_tt_table(opts) { |t| t.add_row([ west, east ]) }.to_s end
# File lib/flor/tt.rb, line 89 def pp_s(o, opts) s = StringIO.new PP.pp(o, s) s.string end
# File lib/flor/tt.rb, line 79 def pp_tt(o, opts) make_tt_table(opts) { |t| t.add_row([ pp_s(o, opts) ]) }.to_s end
# File lib/flor/flor.rb, line 611 def t_to_flor(t, opts) o = opts[:o] i = opts[:ind] t1 = t[1] return o << '_' if t[0, 2] == [ '_', [] ] return c_to_flor(t, opts) if is_coll_tree?(t) return o << JSON.dump(t1) if is_leaf_tree?(t) return o << t1.collect { |a| a[1].to_s }.join('.') if is_ref_tree?(t) o << i << t[0] if t1.is_a?(Array) atts, ctrees = t1.partition { |ct| is_att_tree?(ct) } atts.each do |at| ats = at[1] o << ' ' if ats.length == 1 tree_to_flor(ats[0], opts) else o << ats[0].first << ': ' tree_to_flor(ats[1], opts) end end ctrees.each do |ct| o << "\n" tree_to_flor(ct, opts.merge(ind: ' ' + i)) end unless opts[:chop] end end