icalPal 3.5.0 → 3.6.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f2549d35908833fd3fbb48d98187e3ee5618fb3c610dcb03659e8f41b67ac91d
4
- data.tar.gz: b5999da17435b5eefbc1f19fe8822c45c5ffec0741f5cb58d7f64c313d700ca2
3
+ metadata.gz: b6dbdc21833e53b6318750c5e1035ffaf995b9afa11eda811eb92f8ec39e7890
4
+ data.tar.gz: 4ce4e4166ddae0fac1c35d0e3b50ce25d3e1dc948205c6655775da6ae47c4a6e
5
5
  SHA512:
6
- metadata.gz: 64f542aa97dd5b66c28001b0f70ef289a447bc89b5272ed3a4916930a048ea2c2baed4c75b7fe71310611827b0e6e8b0a0dd13665807dba91816e72a6647b0d9
7
- data.tar.gz: e229b5a9a3261c1f145f1692d4abeb26e653e2e8c7d086d1d0f3a900fe1dfe13a8c68477ddbb22538262d27d1f7fd9cdb7ad302693815e4cb721955c5c379e30
6
+ metadata.gz: e23aea3695d7554dd3a2d38f52852e33979b0892384ae2cef565620031e036d495a1b489d0893e2426b6d2066d3075cea958c579140be798fec3bb576f5185e0
7
+ data.tar.gz: e769f0bd0164a71129a135cb82555c872bac9938ceac2301c7845355da2c9aceb37c05a67c97c10a293db07f9f5e62666b2137e02bca7156d2a31273367c52d6
data/README.md CHANGED
@@ -82,8 +82,9 @@ Shows only reminders that have a due date.
82
82
  * ```--match``` lets you filter the results of any command to items where a *FIELD* matches a regular expression. Eg., ```--match notes=zoom.us``` to show only Zoom meeetings
83
83
 
84
84
  Because icalPal is written in Ruby, and not a native Mac application,
