vpim 0.619 → 0.658
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.
- data/CHANGES +60 -0
- data/README +37 -30
- data/bin/reminder +1 -1
- data/lib/atom.rb +728 -0
- data/lib/atom/pub.rb +206 -0
- data/lib/atom/version.rb +9 -0
- data/lib/atom/xml/parser.rb +305 -0
- data/lib/plist.rb +22 -0
- data/lib/plist/generator.rb +224 -0
- data/lib/plist/parser.rb +225 -0
- data/lib/vpim/date.rb +1 -1
- data/lib/vpim/enumerator.rb +6 -1
- data/lib/vpim/field.rb +1 -0
- data/lib/vpim/icalendar.rb +74 -29
- data/lib/vpim/property/base.rb +31 -1
- data/lib/vpim/property/common.rb +13 -13
- data/lib/vpim/property/recurrence.rb +30 -14
- data/lib/vpim/repo.rb +120 -55
- data/lib/vpim/rfc2425.rb +5 -4
- data/lib/vpim/rrule.rb +70 -7
- data/lib/vpim/vcard.rb +26 -2
- data/lib/vpim/version.rb +2 -2
- data/lib/vpim/vevent.rb +33 -51
- data/lib/vpim/view.rb +90 -0
- data/lib/vpim/vjournal.rb +12 -0
- data/lib/vpim/vpim.rb +1 -1
- data/lib/vpim/vtodo.rb +11 -2
- data/samples/reminder.rb +1 -1
- data/test/test_all.rb +10 -7
- data/test/test_date.rb +2 -2
- data/test/test_ical.rb +199 -4
- data/test/test_repo.rb +158 -0
- data/test/test_rrule.rb +51 -0
- data/test/test_vcard.rb +129 -0
- data/test/test_view.rb +79 -0
- metadata +16 -12
data/lib/vpim/date.rb
CHANGED
@@ -16,7 +16,7 @@ class Date
|
|
16
16
|
|
17
17
|
# Converts this object to a Time object, or throws an ArgumentError if
|
18
18
|
# conversion is not possible because it is before the start of epoch.
|
19
|
-
def
|
19
|
+
def vpim_to_time
|
20
20
|
raise ArgumentError, 'date is before the start of system time' if self < TIME_START
|
21
21
|
days = self - TIME_START
|
22
22
|
|
data/lib/vpim/enumerator.rb
CHANGED
@@ -6,11 +6,16 @@
|
|
6
6
|
details.
|
7
7
|
=end
|
8
8
|
|
9
|
+
require "enumerator"
|
10
|
+
|
9
11
|
module Vpim
|
10
12
|
# This is a way for an object to have multiple ways of being enumerated via
|
11
13
|
# argument to it's #each() method. An Enumerator mixes in Enumerable, so the
|
12
|
-
# standard
|
14
|
+
# standard APIs such as Enumerable#map(), Enumerable#to_a(), and
|
13
15
|
# Enumerable#find_all() can be used on it.
|
16
|
+
#
|
17
|
+
# TODO since 1.8, this is part of the standard library, I should rewrite vPim
|
18
|
+
# so this can be removed.
|
14
19
|
class Enumerator
|
15
20
|
include Enumerable
|
16
21
|
|
data/lib/vpim/field.rb
CHANGED
data/lib/vpim/icalendar.rb
CHANGED
@@ -6,6 +6,8 @@
|
|
6
6
|
details.
|
7
7
|
=end
|
8
8
|
|
9
|
+
require "enumerator"
|
10
|
+
|
9
11
|
require 'vpim/rfc2425'
|
10
12
|
require 'vpim/dirinfo'
|
11
13
|
require 'vpim/rrule'
|
@@ -43,6 +45,7 @@ module Vpim
|
|
43
45
|
# iCalendars are usually transmitted in files with <code>.ics</code>
|
44
46
|
# extensions.
|
45
47
|
class Icalendar
|
48
|
+
# FIXME do NOT do this!
|
46
49
|
include Vpim
|
47
50
|
|
48
51
|
# Regular expression strings for the EBNF of RFC 2445
|
@@ -70,19 +73,16 @@ module Vpim
|
|
70
73
|
|
71
74
|
@components = []
|
72
75
|
|
76
|
+
# could use #constants instead of this
|
73
77
|
factory = {
|
74
78
|
'VEVENT' => Vevent,
|
75
79
|
'VTODO' => Vtodo,
|
76
80
|
'VJOURNAL' => Vjournal,
|
81
|
+
# TODO - VTIMEZONE
|
77
82
|
}
|
78
83
|
|
79
84
|
inner.each do |component|
|
80
|
-
name = component.first
|
81
|
-
unless name.name? 'BEGIN'
|
82
|
-
raise InvalidEncodingError, "calendar component begins with #{name.name}, instead of BEGIN!"
|
83
|
-
end
|
84
|
-
|
85
|
-
name = name.value
|
85
|
+
name = component.first.value
|
86
86
|
|
87
87
|
if klass = factory[name]
|
88
88
|
@components << klass.new(component)
|
@@ -90,25 +90,43 @@ module Vpim
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
-
# Add
|
93
|
+
# Add an event to this calendar.
|
94
94
|
#
|
95
95
|
# Yields an event maker, Icalendar::Vevent::Maker.
|
96
96
|
def add_event(&block) #:yield:event
|
97
97
|
push Vevent::Maker.make( &block )
|
98
98
|
end
|
99
99
|
|
100
|
-
#
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
100
|
+
# TODO add_todo, add_journal
|
101
|
+
|
102
|
+
=begin
|
103
|
+
TODO
|
104
|
+
# Allows customization of calendar creation.
|
105
|
+
class Maker
|
106
|
+
def initialize #:nodoc:
|
107
|
+
@prodid = Vpim::PRODID
|
108
|
+
end
|
109
|
+
|
110
|
+
attr :prodid
|
111
|
+
end
|
112
|
+
=end
|
113
|
+
|
114
|
+
# The producer ID defaults to Vpim::PRODID but you can set it to something
|
115
|
+
# specific to your application.
|
116
|
+
def Icalendar.create2(producer = Vpim::PRODID) #:yield: self
|
105
117
|
# FIXME - make the primary API
|
106
118
|
di = DirectoryInfo.create( [ DirectoryInfo::Field.create('VERSION', '2.0') ], 'VCALENDAR' )
|
107
119
|
|
108
|
-
di.push_unique DirectoryInfo::Field.create('PRODID',
|
120
|
+
di.push_unique DirectoryInfo::Field.create('PRODID', producer.to_str)
|
109
121
|
di.push_unique DirectoryInfo::Field.create('CALSCALE', "Gregorian")
|
110
122
|
|
111
|
-
new(di.to_a)
|
123
|
+
cal = new(di.to_a)
|
124
|
+
|
125
|
+
if block_given?
|
126
|
+
yield cal
|
127
|
+
end
|
128
|
+
|
129
|
+
cal
|
112
130
|
end
|
113
131
|
|
114
132
|
# Create a new Icalendar object with the minimal set of fields for a valid
|
@@ -149,7 +167,10 @@ module Vpim
|
|
149
167
|
def fields # :nodoc:
|
150
168
|
f = @properties.to_a
|
151
169
|
last = f.pop
|
152
|
-
|
170
|
+
# Use of #each means we won't encode components in our View, but also
|
171
|
+
# that we won't encode timezones... but we don't decode/support timezones
|
172
|
+
# anyhow, so fix later.
|
173
|
+
each { |c| f << c.fields }
|
153
174
|
f.push last
|
154
175
|
end
|
155
176
|
|
@@ -175,6 +196,8 @@ module Vpim
|
|
175
196
|
self
|
176
197
|
end
|
177
198
|
|
199
|
+
alias :<< :push
|
200
|
+
|
178
201
|
# Check if the protocol method is +method+
|
179
202
|
def protocol?(method)
|
180
203
|
Vpim::Methods.casecmp?(protocol, method)
|
@@ -246,9 +269,8 @@ module Vpim
|
|
246
269
|
calendars
|
247
270
|
end
|
248
271
|
|
249
|
-
# The iCalendar version multiplied by 10 as an Integer.
|
250
|
-
#
|
251
|
-
# have a version of 20, and vCalendar would have a version of 10.
|
272
|
+
# The iCalendar version multiplied by 10 as an Integer. iCalendar must have
|
273
|
+
# a version of 20, and vCalendar must have a version of 10.
|
252
274
|
def version
|
253
275
|
v = @properties['VERSION']
|
254
276
|
|
@@ -284,11 +306,11 @@ module Vpim
|
|
284
306
|
# The value of the CALSCALE: property, or "GREGORIAN" if CALSCALE: is not
|
285
307
|
# present.
|
286
308
|
#
|
287
|
-
# This is of academic interest
|
288
|
-
#
|
289
|
-
#
|
309
|
+
# This is of academic interest only. There aren't any other calendar scales
|
310
|
+
# defined, and given that its hard enough just dealing with Gregorian
|
311
|
+
# calendars, there probably won't be.
|
290
312
|
def calscale
|
291
|
-
|
313
|
+
(@properties['CALSCALE'] || 'GREGORIAN').upcase
|
292
314
|
end
|
293
315
|
|
294
316
|
# The array of all supported calendar components. If a class is provided,
|
@@ -305,8 +327,12 @@ module Vpim
|
|
305
327
|
#
|
306
328
|
# calendar.components {|c| c... }
|
307
329
|
# => yield all components
|
330
|
+
#
|
331
|
+
# Note - use of this is mildly deprecated in favour of #each, #events,
|
332
|
+
# #todos, #journals because those won't return timezones, and will return
|
333
|
+
# Enumerators if called without a block.
|
308
334
|
def components(klass=Object) #:yields:component
|
309
|
-
|
335
|
+
klass ||= Object
|
310
336
|
|
311
337
|
unless block_given?
|
312
338
|
return @components.select{|c| klass === c}.freeze
|
@@ -320,14 +346,33 @@ module Vpim
|
|
320
346
|
self
|
321
347
|
end
|
322
348
|
|
323
|
-
|
324
|
-
|
325
|
-
|
349
|
+
include Enumerable
|
350
|
+
|
351
|
+
# Enumerate the top-level calendar components. Yields them if a block
|
352
|
+
# is provided, otherwise returns an Enumerator.
|
353
|
+
#
|
354
|
+
# This skips components that are only internally meaningful to iCalendar,
|
355
|
+
# such as timezone definitions.
|
356
|
+
def each(klass=nil, &block) # :yield: component
|
357
|
+
unless block
|
358
|
+
return Enumerable::Enumerator.new(self, :each, klass)
|
359
|
+
end
|
360
|
+
components(klass, &block)
|
361
|
+
end
|
362
|
+
|
363
|
+
# Short-hand for #each(Icalendar::Vevent).
|
364
|
+
def events(&block) #:yield: Vevent
|
365
|
+
each(Icalendar::Vevent, &block)
|
366
|
+
end
|
367
|
+
|
368
|
+
# Short-hand for #each(Icalendar::Vtodo).
|
369
|
+
def todos(&block) #:yield: Vtodo
|
370
|
+
each(Icalendar::Vtodo, &block)
|
326
371
|
end
|
327
372
|
|
328
|
-
#
|
329
|
-
def
|
330
|
-
|
373
|
+
# Short-hand for #each(Icalendar::Vjournal).
|
374
|
+
def journals(&block) #:yield: Vjournal
|
375
|
+
each(Icalendar::Vjournal, &block)
|
331
376
|
end
|
332
377
|
|
333
378
|
end
|
data/lib/vpim/property/base.rb
CHANGED
@@ -10,6 +10,7 @@ module Vpim
|
|
10
10
|
class Icalendar
|
11
11
|
module Set #:nodoc:
|
12
12
|
module Util #:nodoc:
|
13
|
+
# TODO - rename module to Private?
|
13
14
|
|
14
15
|
def rm_all(name)
|
15
16
|
rm = @comp.properties.select { |f| f.name? name }
|
@@ -114,7 +115,7 @@ module Vpim
|
|
114
115
|
end
|
115
116
|
|
116
117
|
def proptoken(name, allowed, default_token = nil) #:nodoc:
|
117
|
-
prop = propvalue
|
118
|
+
prop = propvalue(name)
|
118
119
|
|
119
120
|
if prop
|
120
121
|
prop = prop.to_str.upcase
|
@@ -156,6 +157,35 @@ module Vpim
|
|
156
157
|
@properties.select{ |f| f.name? name }.map{ |p| Vpim.decode_text_list(p.value_raw) }.flatten
|
157
158
|
end
|
158
159
|
|
160
|
+
# Duration has "almost" the same definition for Event and Todo
|
161
|
+
def propduration(endfield)
|
162
|
+
dur = @properties.field 'DURATION'
|
163
|
+
dte = @properties.field endfield
|
164
|
+
|
165
|
+
if !dur
|
166
|
+
return nil unless dte
|
167
|
+
|
168
|
+
b = dtstart
|
169
|
+
e = send(endfield.downcase.to_sym)
|
170
|
+
|
171
|
+
return (e - b).to_i
|
172
|
+
end
|
173
|
+
|
174
|
+
Icalendar.decode_duration(dur.value_raw)
|
175
|
+
end
|
176
|
+
|
177
|
+
def propend(endfield)
|
178
|
+
dte = @properties.field endfield.to_s.upcase
|
179
|
+
if dte
|
180
|
+
dte.to_time.first
|
181
|
+
elsif duration
|
182
|
+
dtstart + duration
|
183
|
+
else
|
184
|
+
nil
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
|
159
189
|
end
|
160
190
|
end
|
161
191
|
end
|
data/lib/vpim/property/common.rb
CHANGED
@@ -180,46 +180,46 @@ seq
|
|
180
180
|
# Properties common to Vevent, Vtodo, and Vjournal.
|
181
181
|
module Common
|
182
182
|
|
183
|
-
# Set the access class of the component, see Icalendar::
|
183
|
+
# Set the access class of the component, see Icalendar::Property::Common#access_class.
|
184
184
|
def access_class(token)
|
185
185
|
set_token 'CLASS', ["PUBLIC", "PRIVATE", "CONFIDENTIAL"], "PUBLIC", token
|
186
186
|
end
|
187
187
|
|
188
|
-
# Set the creation time, see Icalendar::
|
188
|
+
# Set the creation time, see Icalendar::Property::Common#created
|
189
189
|
def created(time)
|
190
190
|
set_datetime 'CREATED', time
|
191
191
|
end
|
192
192
|
|
193
|
-
# Set the description, see Icalendar::
|
193
|
+
# Set the description, see Icalendar::Property::Common#description.
|
194
194
|
def description(text)
|
195
195
|
set_text 'DESCRIPTION', text
|
196
196
|
end
|
197
197
|
|
198
|
-
# Set the sequence number, see Icalendar::
|
198
|
+
# Set the sequence number, see Icalendar::Property::Common#sequence.
|
199
199
|
# is no SEQUENCE; property.
|
200
200
|
def sequence(int)
|
201
201
|
set_integer 'SEQUENCE', int
|
202
202
|
end
|
203
203
|
|
204
|
-
# Set the timestamp, see Icalendar::
|
204
|
+
# Set the timestamp, see Icalendar::Property::Common#timestamp.
|
205
205
|
def dtstamp(time)
|
206
206
|
set_datetime 'DTSTAMP', time
|
207
207
|
self
|
208
208
|
end
|
209
209
|
|
210
|
-
# The start time or date, see Icalendar::
|
210
|
+
# The start time or date, see Icalendar::Property::Common#dtstart.
|
211
211
|
def dtstart(start)
|
212
212
|
set_date_or_datetime 'DTSTART', 'DATE-TIME', start
|
213
213
|
self
|
214
214
|
end
|
215
215
|
|
216
|
-
# Set the last modification time, see Icalendar::
|
216
|
+
# Set the last modification time, see Icalendar::Property::Common#lastmod.
|
217
217
|
def lastmod(time)
|
218
218
|
set_datetime 'LAST-MODIFIED', time
|
219
219
|
self
|
220
220
|
end
|
221
221
|
|
222
|
-
# Set the event organizer, an Icalendar::Address, see Icalendar::
|
222
|
+
# Set the event organizer, an Icalendar::Address, see Icalendar::Property::Common#organizer.
|
223
223
|
#
|
224
224
|
# Without an +adr+ it yields an Icalendar::Address that is a copy of
|
225
225
|
# the current organizer (if any), allowing it to be modified.
|
@@ -255,12 +255,12 @@ seq
|
|
255
255
|
end
|
256
256
|
=end
|
257
257
|
|
258
|
-
# Set summary description of component, see Icalendar::
|
258
|
+
# Set summary description of component, see Icalendar::Property::Common#summary.
|
259
259
|
def summary(text)
|
260
260
|
set_text 'SUMMARY', text
|
261
261
|
end
|
262
262
|
|
263
|
-
# Set the unique identifier of this calendar component, see Icalendar::
|
263
|
+
# Set the unique identifier of this calendar component, see Icalendar::Property::Common#uid.
|
264
264
|
def uid(uid)
|
265
265
|
set_text 'UID', uid
|
266
266
|
end
|
@@ -269,12 +269,12 @@ seq
|
|
269
269
|
set_text 'URL', url
|
270
270
|
end
|
271
271
|
|
272
|
-
# Add an attendee Address, see Icalendar::
|
272
|
+
# Add an attendee Address, see Icalendar::Property::Common#attendees.
|
273
273
|
def add_attendee(adr)
|
274
274
|
add_address('ATTENDEE', adr)
|
275
275
|
end
|
276
276
|
|
277
|
-
# Set the categories, see Icalendar::
|
277
|
+
# Set the categories, see Icalendar::Property::Common#attendees.
|
278
278
|
#
|
279
279
|
# If +cats+ is provided, the categories are set to cats, either a
|
280
280
|
# String or an Array of String. Otherwise, and array of the existing
|
@@ -288,7 +288,7 @@ seq
|
|
288
288
|
set_text_list('CATEGORIES', cats)
|
289
289
|
end
|
290
290
|
|
291
|
-
# Set the comment, see Icalendar::
|
291
|
+
# Set the comment, see Icalendar::Property::Common#comments.
|
292
292
|
def comment(value)
|
293
293
|
set_text 'COMMENT', value
|
294
294
|
end
|
@@ -6,42 +6,58 @@
|
|
6
6
|
details.
|
7
7
|
=end
|
8
8
|
|
9
|
+
require "enumerator"
|
10
|
+
|
9
11
|
module Vpim
|
10
12
|
class Icalendar
|
11
13
|
module Property
|
12
14
|
|
13
|
-
# Occurrences are calculated from DTSTART
|
14
|
-
# RRULE
|
15
|
+
# Occurrences are calculated from DTSTART and RRULE. If there is no
|
16
|
+
# RRULE, the component occurs only once, at the start time.
|
15
17
|
#
|
16
18
|
# Limitations:
|
17
19
|
#
|
18
20
|
# Only a single RRULE: is currently supported, this is the most common
|
19
21
|
# case.
|
20
|
-
#
|
21
|
-
# Implementation of multiple RRULE:s, and RDATE:, EXRULE:, and EXDATE: is
|
22
|
-
# on the todo list. Its not a very high priority, because I haven't seen
|
23
|
-
# calendars using the full range of recurrence features, and haven't
|
24
|
-
# received feedback from any users requesting these features. So, if you
|
25
|
-
# need it, contact me and implementation will get on the schedule.
|
26
22
|
module Recurrence
|
27
|
-
|
28
|
-
def occurrences
|
23
|
+
def rrule #:nodoc:
|
29
24
|
start = dtstart
|
30
25
|
unless start
|
31
|
-
raise ArgumentError, "Components
|
26
|
+
raise ArgumentError, "Components without a DTSTART don't have occurrences!"
|
32
27
|
end
|
33
28
|
Vpim::Rrule.new(start, propvalue('RRULE'))
|
34
29
|
end
|
35
30
|
|
31
|
+
# The times this components occurs. If a block is not provided, returns
|
32
|
+
# an enumerator.
|
33
|
+
#
|
34
|
+
# Occurrences may be infinite, +dountil+ can be provided to limit the
|
35
|
+
# iterations, see Rrule#each.
|
36
|
+
def occurrences(dountil = nil, &block) #:yield: occurrence time
|
37
|
+
rr = rrule
|
38
|
+
unless block_given?
|
39
|
+
return Enumerable::Enumerator.new(self, :occurrences, dountil)
|
40
|
+
end
|
41
|
+
|
42
|
+
rr.each(dountil, &block)
|
43
|
+
end
|
44
|
+
|
36
45
|
alias occurences occurrences #:nodoc: backwards compatibility
|
37
46
|
|
38
|
-
#
|
47
|
+
# True if this components occurs in a time period later than +t0+, but
|
39
48
|
# earlier than +t1+.
|
40
49
|
def occurs_in?(t0, t1)
|
41
|
-
|
50
|
+
# TODO - deprecate this, its a hack
|
51
|
+
occurrences(t1).detect do |tend|
|
52
|
+
if respond_to? :duration
|
53
|
+
tend += duration || 0
|
54
|
+
end
|
55
|
+
tend >= t0
|
56
|
+
end
|
42
57
|
end
|
43
58
|
|
44
|
-
def rdates
|
59
|
+
def rdates #:nodoc:
|
60
|
+
# TODO - this is a hack, remove it
|
45
61
|
Vpim.decode_date_time_list(propvalue('RDATE'))
|
46
62
|
end
|
47
63
|
|
data/lib/vpim/repo.rb
CHANGED
@@ -6,109 +6,174 @@
|
|
6
6
|
details.
|
7
7
|
=end
|
8
8
|
|
9
|
+
require 'enumerator'
|
10
|
+
|
11
|
+
require 'plist'
|
12
|
+
|
9
13
|
require 'vpim/icalendar'
|
10
14
|
require 'vpim/duration'
|
11
15
|
|
12
16
|
module Vpim
|
13
|
-
# A Repo is a representation of
|
14
|
-
# repositories and directories containing .ics files are supported.
|
17
|
+
# A Repo is a representation of a calendar repository.
|
15
18
|
#
|
16
|
-
#
|
17
|
-
# an
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
# Currently supported repository types are:
|
20
|
+
# - Repo::Apple3, an Apple iCal3 repository.
|
21
|
+
# - Repo::Directory, a directory hierarchy containing .ics files
|
22
|
+
#
|
23
|
+
# All repository types support at least the methods of Repo, and all
|
24
|
+
# repositories return calendars that support at least the methods of
|
25
|
+
# Repo::Calendar.
|
26
|
+
class Repo
|
27
|
+
include Enumerable
|
28
|
+
|
29
|
+
# Open a repository at location +where+.
|
30
|
+
def initialize(where)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Enumerate the calendars in the repository.
|
34
|
+
def each #:yield: calendar
|
35
|
+
end
|
36
|
+
|
37
|
+
# A calendar abstraction. It models a calendar in a calendar repository
|
38
|
+
# that may not be an iCalendar.
|
39
|
+
#
|
40
|
+
# It has methods that behave identically to Icalendar, but it also has
|
41
|
+
# methods like name and displayed that are not present in an iCalendar.
|
42
|
+
class Calendar
|
43
|
+
include Enumerable
|
44
|
+
|
45
|
+
# The calendar name.
|
46
|
+
def name
|
47
|
+
end
|
48
|
+
|
49
|
+
# Whether a calendar should be displayed.
|
50
|
+
#
|
51
|
+
# TODO - should be #displayed?
|
52
|
+
def displayed
|
53
|
+
end
|
54
|
+
|
55
|
+
# Encode into iCalendar format.
|
56
|
+
def encode
|
57
|
+
end
|
58
|
+
|
59
|
+
# Enumerate the components in the calendar, both todos and events, or
|
60
|
+
# the specified klass. Like Icalendar#each()
|
61
|
+
def each(klass=nil, &block) #:yield: component
|
62
|
+
end
|
63
|
+
|
64
|
+
# Enumerate the events in the calendar.
|
65
|
+
def events(&block) #:yield: Vevent
|
66
|
+
each(Vpim::Icalendar::Vevent, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Enumerate the todos in the calendar.
|
70
|
+
def todos(&block) #:yield: Vtodo
|
71
|
+
each(Vpim::Icalendar::Vtodo, &block)
|
72
|
+
end
|
73
|
+
|
74
|
+
# The method definitions are just to fool rdoc, not to be used.
|
75
|
+
%w{each name displayed encode}.each{|m| remove_method m}
|
76
|
+
|
77
|
+
def file_each(file, klass, &block) #:nodoc:
|
78
|
+
unless iterator?
|
79
|
+
return Enumerable::Enumerator.new(self, :each, klass)
|
80
|
+
end
|
81
|
+
|
22
82
|
cals = Vpim::Icalendar.decode(File.open(file))
|
23
83
|
|
24
84
|
cals.each do |cal|
|
25
|
-
cal.
|
26
|
-
somethings << x
|
27
|
-
end
|
85
|
+
cal.each(klass, &block)
|
28
86
|
end
|
87
|
+
self
|
29
88
|
end
|
30
|
-
somethings
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.events_from_file(file) #:nodoc:
|
34
|
-
self.somethings_from_file("events", file)
|
35
89
|
end
|
90
|
+
end
|
36
91
|
|
37
|
-
|
38
|
-
|
39
|
-
end
|
92
|
+
class Repo
|
93
|
+
include Enumerable
|
40
94
|
|
41
95
|
# An Apple iCal version 3 repository.
|
42
|
-
|
43
|
-
|
96
|
+
class Apple3 < Repo
|
97
|
+
def initialize(where = "~/Library/Calendars")
|
98
|
+
@where = where.to_str
|
99
|
+
end
|
100
|
+
|
101
|
+
def each #:nodoc:
|
102
|
+
Dir[ File.expand_path(@where + "/**/*.calendar") ].each do |dir|
|
103
|
+
yield Calendar.new(dir)
|
104
|
+
end
|
105
|
+
self
|
106
|
+
end
|
107
|
+
|
108
|
+
class Calendar < Repo::Calendar
|
44
109
|
def initialize(dir) # :nodoc:
|
45
110
|
@dir = dir
|
46
111
|
end
|
112
|
+
|
47
113
|
def plist(key) #:nodoc:
|
48
|
-
|
114
|
+
Plist::parse_xml( @dir + "/Info.plist")[key]
|
49
115
|
end
|
50
116
|
|
51
|
-
|
52
|
-
def name
|
117
|
+
def name #:nodoc:
|
53
118
|
plist "Title"
|
54
119
|
end
|
55
120
|
|
56
|
-
|
57
|
-
def displayed
|
121
|
+
def displayed #:nodoc:
|
58
122
|
1 == plist("Checked")
|
59
123
|
end
|
60
124
|
|
61
|
-
|
62
|
-
|
125
|
+
def each(klass=nil, &block) #:nodoc:
|
126
|
+
unless iterator?
|
127
|
+
return Enumerable::Enumerator.new(self, :each, klass)
|
128
|
+
end
|
63
129
|
Dir[ @dir + "/Events/*.ics" ].map do |ics|
|
64
|
-
|
65
|
-
end
|
130
|
+
file_each(ics, klass, &block)
|
131
|
+
end
|
132
|
+
self
|
66
133
|
end
|
67
134
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end.flatten
|
135
|
+
def encode #:nodoc:
|
136
|
+
Icalendar.create2 do |cal|
|
137
|
+
each{|c| cal << c}
|
138
|
+
end.encode
|
73
139
|
end
|
74
|
-
|
75
140
|
end
|
76
141
|
|
77
|
-
def self.each(where = "~/Library/Calendars") # :yield: Apple::Calendar
|
78
|
-
Dir[ File.expand_path(where + "/**/*.calendar") ].each do |dir|
|
79
|
-
yield Calendar.new(dir)
|
80
|
-
end
|
81
|
-
self
|
82
|
-
end
|
83
142
|
end
|
84
|
-
|
85
|
-
|
143
|
+
|
144
|
+
class Directory < Repo
|
145
|
+
class Calendar < Repo::Calendar
|
86
146
|
def initialize(file) #:nodoc:
|
87
147
|
@file = file
|
88
148
|
end
|
89
149
|
|
90
|
-
def name
|
150
|
+
def name #:nodoc:
|
91
151
|
File.basename(@file)
|
92
152
|
end
|
93
153
|
|
94
|
-
def displayed
|
154
|
+
def displayed #:nodoc:
|
95
155
|
true
|
96
156
|
end
|
97
157
|
|
98
|
-
def
|
99
|
-
|
158
|
+
def each(klass, &block) #:nodoc:
|
159
|
+
file_each(@file, klass, &block)
|
100
160
|
end
|
101
161
|
|
102
|
-
def
|
103
|
-
|
162
|
+
def encode #:nodoc:
|
163
|
+
open(@file, "r"){|f| f.read}
|
104
164
|
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
def initialize(where = ".")
|
169
|
+
@where = where.to_str
|
105
170
|
end
|
106
171
|
|
107
|
-
def
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
172
|
+
def each #:nodoc:
|
173
|
+
Dir[ File.expand_path(@where + "/**/*.ics") ].each do |file|
|
174
|
+
yield Calendar.new(file)
|
175
|
+
end
|
176
|
+
self
|
112
177
|
end
|
113
178
|
end
|
114
179
|
end
|