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