tickle 1.0.2 → 2.0.0rc3

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.
@@ -0,0 +1,115 @@
1
+ module Tickle
2
+
3
+ # A place to keep all the regular expressions.
4
+ module Patterns
5
+
6
+ PLURAL_OR_PRESENT_PARTICIPLE = /
7
+ s
8
+ |
9
+ ing
10
+ /x
11
+
12
+ ON_THE = /
13
+ \bon\b
14
+ (?:
15
+ \s+
16
+ the
17
+ )?
18
+ /x
19
+
20
+ END_OR_UNTIL = /
21
+ (?:
22
+ (?:\band\b\s+)?
23
+ \bend
24
+ (?: #{PLURAL_OR_PRESENT_PARTICIPLE} )?
25
+ (?:
26
+ \s+
27
+ #{ON_THE}
28
+ )?
29
+ )
30
+ |
31
+ (:?
32
+ until
33
+ (?:
34
+ \s+
35
+ \bthe\b
36
+ )?
37
+ )
38
+ /x
39
+
40
+ SET_IDENTIFIER = /
41
+ every
42
+ |
43
+ each
44
+ |
45
+ (?: #{ON_THE} )
46
+ /x
47
+
48
+ # This is here so we can check for repetition
49
+ # and set 'until' more easily. If so desired.
50
+ REPETITION = /
51
+ (?<repeat>
52
+ repeat
53
+ )
54
+ /x
55
+
56
+ START = /
57
+ start
58
+ (?: #{PLURAL_OR_PRESENT_PARTICIPLE} )?
59
+ /x
60
+
61
+ START_EVERY_REGEX = /^
62
+ (?:
63
+ #{START}
64
+ )
65
+ \s+
66
+ (?<start>.*?)
67
+ (?:
68
+ \s+
69
+ #{REPETITION}
70
+ )?
71
+ \s+
72
+ #{SET_IDENTIFIER}
73
+ \s+
74
+ (?<event>.*)
75
+ /ix
76
+
77
+
78
+ EVERY_START_REGEX = /^
79
+ (?: #{SET_IDENTIFIER} )
80
+ \s+
81
+ (?<event>.*)
82
+ (?:
83
+ \s+
84
+ #{START}
85
+ (?:
86
+ \s+
87
+ #{ON_THE}
88
+ )?
89
+ )
90
+ \s+
91
+ (?<start>.*)
92
+ /ix
93
+
94
+ START_ENDING_REGEX = /^
95
+ #{START}
96
+ \s+
97
+ (?<start>.*?)
98
+ (?:
99
+ \s+
100
+ #{END_OR_UNTIL}
101
+ )
102
+ \s+
103
+ (?<finish>.*)
104
+ /ix
105
+
106
+ PROCESS_FOR_ENDING = /^
107
+ (?<target>.*)
108
+ \s+
109
+ (?: #{END_OR_UNTIL})
110
+ \s+
111
+ (?<ending>.*)
112
+ /ix
113
+
114
+ end
115
+ end
@@ -1,136 +1,252 @@
1
- class Tickle::Repeater < Chronic::Tag #:nodoc:
2
- #
3
- def self.scan(tokens)
4
- # for each token
5
- tokens.each do |token|
6
- token = self.scan_for_numbers(token)
7
- token = self.scan_for_ordinal_names(token) unless token.type
8
- token = self.scan_for_ordinals(token) unless token.type
9
- token = self.scan_for_month_names(token) unless token.type
10
- token = self.scan_for_day_names(token) unless token.type
11
- token = self.scan_for_year_name(token) unless token.type
12
- token = self.scan_for_special_text(token) unless token.type
13
- token = self.scan_for_units(token) unless token.type
1
+ module Tickle
2
+ require_relative "../ext/string.rb"
3
+ class Repeater
4
+ require_relative "token.rb"
5
+
6
+ attr_reader :tokens
7
+
8
+ def initialize( tokens )
9
+ @tokens = tokens.map(&:clone)
14
10
  end
15
- tokens
16
- end
17
11
 
18
- def self.scan_for_numbers(token)
19
- regex = /\b(\d\d?)\b/
20
- token.update(:number, token.word.gsub(regex,'\1').to_i, token.word.gsub(regex,'\1').to_i) if token.word =~ regex
21
- token
22
- end
12
+
13
+ SCANNING_METHODS = [
14
+ :scan_for_numbers,
15
+ :scan_for_ordinal_names,
16
+ :scan_for_ordinals,
17
+ :scan_for_month_names,
18
+ :scan_for_day_names,
19
+ :scan_for_year_name,
20
+ :scan_for_special_text,
21
+ :scan_for_units,
22
+ ]
23
+
23
24
 
24
- def self.scan_for_ordinal_names(token)
25
- scanner = {/first/ => '1st',
26
- /second/ => '2nd',
27
- /third/ => '3rd',
28
- /fourth/ => '4th',
29
- /fifth/ => '5th',
30
- /sixth/ => '6th',
31
- /seventh/ => '7th',
32
- /eighth/ => '8th',
33
- /ninth/ => '9th',
34
- /tenth/ => '10th',
35
- /eleventh/ => '11th',
36
- /twelfth/ => '12th',
37
- /thirteenth/ => '13th',
38
- /fourteenth/ => '14th',
39
- /fifteenth/ => '15th',
40
- /sixteenth/ => '16th',
41
- /seventeenth/ => '17th',
42
- /eighteenth/ => '18th',
43
- /nineteenth/ => '19th',
44
- /twentieth/ => '20th',
45
- /thirtieth/ => '30th',
25
+ #
26
+ def scan!
27
+ # for each token
28
+ @tokens.each do |token|
29
+ new_details = catch(:token_found) {
30
+ SCANNING_METHODS.each{|meth|
31
+ send meth, token
32
+ }
33
+ nil # if nothing matched, set to nil
34
+ }
35
+ token.update! new_details if new_details
36
+ end
37
+ self
38
+ end
39
+
40
+
41
+ def detection(token, scanner, &block )
42
+ scanner = [scanner] unless scanner.respond_to? :keys
43
+ scanner.each do |key,value|
44
+ if (md = key.match token.downcase) or (md = key.match token.word)
45
+ throw :token_found, block.call(md,key,value)
46
+ end
47
+ end
48
+ nil # if it reaches here nothing was found so return nil
49
+ end
50
+
51
+
52
+ SCAN_FOR_NUMBERS = /
53
+ \b
54
+ (?<number>\d\d?)
55
+ \b
56
+ /x
57
+
58
+ def scan_for_numbers(token)
59
+ detection token, SCAN_FOR_NUMBERS do |md,key,value|
60
+ n = md[:number].to_i
61
+ {type: :number, start: n, interval: n }
62
+ end
63
+ end
64
+
65
+
66
+ SCAN_FOR_ORDINAL_NAMES = {
67
+ /first/ => Ordinal.new( '1st' ),
68
+ /second\b/ => Ordinal.new( '2nd' ),
69
+ /third/ => Ordinal.new( '3rd' ),
70
+ /fourth/ => Ordinal.new( '4th' ),
71
+ /fifth/ => Ordinal.new( '5th' ),
72
+ /sixth/ => Ordinal.new( '6th' ),
73
+ /seventh/ => Ordinal.new( '7th' ),
74
+ /eighth/ => Ordinal.new( '8th' ),
75
+ /ninth/ => Ordinal.new( '9th' ),
76
+ /tenth/ => Ordinal.new( '10th' ),
77
+ /eleventh/ => Ordinal.new( '11th' ),
78
+ /twelfth/ => Ordinal.new( '12th' ),
79
+ /thirteenth/ => Ordinal.new( '13th' ),
80
+ /fourteenth/ => Ordinal.new( '14th' ),
81
+ /fifteenth/ => Ordinal.new( '15th' ),
82
+ /sixteenth/ => Ordinal.new( '16th' ),
83
+ /seventeenth/ => Ordinal.new( '17th' ),
84
+ /eighteenth/ => Ordinal.new( '18th' ),
85
+ /nineteenth/ => Ordinal.new( '19th' ),
86
+ /twentieth/ => Ordinal.new( '20th' ),
87
+ /thirtieth/ => Ordinal.new( '30th' ),
46
88
  }
47
- scanner.keys.each do |scanner_item|
48
- if scanner_item =~ token.original
49
- token.word = scanner[scanner_item]
50
- token.update(:ordinal, scanner[scanner_item].ordinal_as_number, Tickle.days_in_month(Tickle.get_next_month(scanner[scanner_item].ordinal_as_number)))
89
+
90
+
91
+ def scan_for_ordinal_names(token)
92
+ detection token, SCAN_FOR_ORDINAL_NAMES do |md,key,value|
93
+ { :type => :ordinal,
94
+ :start => value.ordinal_as_number,
95
+ :interval => Tickle::Helpers.days_in_month( Tickle::Helpers.get_next_month( value.ordinal_as_number )),
96
+ }
51
97
  end
52
98
  end
53
- token
54
- end
55
99
 
56
- def self.scan_for_ordinals(token)
57
- regex = /\b(\d*)(st|nd|rd|th)\b/
58
- if token.original =~ regex
59
- token.word = token.original
60
- token.update(:ordinal, token.word.ordinal_as_number, Tickle.days_in_month(Tickle.get_next_month(token.word)))
100
+
101
+ SCAN_FOR_ORDINALS = /
102
+ \b
103
+ (?<number>\d+)
104
+ (?:
105
+ st
106
+ |
107
+ nd
108
+ |
109
+ rd
110
+ |th
111
+ )
112
+ \b
113
+ /x
114
+
115
+ def scan_for_ordinals(token)
116
+ detection token, SCAN_FOR_ORDINALS do |md,key,value|
117
+ number = Ordinal.new(md[:number])
118
+ { :type => :ordinal,
119
+ :start => number.ordinal_as_number,
120
+ :interval => Tickle::Helpers.days_in_month(Tickle::Helpers.get_next_month number )
121
+ }
122
+ end
61
123
  end
62
- token
63
- end
64
124
 
65
- def self.scan_for_month_names(token)
66
- scanner = {/^jan\.?(uary)?$/ => 1,
67
- /^feb\.?(ruary)?$/ => 2,
68
- /^mar\.?(ch)?$/ => 3,
69
- /^apr\.?(il)?$/ => 4,
70
- /^may$/ => 5,
71
- /^jun\.?e?$/ => 6,
72
- /^jul\.?y?$/ => 7,
73
- /^aug\.?(ust)?$/ => 8,
74
- /^sep\.?(t\.?|tember)?$/ => 9,
75
- /^oct\.?(ober)?$/ => 10,
76
- /^nov\.?(ember)?$/ => 11,
77
- /^dec\.?(ember)?$/ => 12}
78
- scanner.keys.each do |scanner_item|
79
- token.update(:month_name, scanner[scanner_item], 30) if scanner_item =~ token.word
125
+
126
+ def scan_for_month_names(token)
127
+ scanner = {/^jan\.?(uary)?$/ => 1,
128
+ /^feb\.?(ruary)?$/ => 2,
129
+ /^mar\.?(ch)?$/ => 3,
130
+ /^apr\.?(il)?$/ => 4,
131
+ /^may$/ => 5,
132
+ /^jun\.?e?$/ => 6,
133
+ /^jul\.?y?$/ => 7,
134
+ /^aug\.?(ust)?$/ => 8,
135
+ /^sep\.?(t\.?|tember)?$/ => 9,
136
+ /^oct\.?(ober)?$/ => 10,
137
+ /^nov\.?(ember)?$/ => 11,
138
+ /^dec\.?(ember)?$/ => 12}
139
+ detection token, scanner do |md,key,value|
140
+ {
141
+ :type => :month_name,
142
+ :start => value,
143
+ :interval => 30,
144
+ }
145
+ end
80
146
  end
81
- token
82
- end
83
147
 
84
- def self.scan_for_day_names(token)
85
- scanner = {/^m[ou]n(day)?$/ => :monday,
86
- /^t(ue|eu|oo|u|)s(day)?$/ => :tuesday,
87
- /^tue$/ => :tuesday,
88
- /^we(dnes|nds|nns)day$/ => :wednesday,
89
- /^wed$/ => :wednesday,
90
- /^th(urs|ers)day$/ => :thursday,
91
- /^thu$/ => :thursday,
92
- /^fr[iy](day)?$/ => :friday,
93
- /^sat(t?[ue]rday)?$/ => :saturday,
94
- /^su[nm](day)?$/ => :sunday}
95
- scanner.keys.each do |scanner_item|
96
- token.update(:weekday, scanner[scanner_item], 7) if scanner_item =~ token.word
148
+
149
+ def scan_for_day_names(token)
150
+ scanner = {
151
+ /^m[ou]n(day)?$/ => :monday,
152
+ /^t(ue|eu|oo|u|)s(day)?$/ => :tuesday,
153
+ /^tue$/ => :tuesday,
154
+ /^we(dnes|nds|nns)day$/ => :wednesday,
155
+ /^wed$/ => :wednesday,
156
+ /^th(urs|ers)day$/ => :thursday,
157
+ /^thu$/ => :thursday,
158
+ /^fr[iy](day)?$/ => :friday,
159
+ /^sat(t?[ue]rday)?$/ => :saturday,
160
+ /^su[nm](day)?$/ => :sunday
161
+ }
162
+ detection token, scanner do |md,key,value|
163
+ {
164
+ :type => :weekday,
165
+ :start => value,
166
+ :interval => 7,
167
+ }
168
+ end
97
169
  end
98
- token
99
- end
100
170
 
101
- def self.scan_for_year_name(token)
102
- regex = /\b\d{4}\b/
103
- token.update(:specific_year, token.original.gsub(regex,'\1'), 365) if token.original =~ regex
104
- token
105
- end
106
171
 
107
- def self.scan_for_special_text(token)
108
- scanner = {/^other$/ => :other,
109
- /^begin(ing|ning)?$/ => :beginning,
110
- /^start$/ => :beginning,
111
- /^end$/ => :end,
112
- /^mid(d)?le$/ => :middle}
113
- scanner.keys.each do |scanner_item|
114
- token.update(:special, scanner[scanner_item], 7) if scanner_item =~ token.word
172
+ def scan_for_year_name(token)
173
+ detection token, /\b(?<year>\d{4})\b/ do |md,key,value|
174
+ {
175
+ :type => :specific_year,
176
+ :start => md[:year],
177
+ :interval => 365,
178
+ }
179
+ end
115
180
  end
116
- token
117
- end
118
181
 
119
- def self.scan_for_units(token)
120
- scanner = {/^year(ly)?s?$/ => {:type => :year, :interval => 365, :start => :today},
121
- /^month(ly)?s?$/ => {:type => :month, :interval => 30, :start => :today},
122
- /^fortnights?$/ => {:type => :fortnight, :interval => 365, :start => :today},
123
- /^week(ly)?s?$/ => {:type => :week, :interval => 7, :start => :today},
124
- /^weekends?$/ => {:type => :weekend, :interval => 7, :start => :saturday},
125
- /^days?$/ => {:type => :day, :interval => 0, :start => :today},
126
- /^daily?$/ => {:type => :day, :interval => 0, :start => :today}}
127
- scanner.keys.each do |scanner_item|
128
- if scanner_item =~ token.word
129
- token.update(scanner[scanner_item][:type], scanner[scanner_item][:start], scanner[scanner_item][:interval]) if scanner_item =~ token.word
182
+
183
+ def scan_for_special_text(token)
184
+ scanner = {
185
+ /^other$/ => :other,
186
+ /^begin(ing|ning)?$/ => :beginning,
187
+ /^start$/ => :beginning,
188
+ /^end$/ => :end,
189
+ /^mid(d)?le$/ => :middle
190
+ }
191
+ detection token, scanner do |md,key,value|
192
+ {
193
+ :type => :special,
194
+ :start => value,
195
+ :interval => 7,
196
+ }
130
197
  end
131
198
  end
132
- token
133
- end
134
199
 
135
200
 
136
- end
201
+ def scan_for_units(token)
202
+ scanner = {
203
+ /^year(?:ly)?s?$/ => {
204
+ :type => :year,
205
+ :interval => 365,
206
+ :start => :today
207
+ },
208
+ /^month(?:ly|s)?$/ => {
209
+ :type => :month,
210
+ :interval => 30,
211
+ :start => :today
212
+ },
213
+ /^fortnights?$/ => {
214
+ :type => :fortnight,
215
+ :interval => 14,
216
+ :start => :today
217
+ },
218
+ /^week(?:ly|s)?$/ => {
219
+ :type => :week,
220
+ :interval => 7,
221
+ :start => :today
222
+ },
223
+ /^weekends?$/ => {
224
+ :type => :weekend,
225
+ :interval => 7,
226
+ :start => :saturday
227
+ },
228
+ /^days?$/ => {
229
+ :type => :day,
230
+ :interval => 1,
231
+ :start => :today
232
+ },
233
+ /^daily$/ => {
234
+ :type => :day,
235
+ :interval => 1,
236
+ :start => :today
237
+ },
238
+ /^sec(?:onds)?$/ => {
239
+ :type => :sec,
240
+ :interval => 1,
241
+ :start => :today
242
+ },
243
+ }
244
+
245
+ detection token, scanner do |md,key,value|
246
+ value
247
+ end
248
+ end
249
+
250
+
251
+ end
252
+ end