terminal-notifier 1.8.0 → 3.0.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 +5 -5
- data/LICENSE +24 -0
- data/README.markdown +57 -6
- data/bin/terminal-notifier +4 -9
- data/lib/terminal-notifier/cli.rb +21 -0
- data/lib/terminal-notifier/version.rb +10 -0
- data/lib/terminal-notifier.rb +205 -38
- data/vendor/terminal-notifier/terminal-notifier.app/Contents/Info.plist +34 -0
- data/vendor/terminal-notifier/terminal-notifier.app/Contents/MacOS/terminal-notifier +0 -0
- data/vendor/terminal-notifier/terminal-notifier.app/Contents/PkgInfo +1 -0
- data/vendor/terminal-notifier/terminal-notifier.app/Contents/Resources/Terminal.icns +0 -0
- data/vendor/terminal-notifier/terminal-notifier.app/Contents/Resources/en.lproj/InfoPlist.strings +2 -0
- data/vendor/terminal-notifier/terminal-notifier.app/Contents/_CodeSignature/CodeResources +146 -0
- metadata +23 -55
- data/vendor/terminal-notifier +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 78c9a9b889e4da2b6154981a05925abdbc29f29c50591d233e599b0de4cdff08
|
|
4
|
+
data.tar.gz: 07c78da6932247a170a8b30289f7720089f82a1fd7120f769164295be777abdc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 94d37dc8ec053c61311c09931d7ab5d6a37922669fcf355d1a2569d86f0afc7ff913200e977e21d933329d4aaeb56b6e84bbdabe718694e9d8fc8f917e936976
|
|
7
|
+
data.tar.gz: 3552e9814c3a24a63e898d3aaab4c6bbf12c8231d0ab55dfade43db566605dc9f1e18f053c85f2251f90b4c37e6d0bcf3b42d27c4a6bbb90fdc24388235464db
|
data/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
All the works are available under the MIT license. **Except** for
|
|
2
|
+
‘Terminal.icns’, which is a copy of Apple’s Terminal.app icon and as such is
|
|
3
|
+
copyright of Apple.
|
|
4
|
+
|
|
5
|
+
Copyright (C) 2012-2013 Eloy Durán <eloy.de.enige@gmail.com>, Julien Blanchard
|
|
6
|
+
<julien@sideburns.eu>
|
|
7
|
+
|
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
9
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
10
|
+
the Software without restriction, including without limitation the rights to
|
|
11
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
12
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
|
13
|
+
so, subject to the following conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be included in all
|
|
16
|
+
copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
+
SOFTWARE.
|
data/README.markdown
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
A simple Ruby wrapper around the [`terminal-notifier`][HOMEPAGE] command-line
|
|
4
4
|
tool, which allows you to send User Notifications to the Notification Center on
|
|
5
|
-
|
|
5
|
+
macOS 10.14, or higher.
|
|
6
|
+
|
|
7
|
+
Requires Ruby 3.2 or newer.
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
## Installation
|
|
@@ -22,11 +24,11 @@ Examples are:
|
|
|
22
24
|
TerminalNotifier.notify('Hello World')
|
|
23
25
|
TerminalNotifier.notify('Hello World', :title => 'Ruby', :subtitle => 'Programming Language')
|
|
24
26
|
TerminalNotifier.notify('Hello World', :activate => 'com.apple.Safari')
|
|
25
|
-
TerminalNotifier.notify('Hello World', :open => 'http://twitter.com/
|
|
27
|
+
TerminalNotifier.notify('Hello World', :open => 'http://twitter.com/julienXX')
|
|
26
28
|
TerminalNotifier.notify('Hello World', :execute => 'say "OMG"')
|
|
27
29
|
TerminalNotifier.notify('Hello World', :group => Process.pid)
|
|
28
|
-
TerminalNotifier.notify('Hello World', :sender => 'com.apple.Safari')
|
|
29
30
|
TerminalNotifier.notify('Hello World', :sound => 'default')
|
|
31
|
+
TerminalNotifier.notify('Hello World', :contentImage => './logo.png')
|
|
30
32
|
|
|
31
33
|
TerminalNotifier.remove(Process.pid)
|
|
32
34
|
|
|
@@ -34,6 +36,55 @@ TerminalNotifier.list(Process.pid)
|
|
|
34
36
|
TerminalNotifier.list
|
|
35
37
|
```
|
|
36
38
|
|
|
39
|
+
`:sender` and `:appIcon` were removed in 3.0.0. They are still accepted, but the
|
|
40
|
+
tool ignores them and warns on stderr — see the main [README][README].
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
## Asking a question
|
|
44
|
+
|
|
45
|
+
`:action` and `:reply` wait for the user and return what they chose. An option
|
|
46
|
+
whose value is `true` is passed as a bare flag.
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
TerminalNotifier.notify('Deploy to production?', :action => 'Yes,No', :timeout => 30)
|
|
50
|
+
#=> :yes (or :no, :_actionclicked, :_closed, :_timeout)
|
|
51
|
+
|
|
52
|
+
TerminalNotifier.notify("What's your name?", :reply => true, :timeout => 30)
|
|
53
|
+
#=> "Alice" (a String, because :reply was given)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Action results come back symbolised by `notify_result`; a `:reply` result is
|
|
57
|
+
returned as the raw string.
|
|
58
|
+
|
|
59
|
+
A timeout returns `:_timeout` rather than `false`, so it can be told apart from
|
|
60
|
+
the notification failing to send — which is what `false` means.
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
## Return values
|
|
64
|
+
|
|
65
|
+
`notify` and `remove` return whether the command succeeded. `list` returns a
|
|
66
|
+
hash (or an array of hashes for the default `'ALL'` group) with the keys
|
|
67
|
+
`:group`, `:title`, `:subtitle`, `:message` and `:delivered_at`; absent fields
|
|
68
|
+
are `nil`. It returns `nil` when there is nothing to report.
|
|
69
|
+
|
|
70
|
+
Both raise `TerminalNotifier::UnsupportedPlatformError` when run on anything
|
|
71
|
+
other than a supported macOS, and `TerminalNotifier::BinaryNotFoundError` when
|
|
72
|
+
the bundled binary is missing.
|
|
73
|
+
|
|
74
|
+
Set `TERMINAL_NOTIFIER_BIN` to use a binary other than the bundled one.
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
## Development
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
$ cd Ruby
|
|
81
|
+
$ bundle install
|
|
82
|
+
$ bundle exec rspec
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
One example needs the compiled application bundle and is skipped without it.
|
|
86
|
+
Build and vendor it with `bundle exec rake update_build`, which requires Xcode.
|
|
87
|
+
|
|
37
88
|
|
|
38
89
|
## License
|
|
39
90
|
|
|
@@ -43,6 +94,6 @@ copyright of Apple.
|
|
|
43
94
|
|
|
44
95
|
See [LICENSE][LICENSE] for details.
|
|
45
96
|
|
|
46
|
-
[HOMEPAGE]: https://github.com/
|
|
47
|
-
[README]: https://github.com/
|
|
48
|
-
[LICENSE]: https://github.com/
|
|
97
|
+
[HOMEPAGE]: https://github.com/julienXX/terminal-notifier
|
|
98
|
+
[README]: https://github.com/julienXX/terminal-notifier/blob/master/README.markdown
|
|
99
|
+
[LICENSE]: https://github.com/julienXX/terminal-notifier/blob/master/Ruby/LICENSE
|
data/bin/terminal-notifier
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
|
-
if $
|
|
4
|
-
$:.unshift File.expand_path('../../lib', __FILE__)
|
|
5
|
-
end
|
|
4
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __dir__) if $PROGRAM_NAME == __FILE__
|
|
6
5
|
|
|
7
|
-
require 'terminal-notifier'
|
|
6
|
+
require 'terminal-notifier/cli'
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
ARGV.push(*["-message", STDIN.read.chomp])
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
exec TerminalNotifier::BIN_PATH, *ARGV
|
|
8
|
+
TerminalNotifier::CLI.run
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'terminal-notifier'
|
|
4
|
+
|
|
5
|
+
module TerminalNotifier
|
|
6
|
+
# The bin wrapper's logic, extracted so that it can be tested without
|
|
7
|
+
# spawning a process.
|
|
8
|
+
module CLI
|
|
9
|
+
# Folds piped stdin into a -message option, matching the behaviour of the
|
|
10
|
+
# binary itself when data is piped to it directly.
|
|
11
|
+
def self.argv_for(argv, stdin)
|
|
12
|
+
return argv if argv.include?('-message') || stdin.tty?
|
|
13
|
+
|
|
14
|
+
argv + ['-message', stdin.read.chomp]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.run(argv = ARGV, stdin = $stdin)
|
|
18
|
+
exec TerminalNotifier::BIN_PATH, *argv_for(argv, stdin)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TerminalNotifier
|
|
4
|
+
# The version of this gem, which tracks the version of the bundled
|
|
5
|
+
# terminal-notifier binary.
|
|
6
|
+
#
|
|
7
|
+
# Note: this is *not* TerminalNotifier.version, which returns the macOS
|
|
8
|
+
# product version the tool is running on.
|
|
9
|
+
VERSION = '3.0.0'
|
|
10
|
+
end
|
data/lib/terminal-notifier.rb
CHANGED
|
@@ -1,42 +1,192 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
3
|
require 'rbconfig'
|
|
4
|
+
require 'shellwords'
|
|
5
|
+
require 'time'
|
|
6
|
+
|
|
7
|
+
require 'terminal-notifier/version'
|
|
4
8
|
|
|
9
|
+
# Sends macOS User Notifications by shelling out to the bundled
|
|
10
|
+
# terminal-notifier application.
|
|
11
|
+
#
|
|
12
|
+
# See TerminalNotifier.notify, .remove and .list for the public API.
|
|
5
13
|
module TerminalNotifier
|
|
6
|
-
|
|
14
|
+
# Minimum macOS version supported by the bundled binary. UNUserNotificationCenter,
|
|
15
|
+
# which the tool is built on, is not available before this.
|
|
16
|
+
MINIMUM_MACOS_VERSION = '10.14'
|
|
17
|
+
|
|
18
|
+
# Exit code the binary uses when -timeout expires waiting for -action or
|
|
19
|
+
# -reply. The notification was delivered correctly and the tool reported
|
|
20
|
+
# @TIMEOUT, so this is an outcome to pass on rather than a failure.
|
|
21
|
+
TIMEOUT_EXIT_CODE = 6
|
|
22
|
+
|
|
23
|
+
# Path to the binary inside the vendored application bundle. Overridable so
|
|
24
|
+
# that a Homebrew-installed or self-built copy can be used instead.
|
|
25
|
+
BIN_PATH = ENV.fetch(
|
|
26
|
+
'TERMINAL_NOTIFIER_BIN',
|
|
27
|
+
File.expand_path(
|
|
28
|
+
'../vendor/terminal-notifier/terminal-notifier.app/Contents/MacOS/terminal-notifier',
|
|
29
|
+
__dir__
|
|
30
|
+
)
|
|
31
|
+
)
|
|
7
32
|
|
|
8
33
|
class UnsupportedPlatformError < StandardError; end
|
|
9
|
-
|
|
34
|
+
class BinaryNotFoundError < StandardError; end
|
|
35
|
+
|
|
36
|
+
# Returns whether the current platform is macOS 10.14 or higher.
|
|
10
37
|
def self.available?
|
|
11
|
-
|
|
38
|
+
# Memoise with defined? rather than ||=, so that a false result is cached
|
|
39
|
+
# too and we don't re-shell out on every single call.
|
|
40
|
+
return @available if defined?(@available)
|
|
41
|
+
|
|
42
|
+
@available = macos? && Gem::Version.new(version) >= Gem::Version.new(MINIMUM_MACOS_VERSION)
|
|
12
43
|
end
|
|
13
44
|
|
|
45
|
+
# The macOS product version, or nil when not running on macOS.
|
|
14
46
|
def self.version
|
|
15
|
-
@version
|
|
47
|
+
return @version if defined?(@version)
|
|
48
|
+
|
|
49
|
+
# Only shell out when we already know this is macOS. RbConfig reports the
|
|
50
|
+
# Darwin kernel version, which doesn't map cleanly onto product versions,
|
|
51
|
+
# so sw_vers is still needed for the number itself.
|
|
52
|
+
@version = macos? ? `sw_vers -productVersion`.strip : nil
|
|
16
53
|
end
|
|
17
54
|
|
|
18
|
-
def self.
|
|
19
|
-
if
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
55
|
+
def self.macos?
|
|
56
|
+
return @macos if defined?(@macos)
|
|
57
|
+
|
|
58
|
+
@macos = !(RbConfig::CONFIG['host_os'] =~ /darwin|mac os/).nil?
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Builds the argument vector for the binary.
|
|
62
|
+
#
|
|
63
|
+
# A value of `true` becomes a bare flag and `false` omits the option entirely,
|
|
64
|
+
# so switches like :reply and :ignoreDnD don't end up with a stray "true" as
|
|
65
|
+
# their value (which -reply would show as its placeholder text).
|
|
66
|
+
def self.command_for(options)
|
|
67
|
+
arguments = options.flat_map do |key, value|
|
|
68
|
+
case value
|
|
69
|
+
when true then ["-#{key}"]
|
|
70
|
+
when false, nil then []
|
|
71
|
+
else ["-#{key}", escape_value(value.to_s)]
|
|
27
72
|
end
|
|
73
|
+
end
|
|
74
|
+
[BIN_PATH, *arguments]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Prepares a single option value for the binary.
|
|
78
|
+
#
|
|
79
|
+
# This is *not* shell escaping — IO.popen is handed an argv array, so no shell
|
|
80
|
+
# is ever involved. It is the escaping the tool's own README documents as
|
|
81
|
+
# ‘\[’: the binary reads its arguments through NSUserDefaults, which tries to
|
|
82
|
+
# parse each value as a property list, so a value beginning with '[', '(',
|
|
83
|
+
# '{', a quote, a space and so on comes back as nil and the notification is
|
|
84
|
+
# never sent. Prefixing a backslash makes NSUserDefaults treat it as a plain
|
|
85
|
+
# string, and the binary strips that backslash again (see
|
|
86
|
+
# objectForKeyedSubscript: in AppDelegate.m).
|
|
87
|
+
#
|
|
88
|
+
# Shellwords.escape is used purely as a convenient test of "would this
|
|
89
|
+
# character be taken as syntax", which is the same set that matters here.
|
|
90
|
+
def self.escape_value(value)
|
|
91
|
+
return value if value.empty?
|
|
92
|
+
|
|
93
|
+
# A value starting with '-' would be read as the next flag; the binary
|
|
94
|
+
# strips this leading space back off.
|
|
95
|
+
prefix = value.start_with?('-') ? ' ' : ''
|
|
96
|
+
"#{prefix}#{Shellwords.escape(value[0, 1])}#{value[1..]}"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Runs the binary and returns its standard output.
|
|
100
|
+
#
|
|
101
|
+
# Raises UnsupportedPlatformError when not on a supported macOS, and
|
|
102
|
+
# BinaryNotFoundError when the vendored binary is missing.
|
|
103
|
+
def self.execute(verbose, options)
|
|
104
|
+
ensure_usable!
|
|
105
|
+
|
|
106
|
+
output = IO.popen(command_for(options), &:read)
|
|
107
|
+
# Remember the status so callers aren't exposed to races on the global $?.
|
|
108
|
+
Thread.current[:terminal_notifier_last_status] = $?
|
|
109
|
+
$stdout.print output if verbose
|
|
110
|
+
output
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Raises unless this platform and installation can actually run the binary.
|
|
114
|
+
def self.ensure_usable!
|
|
115
|
+
unless available?
|
|
116
|
+
raise UnsupportedPlatformError,
|
|
117
|
+
"terminal-notifier is only supported on macOS #{MINIMUM_MACOS_VERSION} or higher."
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
return if File.executable?(BIN_PATH)
|
|
121
|
+
|
|
122
|
+
raise BinaryNotFoundError,
|
|
123
|
+
"terminal-notifier binary not found at #{BIN_PATH}. " \
|
|
124
|
+
'Set TERMINAL_NOTIFIER_BIN to point at it.'
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# The exit status of the most recent execute call on this thread.
|
|
128
|
+
def self.last_status
|
|
129
|
+
Thread.current[:terminal_notifier_last_status]
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def self.succeeded?
|
|
133
|
+
status = last_status
|
|
134
|
+
!status.nil? && status.success?
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# True when the binary ran and reported an outcome, including a timeout.
|
|
138
|
+
def self.reported?
|
|
139
|
+
status = last_status
|
|
140
|
+
return false if status.nil?
|
|
141
|
+
|
|
142
|
+
status.success? || status.exitstatus == TIMEOUT_EXIT_CODE
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Cleans up the result of a notification, making it easier to work it
|
|
146
|
+
#
|
|
147
|
+
# The result of a notification is downcased, then groups of 1 or more
|
|
148
|
+
# non-word characters are replaced with an underscore, before being
|
|
149
|
+
# symbolised.
|
|
150
|
+
#
|
|
151
|
+
# If the reply option was given, then instead of going through the
|
|
152
|
+
# above process, the result is returned with no changes as a string.
|
|
153
|
+
#
|
|
154
|
+
# If the always_string param is set to true, a the result is returned
|
|
155
|
+
# with no changes as a string, like above.
|
|
156
|
+
#
|
|
157
|
+
# Examples are:
|
|
158
|
+
#
|
|
159
|
+
# notify_result('Test', {}) #=> :test
|
|
160
|
+
# notify_result('No, sir', {}) #=> :no_sir
|
|
161
|
+
# notify_result('@timeout', {}) #=> :_timeout
|
|
162
|
+
# notify_result('@closeaction', {}) #=> :_closeaction
|
|
163
|
+
# notify_result('I like pie', {reply: true}) #=> 'I like pie'
|
|
164
|
+
# notify_result('I do not like pie', {'reply' => true}) #=> 'I do not like pie'
|
|
165
|
+
# notify_result('@timeout', {'reply' => true}) #=> '@timeout'
|
|
166
|
+
# notify_result('I may like pie', {}) #=> :i_may_like_pie
|
|
167
|
+
def notify_result(result, options, always_string = false)
|
|
168
|
+
# The binary terminates its response with a newline. Left on, a reply comes
|
|
169
|
+
# back as "text\n" and an action title symbolises to :title_ because the
|
|
170
|
+
# newline is a non-word character.
|
|
171
|
+
result = result.to_s.chomp
|
|
172
|
+
|
|
173
|
+
if options[:reply] || options['reply'] || always_string
|
|
28
174
|
result
|
|
29
175
|
else
|
|
30
|
-
|
|
176
|
+
# NOTE: an empty result yields `true`, not a symbol, because the `||`
|
|
177
|
+
# short-circuits. Odd, but it is the long-standing public contract.
|
|
178
|
+
result.empty? || result.downcase.gsub(/\W+/, '_').to_sym
|
|
31
179
|
end
|
|
32
180
|
end
|
|
181
|
+
module_function :notify_result
|
|
33
182
|
|
|
34
183
|
# Sends a User Notification and returns whether or not it was a success.
|
|
35
184
|
#
|
|
36
|
-
# The available options are `:title`, `:
|
|
37
|
-
# `:execute`, `:
|
|
185
|
+
# The available options are `:title`, `:subtitle`, `:group`, `:activate`,
|
|
186
|
+
# `:open`, `:execute`, `:contentImage`, and `:sound`. For a description of
|
|
187
|
+
# each option see:
|
|
38
188
|
#
|
|
39
|
-
# https://github.com/
|
|
189
|
+
# https://github.com/julienXX/terminal-notifier/blob/master/README.markdown
|
|
40
190
|
#
|
|
41
191
|
# Examples are:
|
|
42
192
|
#
|
|
@@ -44,15 +194,16 @@ module TerminalNotifier
|
|
|
44
194
|
# TerminalNotifier.notify('Hello World', :title => 'Ruby')
|
|
45
195
|
# TerminalNotifier.notify('Hello World', :group => Process.pid)
|
|
46
196
|
# TerminalNotifier.notify('Hello World', :activate => 'com.apple.Safari')
|
|
47
|
-
# TerminalNotifier.notify('Hello World', :open => 'http://twitter.com/
|
|
197
|
+
# TerminalNotifier.notify('Hello World', :open => 'http://twitter.com/julienXX')
|
|
48
198
|
# TerminalNotifier.notify('Hello World', :execute => 'say "OMG"')
|
|
49
|
-
# TerminalNotifier.notify('Hello World', :sender => 'com.apple.Safari')
|
|
50
199
|
# TerminalNotifier.notify('Hello World', :sound => 'default')
|
|
51
200
|
#
|
|
52
|
-
# Raises if not supported on the current platform.
|
|
53
|
-
def notify(message, options = {}, verbose = false)
|
|
54
|
-
TerminalNotifier.execute(verbose, options.merge(:
|
|
55
|
-
|
|
201
|
+
# Raises UnsupportedPlatformError if not supported on the current platform.
|
|
202
|
+
def notify(message, options = {}, verbose = false, always_string = false)
|
|
203
|
+
result = TerminalNotifier.execute(verbose, options.merge(message: message))
|
|
204
|
+
# A timeout counts as a reported outcome: without this it would come back as
|
|
205
|
+
# a bare false, indistinguishable from the notification failing to send.
|
|
206
|
+
TerminalNotifier.reported? && notify_result(result, options, always_string)
|
|
56
207
|
end
|
|
57
208
|
module_function :notify
|
|
58
209
|
|
|
@@ -60,13 +211,15 @@ module TerminalNotifier
|
|
|
60
211
|
# ‘group’ ID, if one exists.
|
|
61
212
|
#
|
|
62
213
|
# If no ‘group’ ID is given, all notifications are removed.
|
|
214
|
+
# rubocop:disable Naming/PredicateMethod -- `remove` is the public API name
|
|
63
215
|
def remove(group = 'ALL', verbose = false)
|
|
64
|
-
TerminalNotifier.execute(verbose, :
|
|
65
|
-
|
|
216
|
+
TerminalNotifier.execute(verbose, remove: group)
|
|
217
|
+
TerminalNotifier.succeeded?
|
|
66
218
|
end
|
|
219
|
+
# rubocop:enable Naming/PredicateMethod
|
|
67
220
|
module_function :remove
|
|
68
221
|
|
|
69
|
-
LIST_FIELDS = [
|
|
222
|
+
LIST_FIELDS = %i[group title subtitle message delivered_at].freeze
|
|
70
223
|
|
|
71
224
|
# If a ‘group’ ID is given, and a notification for that group exists,
|
|
72
225
|
# returns a hash with details about the notification.
|
|
@@ -76,18 +229,32 @@ module TerminalNotifier
|
|
|
76
229
|
#
|
|
77
230
|
# If no information is available this will return `nil`.
|
|
78
231
|
def list(group = 'ALL', verbose = false)
|
|
79
|
-
output = TerminalNotifier.execute(verbose, :
|
|
80
|
-
return if output.strip.empty?
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
notifications = output.split("\n")[1
|
|
84
|
-
LIST_FIELDS.zip(line.split("\t")).inject({}) do |hash, (key, value)|
|
|
85
|
-
hash[key] = key == :delivered_at ? Time.parse(value) : (value unless value == '(null)')
|
|
86
|
-
hash
|
|
87
|
-
end
|
|
88
|
-
end
|
|
232
|
+
output = TerminalNotifier.execute(verbose, list: group)
|
|
233
|
+
return if output.nil? || output.strip.empty?
|
|
234
|
+
|
|
235
|
+
# Drop the header row.
|
|
236
|
+
notifications = output.split("\n")[1..].to_a.map { |line| TerminalNotifier.parse_list_row(line) }
|
|
89
237
|
|
|
90
238
|
group == 'ALL' ? notifications : notifications.first
|
|
91
239
|
end
|
|
92
240
|
module_function :list
|
|
241
|
+
|
|
242
|
+
# Turns one tab-separated -list row into a hash.
|
|
243
|
+
def self.parse_list_row(line)
|
|
244
|
+
LIST_FIELDS.zip(line.split("\t")).each_with_object({}) do |(key, value), hash|
|
|
245
|
+
hash[key] = key == :delivered_at ? parse_time(value) : presence(value)
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def self.parse_time(value)
|
|
250
|
+
Time.parse(value.to_s)
|
|
251
|
+
rescue ArgumentError, TypeError
|
|
252
|
+
nil
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
# 3.0.0 emits an empty field for an absent value; earlier binaries emitted the
|
|
256
|
+
# literal string "(null)".
|
|
257
|
+
def self.presence(value)
|
|
258
|
+
value unless value.nil? || value.empty? || value == '(null)'
|
|
259
|
+
end
|
|
93
260
|
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>CFBundleDevelopmentRegion</key>
|
|
6
|
+
<string>en</string>
|
|
7
|
+
<key>CFBundleExecutable</key>
|
|
8
|
+
<string>terminal-notifier</string>
|
|
9
|
+
<key>CFBundleIconFile</key>
|
|
10
|
+
<string>Terminal</string>
|
|
11
|
+
<key>CFBundleIdentifier</key>
|
|
12
|
+
<string>fr.julienxx.oss.terminal-notifier</string>
|
|
13
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
|
14
|
+
<string>6.0</string>
|
|
15
|
+
<key>CFBundleName</key>
|
|
16
|
+
<string>terminal-notifier</string>
|
|
17
|
+
<key>CFBundlePackageType</key>
|
|
18
|
+
<string>APPL</string>
|
|
19
|
+
<key>CFBundleShortVersionString</key>
|
|
20
|
+
<string>3.0.0</string>
|
|
21
|
+
<key>CFBundleSignature</key>
|
|
22
|
+
<string>????</string>
|
|
23
|
+
<key>CFBundleVersion</key>
|
|
24
|
+
<string>16</string>
|
|
25
|
+
<key>LSMinimumSystemVersion</key>
|
|
26
|
+
<string>10.14</string>
|
|
27
|
+
<key>LSUIElement</key>
|
|
28
|
+
<true/>
|
|
29
|
+
<key>NSHumanReadableCopyright</key>
|
|
30
|
+
<string>Copyright © 2012-2017 Eloy Durán, Julien Blanchard. All rights reserved.</string>
|
|
31
|
+
<key>NSPrincipalClass</key>
|
|
32
|
+
<string>NSApplication</string>
|
|
33
|
+
</dict>
|
|
34
|
+
</plist>
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
APPL????
|
|
Binary file
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>files</key>
|
|
6
|
+
<dict>
|
|
7
|
+
<key>Resources/Terminal.icns</key>
|
|
8
|
+
<data>
|
|
9
|
+
Oq9GtJM1DqcGF1JCHiEgb0hoN6I=
|
|
10
|
+
</data>
|
|
11
|
+
<key>Resources/en.lproj/InfoPlist.strings</key>
|
|
12
|
+
<dict>
|
|
13
|
+
<key>hash</key>
|
|
14
|
+
<data>
|
|
15
|
+
j6qg+qbNaStgLrdDQMdUxznV6qM=
|
|
16
|
+
</data>
|
|
17
|
+
<key>optional</key>
|
|
18
|
+
<true/>
|
|
19
|
+
</dict>
|
|
20
|
+
</dict>
|
|
21
|
+
<key>files2</key>
|
|
22
|
+
<dict>
|
|
23
|
+
<key>Resources/Terminal.icns</key>
|
|
24
|
+
<dict>
|
|
25
|
+
<key>hash2</key>
|
|
26
|
+
<data>
|
|
27
|
+
zPwPRX277SsWSp9wjhoAAPrY+Jaw1TMrN24rdI8/9SU=
|
|
28
|
+
</data>
|
|
29
|
+
</dict>
|
|
30
|
+
<key>Resources/en.lproj/InfoPlist.strings</key>
|
|
31
|
+
<dict>
|
|
32
|
+
<key>hash2</key>
|
|
33
|
+
<data>
|
|
34
|
+
/rXoINaO0x+HHSva+NFJNe00OnqHXd13TVVW2o39lRo=
|
|
35
|
+
</data>
|
|
36
|
+
<key>optional</key>
|
|
37
|
+
<true/>
|
|
38
|
+
</dict>
|
|
39
|
+
</dict>
|
|
40
|
+
<key>rules</key>
|
|
41
|
+
<dict>
|
|
42
|
+
<key>^Resources/</key>
|
|
43
|
+
<true/>
|
|
44
|
+
<key>^Resources/.*\.lproj/</key>
|
|
45
|
+
<dict>
|
|
46
|
+
<key>optional</key>
|
|
47
|
+
<true/>
|
|
48
|
+
<key>weight</key>
|
|
49
|
+
<real>1000</real>
|
|
50
|
+
</dict>
|
|
51
|
+
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
|
52
|
+
<dict>
|
|
53
|
+
<key>omit</key>
|
|
54
|
+
<true/>
|
|
55
|
+
<key>weight</key>
|
|
56
|
+
<real>1100</real>
|
|
57
|
+
</dict>
|
|
58
|
+
<key>^Resources/Base\.lproj/</key>
|
|
59
|
+
<dict>
|
|
60
|
+
<key>weight</key>
|
|
61
|
+
<real>1010</real>
|
|
62
|
+
</dict>
|
|
63
|
+
<key>^version.plist$</key>
|
|
64
|
+
<true/>
|
|
65
|
+
</dict>
|
|
66
|
+
<key>rules2</key>
|
|
67
|
+
<dict>
|
|
68
|
+
<key>.*\.dSYM($|/)</key>
|
|
69
|
+
<dict>
|
|
70
|
+
<key>weight</key>
|
|
71
|
+
<real>11</real>
|
|
72
|
+
</dict>
|
|
73
|
+
<key>^(.*/)?\.DS_Store$</key>
|
|
74
|
+
<dict>
|
|
75
|
+
<key>omit</key>
|
|
76
|
+
<true/>
|
|
77
|
+
<key>weight</key>
|
|
78
|
+
<real>2000</real>
|
|
79
|
+
</dict>
|
|
80
|
+
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
|
|
81
|
+
<dict>
|
|
82
|
+
<key>nested</key>
|
|
83
|
+
<true/>
|
|
84
|
+
<key>weight</key>
|
|
85
|
+
<real>10</real>
|
|
86
|
+
</dict>
|
|
87
|
+
<key>^.*</key>
|
|
88
|
+
<true/>
|
|
89
|
+
<key>^Info\.plist$</key>
|
|
90
|
+
<dict>
|
|
91
|
+
<key>omit</key>
|
|
92
|
+
<true/>
|
|
93
|
+
<key>weight</key>
|
|
94
|
+
<real>20</real>
|
|
95
|
+
</dict>
|
|
96
|
+
<key>^PkgInfo$</key>
|
|
97
|
+
<dict>
|
|
98
|
+
<key>omit</key>
|
|
99
|
+
<true/>
|
|
100
|
+
<key>weight</key>
|
|
101
|
+
<real>20</real>
|
|
102
|
+
</dict>
|
|
103
|
+
<key>^Resources/</key>
|
|
104
|
+
<dict>
|
|
105
|
+
<key>weight</key>
|
|
106
|
+
<real>20</real>
|
|
107
|
+
</dict>
|
|
108
|
+
<key>^Resources/.*\.lproj/</key>
|
|
109
|
+
<dict>
|
|
110
|
+
<key>optional</key>
|
|
111
|
+
<true/>
|
|
112
|
+
<key>weight</key>
|
|
113
|
+
<real>1000</real>
|
|
114
|
+
</dict>
|
|
115
|
+
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
|
116
|
+
<dict>
|
|
117
|
+
<key>omit</key>
|
|
118
|
+
<true/>
|
|
119
|
+
<key>weight</key>
|
|
120
|
+
<real>1100</real>
|
|
121
|
+
</dict>
|
|
122
|
+
<key>^Resources/Base\.lproj/</key>
|
|
123
|
+
<dict>
|
|
124
|
+
<key>weight</key>
|
|
125
|
+
<real>1010</real>
|
|
126
|
+
</dict>
|
|
127
|
+
<key>^[^/]+$</key>
|
|
128
|
+
<dict>
|
|
129
|
+
<key>nested</key>
|
|
130
|
+
<true/>
|
|
131
|
+
<key>weight</key>
|
|
132
|
+
<real>10</real>
|
|
133
|
+
</dict>
|
|
134
|
+
<key>^embedded\.provisionprofile$</key>
|
|
135
|
+
<dict>
|
|
136
|
+
<key>weight</key>
|
|
137
|
+
<real>20</real>
|
|
138
|
+
</dict>
|
|
139
|
+
<key>^version\.plist$</key>
|
|
140
|
+
<dict>
|
|
141
|
+
<key>weight</key>
|
|
142
|
+
<real>20</real>
|
|
143
|
+
</dict>
|
|
144
|
+
</dict>
|
|
145
|
+
</dict>
|
|
146
|
+
</plist>
|
metadata
CHANGED
|
@@ -1,59 +1,19 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: terminal-notifier
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Eloy Duran
|
|
8
8
|
- Julien Blanchard
|
|
9
|
-
autorequire:
|
|
10
9
|
bindir: bin
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date:
|
|
13
|
-
dependencies:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
- - ">="
|
|
19
|
-
- !ruby/object:Gem::Version
|
|
20
|
-
version: '0'
|
|
21
|
-
type: :development
|
|
22
|
-
prerelease: false
|
|
23
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
24
|
-
requirements:
|
|
25
|
-
- - ">="
|
|
26
|
-
- !ruby/object:Gem::Version
|
|
27
|
-
version: '0'
|
|
28
|
-
- !ruby/object:Gem::Dependency
|
|
29
|
-
name: mocha
|
|
30
|
-
requirement: !ruby/object:Gem::Requirement
|
|
31
|
-
requirements:
|
|
32
|
-
- - ">="
|
|
33
|
-
- !ruby/object:Gem::Version
|
|
34
|
-
version: '0'
|
|
35
|
-
type: :development
|
|
36
|
-
prerelease: false
|
|
37
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
38
|
-
requirements:
|
|
39
|
-
- - ">="
|
|
40
|
-
- !ruby/object:Gem::Version
|
|
41
|
-
version: '0'
|
|
42
|
-
- !ruby/object:Gem::Dependency
|
|
43
|
-
name: mocha-on-bacon
|
|
44
|
-
requirement: !ruby/object:Gem::Requirement
|
|
45
|
-
requirements:
|
|
46
|
-
- - ">="
|
|
47
|
-
- !ruby/object:Gem::Version
|
|
48
|
-
version: '0'
|
|
49
|
-
type: :development
|
|
50
|
-
prerelease: false
|
|
51
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
52
|
-
requirements:
|
|
53
|
-
- - ">="
|
|
54
|
-
- !ruby/object:Gem::Version
|
|
55
|
-
version: '0'
|
|
56
|
-
description:
|
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: |
|
|
14
|
+
terminal-notifier is a command-line tool to send macOS User Notifications.
|
|
15
|
+
This gem wraps the tool and ships the application bundle it needs, so that
|
|
16
|
+
notifications can be posted from Ruby without any extra installation.
|
|
57
17
|
email:
|
|
58
18
|
- eloy.de.enige@gmail.com
|
|
59
19
|
- julien@sideburns.eu
|
|
@@ -63,15 +23,25 @@ extensions: []
|
|
|
63
23
|
extra_rdoc_files:
|
|
64
24
|
- README.markdown
|
|
65
25
|
files:
|
|
26
|
+
- LICENSE
|
|
66
27
|
- README.markdown
|
|
67
28
|
- bin/terminal-notifier
|
|
68
29
|
- lib/terminal-notifier.rb
|
|
69
|
-
-
|
|
30
|
+
- lib/terminal-notifier/cli.rb
|
|
31
|
+
- lib/terminal-notifier/version.rb
|
|
32
|
+
- vendor/terminal-notifier/terminal-notifier.app/Contents/Info.plist
|
|
33
|
+
- vendor/terminal-notifier/terminal-notifier.app/Contents/MacOS/terminal-notifier
|
|
34
|
+
- vendor/terminal-notifier/terminal-notifier.app/Contents/PkgInfo
|
|
35
|
+
- vendor/terminal-notifier/terminal-notifier.app/Contents/Resources/Terminal.icns
|
|
36
|
+
- vendor/terminal-notifier/terminal-notifier.app/Contents/Resources/en.lproj/InfoPlist.strings
|
|
37
|
+
- vendor/terminal-notifier/terminal-notifier.app/Contents/_CodeSignature/CodeResources
|
|
70
38
|
homepage: https://github.com/julienXX/terminal-notifier
|
|
71
39
|
licenses:
|
|
72
40
|
- MIT
|
|
73
|
-
metadata:
|
|
74
|
-
|
|
41
|
+
metadata:
|
|
42
|
+
source_code_uri: https://github.com/julienXX/terminal-notifier
|
|
43
|
+
bug_tracker_uri: https://github.com/julienXX/terminal-notifier/issues
|
|
44
|
+
changelog_uri: https://github.com/julienXX/terminal-notifier/releases
|
|
75
45
|
rdoc_options: []
|
|
76
46
|
require_paths:
|
|
77
47
|
- lib
|
|
@@ -79,16 +49,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
79
49
|
requirements:
|
|
80
50
|
- - ">="
|
|
81
51
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '
|
|
52
|
+
version: '3.2'
|
|
83
53
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
54
|
requirements:
|
|
85
55
|
- - ">="
|
|
86
56
|
- !ruby/object:Gem::Version
|
|
87
57
|
version: '0'
|
|
88
58
|
requirements: []
|
|
89
|
-
|
|
90
|
-
rubygems_version: 2.5.1
|
|
91
|
-
signing_key:
|
|
59
|
+
rubygems_version: 3.6.9
|
|
92
60
|
specification_version: 4
|
|
93
|
-
summary: Send User Notifications on
|
|
61
|
+
summary: Send User Notifications on macOS 10.14 or higher.
|
|
94
62
|
test_files: []
|
data/vendor/terminal-notifier
DELETED
|
Binary file
|