icalPal 3.3.0 → 3.5.0
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.
- checksums.yaml +4 -4
- data/README.md +45 -25
- data/bin/icalPal +30 -89
- data/bin/icalpal +30 -89
- data/icalPal.gemspec +11 -9
- data/lib/ToICalPal.rb +24 -27
- data/lib/defaults.rb +14 -6
- data/lib/event.rb +99 -78
- data/lib/icalPal.rb +18 -11
- data/lib/options.rb +58 -13
- data/lib/rdt.rb +22 -4
- data/lib/utils.rb +0 -7
- data/lib/version.rb +1 -1
- metadata +23 -2
data/lib/options.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
# rubocop: disable Style/FormatString, Style/FormatStringToken
|
2
2
|
|
3
|
-
|
3
|
+
autoload(:OptionParser, 'optparse')
|
4
4
|
|
5
|
-
require_relative 'defaults'
|
6
5
|
require_relative 'version'
|
7
6
|
|
8
7
|
module ICalPal
|
@@ -27,9 +26,9 @@ module ICalPal
|
|
27
26
|
@op = OptionParser.new
|
28
27
|
@op.summary_width = 23
|
29
28
|
@op.banner += ' [-c] COMMAND'
|
30
|
-
@op.version =
|
29
|
+
@op.version = VERSION
|
31
30
|
|
32
|
-
@op.accept(
|
31
|
+
@op.accept(RDT) { |s| RDT.conv(s) }
|
33
32
|
|
34
33
|
# head
|
35
34
|
@op.on_head("\nCOMMAND must be one of the following:\n\n")
|
@@ -55,6 +54,7 @@ module ICalPal
|
|
55
54
|
'For the tasks commands this should be a directory containing .sqlite files',
|
56
55
|
"(default: #{$defaults[:tasks][:db]})")
|
57
56
|
@op.on('--cf=FILE', "Set config file path (default: #{$defaults[:common][:cf]})")
|
57
|
+
@op.on('--norc', 'Ignore ICALPAL and ICALPAL_CONFIG environment variables')
|
58
58
|
@op.on('-o', '--output=FORMAT', OUTFORMATS,
|
59
59
|
"Print as FORMAT (default: #{$defaults[:common][:output]})", "[#{OUTFORMATS.join(', ')}]")
|
60
60
|
|
@@ -83,8 +83,8 @@ module ICalPal
|
|
83
83
|
# dates
|
84
84
|
@op.separator("\nChoosing dates:\n\n")
|
85
85
|
|
86
|
-
@op.on('--from=DATE',
|
87
|
-
@op.on('--to=DATE',
|
86
|
+
@op.on('--from=DATE', RDT, 'List events starting on or after DATE')
|
87
|
+
@op.on('--to=DATE', RDT, 'List events starting on or before DATE',
|
88
88
|
'DATE can be yesterday, today, tomorrow, +N, -N, or anything accepted by DateTime.parse()',
|
89
89
|
'See https://ruby-doc.org/stdlib-2.6.1/libdoc/date/rdoc/DateTime.html#method-c-parse')
|
90
90
|
@op.separator('')
|
@@ -172,6 +172,14 @@ module ICalPal
|
|
172
172
|
@op.on_tail('%s%s %sAdditional arguments' % pad('ICALPAL'))
|
173
173
|
@op.on_tail('%s%s %sAdditional arguments from a file' % pad('ICALPAL_CONFIG'))
|
174
174
|
@op.on_tail("%s%s %s(default: #{$defaults[:common][:cf]})" % pad(''))
|
175
|
+
|
176
|
+
@op.on_tail('')
|
177
|
+
|
178
|
+
note = 'Do not quote or escape values.'
|
179
|
+
note += ' Options set in ICALPAL override ICALPAL_CONFIG.'
|
180
|
+
note += ' Options on the command line override ICALPAL.'
|
181
|
+
|
182
|
+
@op.on_tail("#{@op.summary_indent}#{note}")
|
175
183
|
end
|
176
184
|
|
177
185
|
# Parse options from the CLI and merge them with other sources
|
@@ -184,11 +192,45 @@ module ICalPal
|
|
184
192
|
env = {}
|
185
193
|
cf = {}
|
186
194
|
|
187
|
-
# Load from CLI
|
195
|
+
# Load from CLI
|
188
196
|
@op.parse!(into: cli)
|
189
|
-
|
190
|
-
|
191
|
-
|
197
|
+
|
198
|
+
# Environment variable needs special parsing.
|
199
|
+
# OptionParser.parse doesn't handle whitespace in a
|
200
|
+
# comma-separated value.
|
201
|
+
begin
|
202
|
+
o = []
|
203
|
+
|
204
|
+
ENV['ICALPAL'].gsub(/^-/, ' -').split(' -').each do |e|
|
205
|
+
a = e.split(' ', 2)
|
206
|
+
|
207
|
+
if a[0]
|
208
|
+
o.push("-#{a[0]}")
|
209
|
+
o.push(a[1]) if a[1]
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
@op.parse!(o, into: env)
|
214
|
+
end if ENV['ICALPAL'] && !cli[:norc]
|
215
|
+
|
216
|
+
# Configuration file needs special parsing for the same reason
|
217
|
+
begin
|
218
|
+
o = []
|
219
|
+
|
220
|
+
cli[:cf] ||= ENV['ICALPAL_CONFIG'] || $defaults[:common][:cf]
|
221
|
+
|
222
|
+
File.read(File.expand_path(cli[:cf])).split("\n").each do |line|
|
223
|
+
a = line.split(' ', 2)
|
224
|
+
|
225
|
+
if a[0] && a[0][0] != '#'
|
226
|
+
o.push(a[0])
|
227
|
+
o.push(a[1]) if a[1]
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
@op.parse!(o, into: cf)
|
232
|
+
rescue StandardError
|
233
|
+
end unless cli[:norc]
|
192
234
|
|
193
235
|
cli[:cmd] ||= @op.default_argv[0]
|
194
236
|
cli[:cmd] ||= env[:cmd] if env[:cmd]
|
@@ -198,10 +240,10 @@ module ICalPal
|
|
198
240
|
# Parse eventsNow and eventsToday commands
|
199
241
|
cli[:cmd].match('events(Now|Today)(\+[0-9]+)?') do |m|
|
200
242
|
cli[:now] = true if m[1] == 'Now'
|
201
|
-
cli[:days] = (m[1] == 'Today')? m[2].to_i
|
243
|
+
cli[:days] = (m[1] == 'Today')? m[2].to_i : 1
|
202
244
|
|
203
245
|
cli[:from] = $today
|
204
|
-
cli[:to] = $today + cli[:days]
|
246
|
+
cli[:to] = $today + cli[:days] if cli[:days]
|
205
247
|
cli[:days] = Integer(cli[:to] - cli[:from])
|
206
248
|
|
207
249
|
cli[:cmd] = 'events'
|
@@ -244,6 +286,7 @@ module ICalPal
|
|
244
286
|
opts[:to] += 1 if opts[:to]
|
245
287
|
opts[:to] ||= opts[:from] + 1 if opts[:from]
|
246
288
|
opts[:to] = opts[:from] + opts[:days] if opts[:days]
|
289
|
+
opts[:to] = RDT.new(*opts[:to].to_a[0..2] + [ 23, 59, 59 ])
|
247
290
|
opts[:days] ||= Integer(opts[:to] - opts[:from])
|
248
291
|
opts[:from] = $now if opts[:n]
|
249
292
|
end
|
@@ -287,7 +330,9 @@ module ICalPal
|
|
287
330
|
# Pad non-options to align with options
|
288
331
|
#
|
289
332
|
# @param t [String] Text on the left side
|
290
|
-
#
|
333
|
+
#
|
334
|
+
# @return [Array<String>] Array containing +summary_indent+, +t+,
|
335
|
+
# a number of spaces equal to (+summary_width+ - +t.length+)
|
291
336
|
def pad(t)
|
292
337
|
[ @op.summary_indent, t, ' ' * (@op.summary_width - t.length) ]
|
293
338
|
end
|
data/lib/rdt.rb
CHANGED
@@ -1,9 +1,22 @@
|
|
1
|
-
require 'date'
|
2
|
-
|
3
1
|
module ICalPal
|
4
2
|
# Child class of DateTime that adds support for relative dates (<em><b>R</b>elative<b>D</b>ate<b>T</b>ime</em>).
|
5
3
|
class RDT < DateTime
|
6
4
|
|
5
|
+
# Create a new RDT from a Time object
|
6
|
+
def self.from_time(t)
|
7
|
+
new(*t.to_a[0..5].reverse)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Create a new RDT from seconds since epoch
|
11
|
+
def self.from_epoch(s)
|
12
|
+
from_time(Time.at(s))
|
13
|
+
end
|
14
|
+
|
15
|
+
# Create a new RDT from seconds since iCal epoch
|
16
|
+
def self.from_itime(s)
|
17
|
+
from_epoch(s + ITIME)
|
18
|
+
end
|
19
|
+
|
7
20
|
# Convert a String to an RDT
|
8
21
|
#
|
9
22
|
# @param str [String] can be +yesterday+, +today+, +tomorrow+,
|
@@ -28,7 +41,7 @@ module ICalPal
|
|
28
41
|
# @return [String] A string representation of self relative to
|
29
42
|
# today.
|
30
43
|
def to_s
|
31
|
-
return strftime($opts[:df]) if $opts[:nrd] && $opts[:df]
|
44
|
+
return strftime($opts[:df]) if $opts && $opts[:nrd] && $opts[:df]
|
32
45
|
|
33
46
|
case Integer(RDT.new(year, month, day) - $today)
|
34
47
|
when -2 then 'day before yesterday'
|
@@ -36,7 +49,7 @@ module ICalPal
|
|
36
49
|
when 0 then 'today'
|
37
50
|
when 1 then 'tomorrow'
|
38
51
|
when 2 then 'day after tomorrow'
|
39
|
-
else strftime($opts[:df]) if $opts[:df]
|
52
|
+
else strftime($opts[:df]) if $opts && $opts[:df]
|
40
53
|
end
|
41
54
|
end
|
42
55
|
|
@@ -54,6 +67,11 @@ module ICalPal
|
|
54
67
|
to_time.to_i
|
55
68
|
end
|
56
69
|
|
70
|
+
# @return [Array] Only the year, month and day of self
|
71
|
+
def ymd
|
72
|
+
[ year, month, day ]
|
73
|
+
end
|
74
|
+
|
57
75
|
# @see ICalPal::RDT.to_s
|
58
76
|
#
|
59
77
|
# @return [Boolean]
|
data/lib/utils.rb
CHANGED
@@ -9,10 +9,6 @@ def xmlify(key, value)
|
|
9
9
|
# Nil
|
10
10
|
when NilClass then "<#{key}/>"
|
11
11
|
|
12
|
-
# String, Integer
|
13
|
-
when String then "<#{key}>#{value}</#{key}>"
|
14
|
-
when Integer then "<#{key}>#{value}</#{key}>"
|
15
|
-
|
16
12
|
# Array
|
17
13
|
when Array
|
18
14
|
# Treat empty arrays as nil values
|
@@ -22,9 +18,6 @@ def xmlify(key, value)
|
|
22
18
|
value.each { |x| retval += xmlify("#{key}0", x) }
|
23
19
|
"<#{key}>#{retval}</#{key}>"
|
24
20
|
|
25
|
-
# RDT
|
26
|
-
when ICalPal::RDT then "<#{key}>#{value}</#{key}>"
|
27
|
-
|
28
21
|
# Unknown
|
29
22
|
else "<#{key}>#{value}</#{key}>"
|
30
23
|
end
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: icalPal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Rosen
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-05-13 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: nokogiri-plist
|
@@ -37,6 +37,26 @@ dependencies:
|
|
37
37
|
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
39
|
version: 2.6.0
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: timezone
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0.99'
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 1.3.0
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0.99'
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 1.3.0
|
40
60
|
description: |
|
41
61
|
Inspired by icalBuddy and maintains close compatability. Includes
|
42
62
|
many additional features for querying, filtering, and formatting.
|
@@ -68,6 +88,7 @@ licenses:
|
|
68
88
|
- GPL-3.0-or-later
|
69
89
|
metadata:
|
70
90
|
bug_tracker_uri: https://github.com/ajrosen/icalPal/issues
|
91
|
+
rubygems_mfa_required: 'true'
|
71
92
|
post_install_message: |2+
|
72
93
|
|
73
94
|
Note: icalPal requires "Full Disk Access" in System Settings to access your calendar.
|