lib/fugit/nat.rb in fugit-1.3.4 vs lib/fugit/nat.rb in fugit-1.3.5

- old
+ new

@@ -13,10 +13,11 @@ return s if s.is_a?(Fugit::Cron) || s.is_a?(Fugit::Duration) return nil unless s.is_a?(String) #p s; Raabro.pp(Parser.parse(s, debug: 3), colours: true) +#(p s; Raabro.pp(Parser.parse(s, debug: 1), colours: true)) rescue nil a = Parser.parse(s) return nil unless a return parse_crons(s, a, opts) \ @@ -35,24 +36,20 @@ protected def parse_crons(s, a, opts) - dhs, aa = a - .partition { |e| e[0] == :digital_hour } - ms = dhs - .inject({}) { |h, dh| (h[dh[1][0]] ||= []) << dh[1][1]; h } + hms, aa = a + .partition { |e| e[0] == :point && e[1][0] == :hour } + ms = hms + .inject({}) { |h, e| (h[e[1][1]] ||= []) << e[1][2]; h } .values .uniq - crons = - #if ms.size <= 1 || hs.size <= 1 - if ms.size <= 1 - [ parse_cron(a, opts) ] - else - dhs.collect { |dh| parse_cron([ dh ] + aa, opts) } - end + ms.size > 1 ? + hms.collect { |e| parse_cron([ e ] + aa, opts) } : + [ parse_cron(a, opts) ] fail ArgumentError.new( "multiple crons in #{s.inspect} " + "(#{crons.collect(&:original).join(' | ')})" ) if opts[:multi] == :fail && crons.size > 1 @@ -64,38 +61,40 @@ end end def parse_cron(a, opts) - h = { min: nil, hou: [], dom: nil, mon: nil, dow: nil } + h = { min: nil, hou: nil, dom: nil, mon: nil, dow: nil } hkeys = h.keys + i0s, es = a.partition { |e| e[0] == :interval0 } + a = es + i0s + # interval0s are fallback + a.each do |key, val| - if key == :biz_day + case key + when :biz_day (h[:dow] ||= []) << '1-5' - elsif key == :simple_hour || key == :numeral_hour - h[:hou] << val - elsif key == :digital_hour - (h[:hou] ||= []) << val[0].to_i - (h[:min] ||= []) << val[1].to_i - elsif key == :name_day + when :name_day (h[:dow] ||= []) << val - elsif key == :day_range + when :day_range (h[:dow] ||= []) << val.collect { |v| v.to_s[0, 3] }.join('-') - elsif key == :tz + when :tz h[:tz] = val - elsif key == :duration - process_duration(h, *val[0].to_h.first) + when :point + process_point(h, *val) + when :interval1 + process_interval1(h, *val[0].to_h.first) + when :interval0 + process_interval0(h, val) end end - h[:min] ||= [ 0 ] - h[:min].uniq! + return nil if h[:fail] - h[:hou].uniq!; - h[:hou].sort! - + h[:min] = (h[:min] || [ 0 ]).uniq + h[:hou] = (h[:hou] || []).uniq.sort h[:dow].sort! if h[:dow] a = hkeys .collect { |k| v = h[k] @@ -106,45 +105,97 @@ s = a.join(' ') Fugit::Cron.parse(s) end - def process_duration(h, interval, value) + def process_point(h, key, *value) - send("process_duration_#{interval}", h, value) + case key + when :hour + v0, v1 = value + v0 = v0.to_i if v0.is_a?(String) && v0.match(/^\d+$/) + (h[:hou] ||= []) << v0 + (h[:min] ||= []) << v1.to_i if v1 + when :sec, :min + (h[key] ||= []) << value[0] + end end - def process_duration_mon(h, value) + def process_interval0(h, value) - h[:hou] = [ 0 ] - h[:dom] = [ 1 ] - h[:mon] = [ value == 1 ? '*' : "*/#{value}" ] + case value + when 'sec', 'second' + h[:min] = [ '*' ] + h[:sec] = [ '*' ] + when 'min', 'minute' + h[:min] = [ '*' ] + when 'hour' + unless h[:min] || h[:hou] + h[:min] = [ 0 ] + h[:hou] = [ '*' ] + end + when 'day' + unless h[:min] || h[:hou] + h[:min] = [ 0 ] + h[:hou] = [ 0 ] + end + when 'week' + unless h[:min] || h[:hou] || h[:dow] + h[:min] = [ 0 ] + h[:hou] = [ 0 ] + h[:dow] = [ 0 ] + end + when 'month' + unless h[:min] || h[:hou] + h[:min] = [ 0 ] + h[:hou] = [ 0 ] + end + (h[:dom] ||= []) << 1 + when 'year' + unless h[:min] || h[:hou] + h[:min] = [ 0 ] + h[:hou] = [ 0 ] + end + (h[:dom] ||= []) << 1 + (h[:mon] ||= []) << 1 + end end - def process_duration_day(h, value) + def process_interval1(h, interval, value) - h[:hou] = [ 0 ] - h[:dom] = [ value == 1 ? '*' : "*/#{value}" ] - end + if value != 1 && [ :yea, :wee ].include?(interval) + int = interval == :year ? 'years' : 'weeks' + h[:fail] = "cannot cron for \"every #{value} #{int}\"" + return + end - def process_duration_hou(h, value) - - h[:hou] = [ value == 1 ? '*' : "*/#{value}" ] + case interval + when :yea + h[:hou] = [ 0 ] + h[:mon] = [ 1 ] + h[:dom] = [ 1 ] + when :mon + h[:hou] = [ 0 ] + h[:dom] = [ 1 ] + h[:mon] = [ value == 1 ? '*' : "*/#{value}" ] + when :wee + h[:hou] = [ 0 ] + h[:dow] = [ 0 ] # Sunday + when :day + h[:hou] = [ 0 ] + h[:dom] = [ value == 1 ? '*' : "*/#{value}" ] + when :hou + h[:hou] = [ value == 1 ? '*' : "*/#{value}" ] + when :min + h[:hou] = [ '*' ] + h[:min] = [ value == 1 ? '*' : "*/#{value}" ] + when :sec + h[:hou] = [ '*' ] + h[:min] = [ '*' ] + h[:sec] = [ value == 1 ? '*' : "*/#{value}" ] + end end - - def process_duration_min(h, value) - - h[:hou] = [ '*' ] - h[:min] = [ value == 1 ? '*' : "*/#{value}" ] - end - - def process_duration_sec(h, value) - - h[:hou] = [ '*' ] - h[:min] = [ '*' ] - h[:sec] = [ value == 1 ? '*' : "*/#{value}" ] - end end module Parser include Raabro NUMS = %w[ @@ -158,10 +209,15 @@ NHOURS = { 'noon' => [ 12, 0 ], 'midnight' => [ 0, 0 ] } # piece parsers bottom to top + def interval0(i) + rex(:interval0, i, + /(year|month|week|day|hour|min(ute)?|sec(ond)?)(?![a-z])/i) + end + def am_pm(i) rex(:am_pm, i, / *(am|pm)/i) end def digital_hour(i) @@ -184,11 +240,10 @@ def name_hour(i) rex(:name_hour, i, /(#{NHOURS.keys.join('|')})/i) end - def plain_day(i); rex(:plain_day, i, /day/i); end def biz_day(i); rex(:biz_day, i, /(biz|business|week) *day/i); end def name_day(i); rex(:name_day, i, /#{WEEKDAYS.reverse.join('|')}/i); end def range_sep(i); rex(nil, i, / *- *| +(to|through) +/); end @@ -202,70 +257,104 @@ def _tz_delta(i) rex(nil, i, /[-+]([01][0-9]|2[0-4]):?(00|15|30|45)/) end def _tz(i); alt(:tz, i, :_tz_delta, :_tz_name); end - def duration(i) - rex( - :duration, i, + def interval1(i) + rex(:interval1, i, / \d+ \s? - (mon(ths?)?|d(ays?)?|h(ours?)?|m(in(ute)?s?)?|s(ec(ond)?s?)?) + (y(ears?)?|months?|w(eeks?)?|d(ays?)?| + h(ours?)?|m(in(ute)?s?)?|s(ec(ond)?s?)?) /ix) end + def min_or_sec(i) + rex(:min_or_sec, i, /(min(ute)?|sec(ond)?)\s+\d+/i) + end + + def point(i) + alt(:point, i, + :min_or_sec, + :name_hour, :numeral_hour, :digital_hour, :simple_hour) + end + def flag(i); rex(:flag, i, /(every|from|at|after|on|in)/i); end def datum(i) alt(nil, i, - :day_range, - :plain_day, :biz_day, :name_day, - :_tz, :flag, - :duration, - :name_hour, :numeral_hour, :digital_hour, :simple_hour) + :interval1, + :point, + :interval0, + :day_range, :biz_day, :name_day, + :_tz) end def sugar(i); rex(nil, i, /(and|or|[, \t]+)/i); end def elt(i); alt(nil, i, :sugar, :datum); end def nat(i); rep(:nat, i, :elt, 1); end # rewrite parsed tree - def rewrite_nat(t) + def _rewrite(t) + [ t.name, t.string.downcase ] + end + alias rewrite_flag _rewrite + alias rewrite_interval0 _rewrite + alias rewrite_biz_day _rewrite -#Raabro.pp(t, colours: true) - t - .subgather(nil) - .collect { |tt| + def rewrite_name_day(t) + [ :name_day, WEEKDAYS.index(t.string.downcase[0, 3]) ] + end - k = tt.name - v = tt.string.downcase + def rewrite_day_range(t) + [ :day_range, t.subgather(nil).collect { |st| st.string.downcase } ] + end - case k - when :tz - [ k, [ tt.string.strip, EtOrbi.get_tzone(tt.string.strip) ] ] - when :duration - [ k, [ Fugit::Duration.parse(tt.string.strip) ] ] - when :digital_hour - v = v.gsub(/:/, '') - [ k, [ v[0, 2], v[2, 2] ] ] - when :name_hour - [ :digital_hour, NHOURS[v] ] - when :name_day - [ k, WEEKDAYS.index(v[0, 3]) ] - when :day_range - [ k, tt.subgather(nil).collect { |st| st.string.downcase } ] - when :numeral_hour, :simple_hour - vs = tt.subgather(nil).collect { |ttt| ttt.string.downcase.strip } - v = k == :simple_hour ? vs[0].to_i : NUMS.index(vs[0]) - v += 12 if vs[1] == 'pm' - [ k, v ] - else - [ k, v ] - end } + def rewrite_name_hour(t) + [ :hour, *NHOURS[t.string.strip.downcase] ] + end + def rewrite_numeral_hour(t) + vs = t.subgather(nil).collect { |st| st.string.downcase.strip } + v = NUMS.index(vs[0]) + v += 12 if vs[1] == 'pm' + [ :hour, v, 0 ] + end + def rewrite_simple_hour(t) + vs = t.subgather(nil).collect { |st| st.string.downcase.strip } + v = vs[0].to_i + v += 12 if vs[1] == 'pm' + [ :hour, v, 0 ] + end + def rewrite_digital_hour(t) + v = t.string.gsub(/:/, '') + [ :hour, v[0, 2], v[2, 2] ] + end + + def rewrite_min_or_sec(t) + unit, num = t.string.split(/\s+/) + [ unit[0, 3].to_sym, num.to_i ] + end + + def rewrite_point(t) + [ :point, rewrite(t.sublookup) ] + end + + def rewrite_tz(t) + [ :tz, [ t.string.strip, EtOrbi.get_tzone(t.string.strip) ] ] + end + + def rewrite_interval1(t) + [ t.name, [ Fugit::Duration.parse(t.string.strip) ] ] + end + + def rewrite_nat(t) + +#Raabro.pp(t, colours: true) + t.subgather(nil).collect { |tt| rewrite(tt) } end end end end