85
- you can run it just about anywhere. It's been tested with the version
86
- of Ruby (2.6.10) included with macOS.
85
+ you can run it just about anywhere. It's been tested with the
86
+ versions of Ruby included with macOS Sequoia (2.6.10) and
87
+ [Homebrew](https://brew.sh/) (3.4.4).
87
88
 
88
89
  ## Usage
89
90
 
@@ -99,6 +100,7 @@ COMMAND must be one of the following:
99
100
  eventsToday Print events occurring today
100
101
  eventsToday+NUM Print events occurring between today and NUM days into the future
101
102
  eventsNow Print events occurring at present time
103
+ eventsRemaining Print events occurring between present time and midnight
102
104
  datedTasks Print tasks with a due date
103
105
  undatedTasks Print tasks with no due date
104
106
  ```
data/bin/icalPal CHANGED
@@ -1,28 +1,37 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- begin
4
- require 'logger'
5
-
6
- require 'csv'
7
- require 'json'
8
- require 'rdoc'
9
- require 'sqlite3'
10
- require 'yaml'
11
-
12
- require_relative '../lib/icalpal'
13
- require_relative '../lib/defaults'
14
- require_relative '../lib/options'
15
- require_relative '../lib/utils'
16
- rescue LoadError => e
17
- dep = e.message[/-- (.*)/, 1]
18
-
19
- $stderr.puts "FATAL: icalpal is missing a dependency: #{dep}"
20
- $stderr.puts
21
- $stderr.puts "Install with 'gem install --user-install #{dep}'"
3
+ # require a gem
4
+ #
5
+ # @param gem [String] The gem
6
+ def r(gem)
7
+ begin
8
+ # puts "require \"#{gem}\""
9
+ require gem
10
+ rescue LoadError => e
11
+ $stderr.puts "FATAL: icalPal is missing a dependency: #{gem}"
12
+ $stderr.puts e
13
+ $stderr.puts
14
+ abort "Try installing with 'gem install --user-install #{gem}'"
15
+ end
16
+ end
22
17
 
23
- exit
18
+ # require_relative a library
19
+ #
20
+ # @param library [String] The library
21
+ def rr(library)
22
+ begin
23
+ # puts "require_relative \"../lib/#{library}\""
24
+ require_relative "../lib/#{library}"
25
+ rescue LoadError => e
26
+ $stderr.puts "FATAL: Could not load library: #{library}"
27
+ $stderr.puts
28
+ abort e.message
29
+ end
24
30
  end
25
31
 
32
+ %w[ logger csv json rdoc sqlite3 yaml ].each { |g| r g }
33
+ %w[ icalPal defaults options utils ].each { |l| rr l }
34
+
26
35
 
27
36
  ##################################################
28
37
  # Load options
data/bin/icalpal CHANGED
@@ -1,28 +1,37 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- begin
4
- require 'logger'
5
-
6
- require 'csv'
7
- require 'json'
8
- require 'rdoc'
9
- require 'sqlite3'
10
- require 'yaml'
11
-
12
- require_relative '../lib/icalpal'
13
- require_relative '../lib/defaults'
14
- require_relative '../lib/options'
15
- require_relative '../lib/utils'
16
- rescue LoadError => e
17
- dep = e.message[/-- (.*)/, 1]
18
-
19
- $stderr.puts "FATAL: icalpal is missing a dependency: #{dep}"
20
- $stderr.puts
21
- $stderr.puts "Install with 'gem install --user-install #{dep}'"
3
+ # require a gem
4
+ #
5
+ # @param gem [String] The gem
6
+ def r(gem)
7
+ begin
8
+ # puts "require \"#{gem}\""
9
+ require gem
10
+ rescue LoadError => e
11
+ $stderr.puts "FATAL: icalPal is missing a dependency: #{gem}"
12
+ $stderr.puts e
13
+ $stderr.puts
14
+ abort "Try installing with 'gem install --user-install #{gem}'"
15
+ end
16
+ end
22
17
 
23
- exit
18
+ # require_relative a library
19
+ #
20
+ # @param library [String] The library
21
+ def rr(library)
22
+ begin
23
+ # puts "require_relative \"../lib/#{library}\""
24
+ require_relative "../lib/#{library}"
25
+ rescue LoadError => e
26
+ $stderr.puts "FATAL: Could not load library: #{library}"
27
+ $stderr.puts
28
+ abort e.message
29
+ end
24
30
  end
25
31
 
32
+ %w[ logger csv json rdoc sqlite3 yaml ].each { |g| r g }
33
+ %w[ icalPal defaults options utils ].each { |l| rr l }
34
+
26
35
 
27
36
  ##################################################
28
37
  # Load options
data/ext/extconf.rb ADDED
@@ -0,0 +1,47 @@
1
+ begin
2
+ require 'mkmf'
3
+ require 'rubygems/dependency_installer'
4
+
5
+ # Search Gem paths for one that is writable.
6
+ gemdir = nil
7
+ Gem.path.each { |p| gemdir = p if File.writable? p }
8
+
9
+ # Dependencies common to all environments
10
+ dependencies = %w[ plist timezone ]
11
+
12
+ if RUBY_VERSION >= '3.4'
13
+ # bigdecimal is not part of the default gems starting from Ruby 3.4.0.
14
+ # csv is not part of the default gems starting from Ruby 3.4.0.
15
+ dependencies.push('bigdecimal')
16
+ dependencies.push('csv')
17
+
18
+ # The macOS and Homebrew versions of rubygems have incompatible
19
+ # requirements for sqlite3.
20
+ #
21
+ # macOS 15.5 (Sequoia) comes with version 1.3.13, so it does not
22
+ # need to be added as a dependency, and it cannot install anything
23
+ # newer:
24
+ #
25
+ # requires Ruby version >= 3.0, < 3.4.dev. The current ruby version is 2.6.10.
26
+ #
27
+ # Homebrew's Ruby formula does not come with sqlite3, so it does
28
+ # need to be added as a dependency, but it cannot install version
29
+ # 1.3.13:
30
+ #
31
+ # error: call to undeclared function
32
+ #
33
+ # So neither environment can install the other's sqlite3 gem. We
34
+ # must install sqlite3, but iff we are not building with macOS'
35
+ # Ruby installation.
36
+ dependencies.push('sqlite3')
37
+ end
38
+
39
+ di = Gem::DependencyInstaller.new(install_dir: gemdir)
40
+ dependencies.each { |d| di.install(d) }
41
+ rescue Exception => e
42
+ exit(1)
43
+ end
44
+
45
+ File.write("Makefile", "clean:\n\ttrue\ninstall:\n\ttrue")
46
+
47
+ exit(0)
data/icalPal.gemspec CHANGED
@@ -4,7 +4,7 @@ Gem::Specification.new do |s|
4
4
  s.name = ICalPal::NAME
5
5
  s.version = ICalPal::VERSION
6
6
 
7
- s.summary = 'Command-line tool to query the macOS Calendar'
7
+ s.summary = 'Command-line tool to query the macOS Calendar and Reminders'
8
8
  s.description = <<-EOF
9
9
  Inspired by icalBuddy and maintains close compatability. Includes
10
10
  many additional features for querying, filtering, and formatting.
@@ -20,30 +20,13 @@ EOF
20
20
  'rubygems_mfa_required' => 'true'
21
21
  }
22
22
 
23
- s.files = Dir["#{s.name}.gemspec", 'bin/*', 'lib/*.rb']
23
+ s.files = Dir["#{s.name}.gemspec", 'bin/*', 'ext/*.rb', 'lib/*.rb']
24
24
  s.executables = [ "#{s.name}" ]
25
25
  s.extra_rdoc_files = [ 'README.md' ]
26
26
 
27
- # The macOS and Homebrew versions of rubygems have incompatible
28
- # requirements for sqlite3.
29
- #
30
- # macOS comes with version 1.3.13, so it does not need to be added
31
- # as a dependency, but it cannot install anything newer:
32
- #
33
- # requires Ruby version >= 3.0, < 3.4.dev. The current ruby version is 2.6.10.
34
- #
35
- # Homebrew's Ruby formula does not come with sqlite3, so it does
36
- # need to be added as a dependency, but it cannot install version
37
- # 1.3.13:
38
- #
39
- # error: call to undeclared function
40
- #
41
- # So we must call add_dependency, but iff we are not building with
42
- # macOS' Ruby installation.
43
-
44
- s.add_dependency 'nokogiri-plist', '~> 0.5.0'
45
- s.add_dependency 'sqlite3', '~> 2.6.0' unless s.rubygems_version == `/usr/bin/gem --version`.strip
46
- s.add_dependency 'timezone', '>= 0.99', '~> 1.3.0'
27
+ # Some installation settings cannot be handled at build time.
28
+ # Handle everything at installation time.
29
+ s.extensions << 'ext/extconf.rb'
47
30
 
48
31
  s.bindir = 'bin'
49
32
  s.required_ruby_version = '>= 2.6.0'
data/lib/defaults.rb CHANGED
@@ -8,6 +8,7 @@ $defaults = {
8
8
  common: {
9
9
  ab: '!',
10
10
  aep: [],
11
+ atp: [],
11
12
  bullet: '•',
12
13
  cf: "#{Dir.home}/.icalpal",
13
14
  color: false,
@@ -19,6 +20,7 @@ $defaults = {
19
20
  df: '%b %-d, %Y',
20
21
  ec: [],
21
22
  eep: [],
23
+ etp: [],
22
24
  el: [],
23
25
  es: [],
24
26
  et: [],
@@ -43,26 +45,26 @@ $defaults = {
43
45
  tasks: {
44
46
  dated: 0,
45
47
  db: [ ICalPal::Reminder::DB_PATH ],
46
- iep: %w[ title notes due priority ],
48
+ itp: %w[ title notes due priority ],
47
49
  sort: 'prio',
48
50
  },
49
51
 
50
52
  undatedTasks: {
51
53
  dated: 1,
52
54
  db: [ ICalPal::Reminder::DB_PATH ],
53
- iep: %w[ title notes due priority ],
55
+ itp: %w[ title notes due priority ],
54
56
  sort: 'prio',
55
57
  },
56
58
 
57
59
  datedTasks: {
58
60
  dated: 2,
59
61
  db: [ ICalPal::Reminder::DB_PATH ],
60
- iep: %w[ title notes due priority ],
62
+ itp: %w[ title notes due priority ],
61
63
  sort: 'prio',
62
64
  },
63
65
 
64
66
  stores: {
65
- iep: %w[ account type ],
67
+ itp: %w[ account type ],
66
68
  sort: 'account',
67
69
  },
68
70
 
data/lib/event.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'timezone'
1
+ r 'timezone'
2
2
 
3
3
  module ICalPal
4
4
  # Class representing items from the <tt>CalendarItem</tt> table
@@ -13,8 +13,8 @@ module ICalPal
13
13
  def []=(k, v)
14
14
  @self[k] = v
15
15
 
16
- @self['sctime'] = Time.at(@self['sdate'].to_i, in: 'UTC') if k == 'sdate'
17
- @self['ectime'] = Time.at(@self['edate'].to_i, in: 'UTC') if k == 'edate'
16
+ @self['sctime'] = Time.at(@self['sdate'].to_i, in: '+00:00') if k == 'sdate'
17
+ @self['ectime'] = Time.at(@self['edate'].to_i, in: '+00:00') if k == 'edate'
18
18
  end
19
19
 
20
20
  # Standard accessor with special handling for +age+,
@@ -96,7 +96,7 @@ module ICalPal
96
96
  begin
97
97
  zone = Timezone.fetch(obj['start_tz'])
98
98
  rescue Timezone::Error::InvalidZone
99
- zone = 'UTC'
99
+ zone = '+00:00'
100
100
  end
101
101
 
102
102
  ctime = obj[k] + ITIME
@@ -177,7 +177,7 @@ module ICalPal
177
177
  skip = false
178
178
 
179
179
  changes[1..].each do |change|
180
- codate = Time.at(change['orig_date'] + ITIME).to_a[3..5].reverse
180
+ codate = Time.at(change['orig_date'] + ITIME, in: '+00:00').to_a[3..5].reverse
181
181
  odate = occurrence['sdate'].ymd
182
182
 
183
183
  skip = true if codate == odate
data/lib/icalPal.rb CHANGED
@@ -1,10 +1,4 @@
1
- require_relative 'EventKit'
2
- require_relative 'ToICalPal'
3
- require_relative 'calendar'
4
- require_relative 'event'
5
- require_relative 'rdt'
6
- require_relative 'reminder'
7
- require_relative 'store'
1
+ %w[ EventKit ToICalPal calendar event rdt reminder store ].each { |l| rr l }
8
2
 
9
3
  # Encapsulate the _Store_ (accounts), _Calendar_ and _CalendarItem_
10
4
  # tables of a Calendar database, and the _Reminder_ table of a
data/lib/options.rb CHANGED
@@ -42,6 +42,7 @@ module ICalPal
42
42
  @op.on('%s%s %sPrint events occurring today' % pad('eventsToday'))
43
43
  @op.on('%s%s %sPrint events occurring between today and NUM days into the future' % pad('eventsToday+NUM'))
44
44
  @op.on('%s%s %sPrint events occurring at present time' % pad('eventsNow'))
45
+ @op.on('%s%s %sPrint events occurring between present time and midnight' % pad('eventsRemaining'))
45
46
  @op.on('%s%s %sPrint tasks with a due date' % pad('datedTasks'))
46
47
  @op.on('%s%s %sPrint tasks with no due date' % pad('undatedTasks'))
47
48
 
@@ -238,10 +239,15 @@ module ICalPal
238
239
  cli[:cmd] = 'stores' if cli[:cmd] == 'accounts'
239
240
 
240
241
  # Parse eventsNow and eventsToday commands
241
- cli[:cmd].match('events(Now|Today)(\+[0-9]+)?') do |m|
242
+ cli[:cmd].match('events(Now|Today|Remaining)(\+[0-9]+)?') do |m|
242
243
  cli[:now] = true if m[1] == 'Now'
243
244
  cli[:days] = (m[1] == 'Today')? m[2].to_i : 1
244
245
 
246
+ if m[1] == 'Remaining'
247
+ cli[:n] = true
248
+ cli[:days] = 0
249
+ end
250
+
245
251
  cli[:from] = $today
246
252
  cli[:to] = $today + cli[:days] if cli[:days]
247
253
  cli[:days] = Integer(cli[:to] - cli[:from])
@@ -276,10 +282,9 @@ module ICalPal
276
282
  opts[:version] = @op.version
277
283
 
278
284
  # From the Department of Redundancy Department
279
- opts[:iep] += opts[:itp] if opts[:itp]
280
- opts[:eep] += opts[:etp] if opts[:etp]
281
- opts[:aep] += opts[:atp] if opts[:atp]
282
- opts[:props] = (opts[:iep] + opts[:aep] - opts[:eep]).uniq
285
+ (opts[:cmd].include? 'tasks')?
286
+ opts[:props] = (opts[:itp] + opts[:atp] - opts[:etp]).uniq :
287
+ opts[:props] = (opts[:iep] + opts[:aep] - opts[:eep]).uniq
283
288
 
284
289
  # From, to, days
285
290
  if opts[:from]
@@ -320,7 +325,7 @@ module ICalPal
320
325
  end
321
326
 
322
327
  # Commands that can be run
323
- COMMANDS = %w[events eventsToday eventsNow tasks datedTasks undatedTasks calendars accounts stores].freeze
328
+ COMMANDS = %w[events eventsToday eventsNow eventsRemaining tasks datedTasks undatedTasks calendars accounts stores].freeze
324
329
 
325
330
  # Supported output formats
326
331
  OUTFORMATS = %w[ansi csv default hash html json md rdoc remind toc xml yaml].freeze
data/lib/reminder.rb CHANGED
@@ -1,5 +1,5 @@
1
- require 'open3'
2
- require 'nokogiri-plist'
1
+ r 'open3'
2
+ r 'plist'
3
3
 
4
4
  module ICalPal
5
5
  # Class representing items from the <tt>Reminders</tt> database
@@ -9,7 +9,7 @@ module ICalPal
9
9
  def [](k)
10
10
  case k
11
11
  when 'notes' # Skip empty notes
12
- (@self['notes'].empty?)? @self['notes'] : nil
12
+ (@self['notes'].empty?)? nil : @self['notes']
13
13
 
14
14
  when 'priority' # Integer -> String
15
15
  EventKit::EKReminderProperty[@self['priority']] if @self['priority'].positive?
@@ -57,7 +57,7 @@ module ICalPal
57
57
  stdin.close
58
58
 
59
59
  # Read output
60
- plist = Nokogiri::PList(stdout.read)['$objects']
60
+ plist = Plist.parse_xml(stdout.read)['$objects']
61
61
 
62
62
  @self['color'] = plist[3]
63
63
  @self['symbolic_color_name'] = (plist[2] == 'custom')? plist[4] : plist[2]
data/lib/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module ICalPal
2
2
  NAME = 'icalPal'.freeze
3
- VERSION = '3.5.0'.freeze
3
+ VERSION = '3.6.1'.freeze
4
4
  end
metadata CHANGED
@@ -1,75 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: icalPal
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.5.0
4
+ version: 3.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Rosen
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-05-13 00:00:00.000000000 Z
11
- dependencies:
12
- - !ruby/object:Gem::Dependency
13
- name: nokogiri-plist
14
- requirement: !ruby/object:Gem::Requirement
15
- requirements:
16
- - - "~>"
17
- - !ruby/object:Gem::Version
18
- version: 0.5.0
19
- type: :runtime
20
- prerelease: false
21
- version_requirements: !ruby/object:Gem::Requirement
22
- requirements:
23
- - - "~>"
24
- - !ruby/object:Gem::Version
25
- version: 0.5.0
26
- - !ruby/object:Gem::Dependency
27
- name: sqlite3
28
- requirement: !ruby/object:Gem::Requirement
29
- requirements:
30
- - - "~>"
31
- - !ruby/object:Gem::Version
32
- version: 2.6.0
33
- type: :runtime
34
- prerelease: false
35
- version_requirements: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
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
10
+ date: 2025-05-20 00:00:00.000000000 Z
11
+ dependencies: []
60
12
  description: |
61
13
  Inspired by icalBuddy and maintains close compatability. Includes
62
14
  many additional features for querying, filtering, and formatting.
63
15
  email: ajr@corp.mlfs.org
64
16
  executables:
65
17
  - icalPal
66
- extensions: []
18
+ extensions:
19
+ - ext/extconf.rb
67
20
  extra_rdoc_files:
68
21
  - README.md
69
22
  files:
70
23
  - README.md
71
24
  - bin/icalPal
72
25
  - bin/icalpal
26
+ - ext/extconf.rb
73
27
  - icalPal.gemspec
74
28
  - lib/EventKit.rb
75
29
  - lib/ToICalPal.rb
@@ -110,6 +64,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
64
  requirements: []
111
65
  rubygems_version: 3.6.6
112
66
  specification_version: 4
113
- summary: Command-line tool to query the macOS Calendar
67
+ summary: Command-line tool to query the macOS Calendar and Reminders
114
68
  test_files: []
115
69
  ...