icalPal 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/icalPal +12 -0
- data/lib/defaults.rb +1 -0
- data/lib/event.rb +85 -63
- data/lib/icalPal.rb +2 -2
- data/lib/options.rb +4 -1
- data/lib/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76513daaf66f3c4aa8b2a9e1703f275ba5d5a65ef9e8b71a86b263c59d409fdd
|
4
|
+
data.tar.gz: c06430cfbdd5c415dae2d154b774c1ba1feb210534e6511f9fbb1cf12052cbfd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 290f75e744ea88673f474c478565ec281a2b8eae8dcfc730ccb7abf88f33b5fdc8c10baf53b971c336d48a3a4abc3f311e02973e9f2295fea2d134e3d987a499
|
7
|
+
data.tar.gz: af3d7eec48d408f2c7ff15af7cdddcf581fa60574e1ab3602efb32e6625bfa61833919194108fe012fbae35a312c14af6ffbf628be4921d7cd11651e67717151
|
data/bin/icalPal
CHANGED
@@ -130,6 +130,18 @@ $rows.each_with_index do |row, i|
|
|
130
130
|
next
|
131
131
|
end
|
132
132
|
|
133
|
+
# --regexp
|
134
|
+
if $opts[:match]
|
135
|
+
r = $opts[:match].split('=')
|
136
|
+
|
137
|
+
if item[r[0]].to_s.respond_to?(:match)
|
138
|
+
unless item[r[0]].to_s.match(Regexp.new(r[1].to_s, Regexp::IGNORECASE)) then
|
139
|
+
$log.debug(":regex")
|
140
|
+
next
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
133
145
|
if ICalPal::Event === item
|
134
146
|
# Check for all-day and cancelled events
|
135
147
|
if $opts[:ea] && item['all_day'].positive? then
|
data/lib/defaults.rb
CHANGED
data/lib/event.rb
CHANGED
@@ -110,20 +110,22 @@ module ICalPal
|
|
110
110
|
# If an event spans multiple days, the return value will contain
|
111
111
|
# a unique {Event} for each day that falls within our window
|
112
112
|
def non_recurring
|
113
|
-
|
113
|
+
events = []
|
114
114
|
|
115
115
|
# Repeat for multi-day events
|
116
116
|
((self['duration'] / 86400).to_i + 1).times do |i|
|
117
117
|
break if self['sdate'] > $opts[:to]
|
118
118
|
|
119
119
|
$log.debug("multi-day event #{i + 1}") if (i > 0)
|
120
|
+
|
120
121
|
self['daynum'] = i + 1
|
121
|
-
|
122
|
+
events.push(clone) if in_window?(self['sdate'])
|
123
|
+
|
122
124
|
self['sdate'] += 1
|
123
125
|
self['edate'] += 1
|
124
126
|
end
|
125
127
|
|
126
|
-
|
128
|
+
events
|
127
129
|
end
|
128
130
|
|
129
131
|
# Check recurring events
|
@@ -131,35 +133,49 @@ module ICalPal
|
|
131
133
|
# @return [Array<Event>]
|
132
134
|
# All occurrences of a recurring event that are within our window
|
133
135
|
def recurring
|
134
|
-
|
136
|
+
stop = [ $opts[:to], (self['rdate'] || $opts[:to]) ].min
|
135
137
|
|
136
138
|
# See if event ends before we start
|
137
|
-
stop = [ $opts[:to], (self['rdate'] || $opts[:to]) ].min
|
138
139
|
if stop < $opts[:from] then
|
139
140
|
$log.debug("#{stop} < #{$opts[:from]}")
|
140
|
-
return(
|
141
|
+
return(Array.new)
|
141
142
|
end
|
142
143
|
|
143
144
|
# Get changes to series
|
144
|
-
changes =
|
145
|
+
changes = [ { 'orig_date' => -1 } ]
|
146
|
+
changes += $rows.select { |r| r['orig_item_id'] == self['ROWID'] }
|
147
|
+
|
148
|
+
events = []
|
149
|
+
count = 1
|
145
150
|
|
146
|
-
i = 1
|
147
151
|
while self['sdate'] <= stop
|
148
|
-
|
149
|
-
|
150
|
-
|
152
|
+
# count
|
153
|
+
break if self['count'].positive? and count > self['count']
|
154
|
+
count += 1
|
155
|
+
|
156
|
+
# Handle specifier or clone self
|
157
|
+
if self['specifier'] and self['specifier'].length.positive?
|
158
|
+
occurrences = get_occurrences(changes)
|
159
|
+
else
|
160
|
+
occurrences = [ clone ]
|
151
161
|
end
|
152
|
-
i += 1
|
153
162
|
|
154
|
-
|
155
|
-
|
156
|
-
|
163
|
+
# Check for changes
|
164
|
+
occurrences.each do |occurrence|
|
165
|
+
changes.each do |change|
|
166
|
+
next if change['orig_date'] == self['sdate'].to_i - ITIME
|
167
|
+
events.push(occurrence) if in_window?(occurrence['sdate'], occurrence['edate'])
|
168
|
+
end
|
157
169
|
end
|
158
170
|
|
171
|
+
break if self['specifier']
|
159
172
|
apply_frequency!
|
160
173
|
end
|
161
174
|
|
162
|
-
|
175
|
+
# Remove exceptions
|
176
|
+
events.delete_if { |event| event['xdate'].any?(event['sdate']) }
|
177
|
+
|
178
|
+
return(events)
|
163
179
|
end
|
164
180
|
|
165
181
|
private
|
@@ -168,67 +184,72 @@ module ICalPal
|
|
168
184
|
|
169
185
|
# @return a deep clone of self
|
170
186
|
def clone()
|
171
|
-
self['stime'] = @self['sdate'].to_i
|
172
|
-
self['etime'] = @self['edate'].to_i
|
173
|
-
|
174
187
|
Marshal.load(Marshal.dump(self))
|
175
188
|
end
|
176
189
|
|
177
|
-
# Get next occurences of a recurring event
|
190
|
+
# Get next occurences of a recurring event from a specifier
|
178
191
|
#
|
179
192
|
# @param changes [Array] Recurrence changes for the event
|
180
193
|
# @return [Array<IcalPal::Event>]
|
181
194
|
def get_occurrences(changes)
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
195
|
+
occurrences = []
|
196
|
+
|
197
|
+
dow = DOW.keys
|
198
|
+
dom = [ nil ]
|
199
|
+
moy = 1..12
|
200
|
+
nth = nil
|
201
|
+
|
202
|
+
specifier = self['specifier']? self['specifier'] : []
|
203
|
+
|
204
|
+
# Deconstruct specifier
|
205
|
+
specifier.split(';').each do |k|
|
206
|
+
j = k.split('=')
|
207
|
+
|
208
|
+
# D=Day of the week, M=Day of the month, O=Month of the year, S=Nth
|
209
|
+
case j[0]
|
210
|
+
when 'D' then dow = j[1].split(',')
|
211
|
+
when 'M' then dom = j[1].split(',')
|
212
|
+
when 'O' then moy = j[1].split(',')
|
213
|
+
when 'S' then nth = j[1].to_i
|
214
|
+
else $log.warn("Unknown specifier: #{k}")
|
200
215
|
end
|
216
|
+
end
|
201
217
|
|
202
|
-
|
203
|
-
|
204
|
-
|
218
|
+
# Build array of DOWs
|
219
|
+
dows = [ nil ]
|
220
|
+
dow.each { |d| dows.push(DOW[d[-2..-1].to_sym]) }
|
205
221
|
|
206
|
-
|
207
|
-
|
208
|
-
|
222
|
+
# Months of the year (O)
|
223
|
+
moy.each do |m|
|
224
|
+
next unless m
|
209
225
|
|
210
|
-
|
211
|
-
|
212
|
-
dow = DOW[n[-2..-1].to_sym]
|
213
|
-
ndate += 1 until ndate.wday == dow
|
214
|
-
ndate = ICalPal.nth(Integer(n[0..1]), n[-2..-1], ndate) unless (n[0] == '0')
|
226
|
+
nsdate = RDT.new(self['sdate'].year, m.to_i, 1)
|
227
|
+
nedate = RDT.new(self['edate'].year, m.to_i, 1)
|
215
228
|
|
216
|
-
#
|
217
|
-
|
218
|
-
|
219
|
-
self['sdate'] = RDT.new(*ndate.to_a[0..2], *self['sdate'].to_a[3..])
|
220
|
-
self['edate'] = RDT.new(*ndate.to_a[0..2], *self['edate'].to_a[3..])
|
221
|
-
retval.push(clone)
|
222
|
-
}) { |i| @self['sday'] == i['sday'] }
|
223
|
-
end
|
229
|
+
# Days of the month (M)
|
230
|
+
dom.each do |x|
|
231
|
+
next unless x
|
224
232
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
233
|
+
self['sdate'] = RDT.new(nsdate.year, nsdate.month, x.to_i)
|
234
|
+
self['edate'] = RDT.new(nedate.year, nedate.month, x.to_i)
|
235
|
+
occurrences.push(clone)
|
236
|
+
end
|
237
|
+
|
238
|
+
# Days of the week (D)
|
239
|
+
if nth
|
240
|
+
self['sdate'] = ICalPal.nth(nth, dows, nsdate)
|
241
|
+
self['edate'] = ICalPal.nth(nth, dows, nedate)
|
242
|
+
occurrences.push(clone)
|
243
|
+
else
|
244
|
+
if dows[0]
|
245
|
+
self['sdate'] = RDT.new(nsdate.year, m.to_i, nsdate.wday)
|
246
|
+
self['edate'] = RDT.new(nedate.year, m.to_i, nedate.wday)
|
247
|
+
occurrences.push(clone)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
230
251
|
|
231
|
-
|
252
|
+
return(occurrences)
|
232
253
|
end
|
233
254
|
|
234
255
|
# Apply frequency and interval
|
@@ -243,6 +264,7 @@ module ICalPal
|
|
243
264
|
when 'weekly' then self[d] += self['interval'] * 7
|
244
265
|
when 'monthly' then self[d] >>= self['interval']
|
245
266
|
when 'yearly' then self[d] >>= self['interval'] * 12
|
267
|
+
else $log.error("Unknown frequency: #{self['frequency']}")
|
246
268
|
end
|
247
269
|
end if self['frequency'] && self['interval']
|
248
270
|
end
|
data/lib/icalPal.rb
CHANGED
@@ -141,7 +141,7 @@ module ICalPal
|
|
141
141
|
# Get the +n+'th +dow+ in month +m+
|
142
142
|
#
|
143
143
|
# @param n [Integer] Integer between -4 and +4
|
144
|
-
# @param dow [
|
144
|
+
# @param dow [Array] Days of the week
|
145
145
|
# @param m [RDT] The RDT with the year and month we're searching
|
146
146
|
# @return [RDT] The resulting day
|
147
147
|
def self.nth(n, dow, m)
|
@@ -155,7 +155,7 @@ module ICalPal
|
|
155
155
|
|
156
156
|
j = 0
|
157
157
|
a[0].step(a[1], step) do |i|
|
158
|
-
j += step if i.wday
|
158
|
+
j += step if dow.any?(i.wday)
|
159
159
|
return i if j == n
|
160
160
|
end
|
161
161
|
end
|
data/lib/options.rb
CHANGED
@@ -55,7 +55,7 @@ module ICalPal
|
|
55
55
|
"Print as FORMAT (default: #{$defaults[:common][:output]})", "[#{OUTFORMATS.join(', ')}]")
|
56
56
|
|
57
57
|
# include/exclude
|
58
|
-
@op.separator("\nIncluding/excluding calendars:\n\n")
|
58
|
+
@op.separator("\nIncluding/excluding accounts, calendars, items:\n\n")
|
59
59
|
|
60
60
|
@op.on('--is=ACCOUNTS', Array, 'List of accounts to include')
|
61
61
|
@op.on('--es=ACCOUNTS', Array, 'List of accounts to exclude')
|
@@ -73,6 +73,9 @@ module ICalPal
|
|
73
73
|
@op.on('--il=LISTS', Array, 'List of reminder lists to include')
|
74
74
|
@op.on('--el=LISTS', Array, 'List of reminder lists to exclude')
|
75
75
|
|
76
|
+
@op.separator('')
|
77
|
+
@op.on('--match=FIELD=REGEXP', String, 'Include only items whose FIELD matches REGEXP (ignoring case)')
|
78
|
+
|
76
79
|
# dates
|
77
80
|
@op.separator("\nChoosing dates:\n\n")
|
78
81
|
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: icalPal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Rosen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sqlite3
|