growl_notify_osascript 0.0.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.
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +20 -0
- data/Rakefile +10 -0
- data/Readme.md +68 -0
- data/growl_notify_osascript.gemspec +26 -0
- data/lib/growl_notify.rb +6 -0
- data/lib/growl_notify_osascript.rb +125 -0
- data/spec/growl_icon.png +0 -0
- data/spec/growl_notify_osascript_spec.rb +108 -0
- data/spec/spec_helper.rb +5 -0
- metadata +123 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rspec', :version => 2, :cli => '--color --format doc' do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
watch('growl_notify.gemspec') { "spec" }
|
9
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Scott Davis
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
data/Readme.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# GrowlNotifyOsascript
|
2
|
+
|
3
|
+
This is a fork of Scott Davis' excellent [GrowlNotify gem](https://github.com/scottdavis/growl_notify).
|
4
|
+
|
5
|
+
The original is based on the rb-appscript bindings to Applescript, which unfortunately doesn't support Kernel::fork. This gem uses Applescript piped through the osascript utility instead.
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
### Configuring
|
10
|
+
|
11
|
+
GrowlNotify.config do |config|
|
12
|
+
config.notifications = ["Compass Application", "Someother Notification"]
|
13
|
+
config.default_notifications = ["Compass Application"]
|
14
|
+
config.application_name = "My Application" #this shows up in the growl applications list in systems settings
|
15
|
+
end
|
16
|
+
|
17
|
+
You can also set a globally scoped icon:
|
18
|
+
|
19
|
+
GrowlNotify.config do |config|
|
20
|
+
config.notifications = ["Compass Application", "Someother Notification"]
|
21
|
+
config.default_notifications = ["Compass Application"]
|
22
|
+
config.application_name = "My Application" #this shoes up in the growl applications list in systems settings
|
23
|
+
config.icon = File.join("SOME PATH")
|
24
|
+
end
|
25
|
+
|
26
|
+
### Using
|
27
|
+
|
28
|
+
#### Notification levels:
|
29
|
+
|
30
|
+
1. very_low: `GrowlNotify.very_low(:title => 'HELLO WORLD', :description => 'Man that was cool')`
|
31
|
+
2. moderate: `GrowlNotify.moderate(:title => 'HELLO WORLD', :description => 'Man that was cool')`
|
32
|
+
3. normal: `GrowlNotify.normal(:title => 'HELLO WORLD', :description => 'Man that was cool')`
|
33
|
+
4. high: `GrowlNotify.high(:title => 'HELLO WORLD', :description => 'Man that was cool')`
|
34
|
+
5. emergency: `GrowlNotify.emergency(:title => 'HELLO WORLD', :description => 'Man that was cool')`
|
35
|
+
|
36
|
+
#### Sticky messages
|
37
|
+
|
38
|
+
`GrowlNotify.sticky!(:title => 'HELLO WORLD', :description => 'Man that was cool')`
|
39
|
+
|
40
|
+
#### Options
|
41
|
+
|
42
|
+
{:title => 'no title', :application_name => "My Application", :description => 'no description', :sticky => false, :priority => 0, :with_name => "Compass Application", :icon => <file path>}
|
43
|
+
|
44
|
+
1. title - Title of message box
|
45
|
+
2. description - Body of your message
|
46
|
+
3. icon - Icon to show - pretty much all image formats are supported
|
47
|
+
4. priority - importance of message from -2 very_low .. 2 emergency
|
48
|
+
5. sticky - boolean if want the message to stick to the screen
|
49
|
+
6. application_name - This is set from configs but you can override it
|
50
|
+
7. with_name - must me one of your set default notifications by default its set to the first one
|
51
|
+
|
52
|
+
#### Error Handling
|
53
|
+
|
54
|
+
If the growl application is not installed on the system `GrowlNotify` will throw a `GrowlNotFound` exception.
|
55
|
+
|
56
|
+
## Author
|
57
|
+
|
58
|
+
GrowlNotify is written by [Scott Davis](http://sdavis.info)
|
59
|
+
|
60
|
+
Scott is a Developer for the Space Telescope Science Institute in Baltimore, MD - [Hubble Space Telescope](http://hubblesite.org)
|
61
|
+
|
62
|
+
[Twitter](http://twitter.com/jetviper21)
|
63
|
+
|
64
|
+
GrowlNotifyOsascript was hacked together by [Inge Jørgensen](http://elektronaut.no)
|
65
|
+
|
66
|
+
## Copyright
|
67
|
+
|
68
|
+
Copyright (c) 2011 Scott Davis. See LICENSE.txt for further details.
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "growl_notify_osascript"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
#s.name = "growl_notify_osascript"
|
7
|
+
s.name = "growl_notify_osascript"
|
8
|
+
s.version = GrowlNotifyOsascript::VERSION
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ["Inge Jørgensen"]
|
11
|
+
s.email = ["inge@elektronaut.no"]
|
12
|
+
s.homepage = "https://github.com/elektronaut/growl_notify_osascript"
|
13
|
+
s.summary = %q{Port of Sam Davis' growl_notify gem without the Appscript dependency}
|
14
|
+
s.description = %q{Port of Sam Davis' growl_notify gem without the Appscript dependency}
|
15
|
+
|
16
|
+
s.rubyforge_project = "growl_notify_osascript"
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
20
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
21
|
+
s.require_paths = ["lib"]
|
22
|
+
s.add_development_dependency 'rspec'
|
23
|
+
s.add_development_dependency 'guard-rspec'
|
24
|
+
s.add_development_dependency 'mocha'
|
25
|
+
|
26
|
+
end
|
data/lib/growl_notify.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
|
5
|
+
class GrowlNotifyOsascript
|
6
|
+
VERSION = "0.0.1"
|
7
|
+
class GrowlNotFound < Exception; end
|
8
|
+
class << self
|
9
|
+
|
10
|
+
attr_accessor :application_name, :default_notifications, :notifications, :icon
|
11
|
+
@application_name = "Ruby Growl"
|
12
|
+
@default_notifications = []
|
13
|
+
@notifications = []
|
14
|
+
@icon = nil
|
15
|
+
|
16
|
+
def config(&block)
|
17
|
+
block.call(self)
|
18
|
+
register
|
19
|
+
end
|
20
|
+
|
21
|
+
def escape(string)
|
22
|
+
'"' + string.to_s.gsub('"', '\"') + '"'
|
23
|
+
end
|
24
|
+
|
25
|
+
def run_script(script)
|
26
|
+
output = Open3.popen3('osascript') do |i, o, ts|
|
27
|
+
i.puts script
|
28
|
+
i.close
|
29
|
+
o.gets
|
30
|
+
end
|
31
|
+
output ? output.strip : nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def reset!
|
35
|
+
[:application_name, :default_notifications, :notifications, :icon].each do |meth|
|
36
|
+
send(:"#{meth}=", nil)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_applescript(hash)
|
41
|
+
hash.map do |key, value|
|
42
|
+
unless value.nil?
|
43
|
+
name = key.to_s.gsub('_', ' ')
|
44
|
+
if value.kind_of?(Array)
|
45
|
+
"#{name} {" + value.map{|v| escape(v)}.join(', ') + "}"
|
46
|
+
else
|
47
|
+
"#{name} " + escape(value)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end.compact.join(' ')
|
51
|
+
end
|
52
|
+
|
53
|
+
def register
|
54
|
+
raise GrowlNotFound unless running?
|
55
|
+
|
56
|
+
script = "tell application id \"com.Growl.GrowlHelperApp\"\n" +
|
57
|
+
"register " +
|
58
|
+
to_applescript(
|
59
|
+
:as_application => @application_name,
|
60
|
+
:all_notifications => @notifications,
|
61
|
+
:default_notifications => @default_notifications
|
62
|
+
) +
|
63
|
+
"\nend tell"
|
64
|
+
|
65
|
+
run_script(script)
|
66
|
+
end
|
67
|
+
|
68
|
+
def running?
|
69
|
+
script = "tell application \"System Events\"\n" +
|
70
|
+
"set isRunning to count of (every process whose bundle identifier is \"com.Growl.GrowlHelperApp\") > 0\n" +
|
71
|
+
"end tell"
|
72
|
+
run_script(script) == 'true'
|
73
|
+
end
|
74
|
+
|
75
|
+
def send_notification(options= {})
|
76
|
+
raise GrowlNotFound unless running?
|
77
|
+
defaults = {:title => 'no title', :application_name => @application_name, :description => 'no description', :sticky => false, :priority => 0, :with_name => notifications.first}
|
78
|
+
local_icon = @icon
|
79
|
+
local_icon = options.delete(:icon) if options.include?(:icon)
|
80
|
+
if local_icon
|
81
|
+
defaults.merge!(:image_from_location => local_icon)
|
82
|
+
end
|
83
|
+
|
84
|
+
opts = defaults.merge(options)
|
85
|
+
|
86
|
+
script = "tell application id \"com.Growl.GrowlHelperApp\"\n" +
|
87
|
+
"notify " +
|
88
|
+
to_applescript(opts) +
|
89
|
+
"\nend tell"
|
90
|
+
|
91
|
+
run_script(script)
|
92
|
+
end
|
93
|
+
|
94
|
+
def very_low(options={})
|
95
|
+
options.merge!(:priority => -2)
|
96
|
+
send_notification(options)
|
97
|
+
end
|
98
|
+
|
99
|
+
def moderate(options={})
|
100
|
+
options.merge!(:priority => -1)
|
101
|
+
send_notification(options)
|
102
|
+
end
|
103
|
+
|
104
|
+
def normal(options={})
|
105
|
+
options.merge!(:priority => 0)
|
106
|
+
send_notification(options)
|
107
|
+
end
|
108
|
+
|
109
|
+
def high(options={})
|
110
|
+
options.merge!(:priority => 1)
|
111
|
+
send_notification(options)
|
112
|
+
end
|
113
|
+
|
114
|
+
def emergency(options={})
|
115
|
+
options.merge!(:priority => 2)
|
116
|
+
send_notification(options)
|
117
|
+
end
|
118
|
+
|
119
|
+
def sticky!(options={})
|
120
|
+
options.merge!(:sticky => true)
|
121
|
+
send_notification(options)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
data/spec/growl_icon.png
ADDED
Binary file
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
ICON = File.join(File.expand_path('../', __FILE__), 'growl_icon.png')
|
3
|
+
describe GrowlNotifyOsascript do
|
4
|
+
it "should reset the configs" do
|
5
|
+
GrowlNotifyOsascript.config do |config|
|
6
|
+
config.notifications = config.default_notifications = ["foo"]
|
7
|
+
config.application_name = config.notifications.first
|
8
|
+
end
|
9
|
+
GrowlNotifyOsascript.notifications.should == ["foo"]
|
10
|
+
GrowlNotifyOsascript.reset!
|
11
|
+
GrowlNotifyOsascript.notifications.should be_nil
|
12
|
+
end
|
13
|
+
after :each do
|
14
|
+
GrowlNotifyOsascript.reset!
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'application not found' do
|
18
|
+
before do
|
19
|
+
GrowlNotifyOsascript.stubs(:running?).returns(false)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should raise correct error" do
|
23
|
+
lambda {
|
24
|
+
GrowlNotifyOsascript.config do |config|
|
25
|
+
config.notifications = config.default_notifications = ["Compass Application"]
|
26
|
+
config.application_name = config.notifications.first
|
27
|
+
end
|
28
|
+
GrowlNotifyOsascript.normal(:title => 'GrowlNotifyOsascript Spec', :description => 'This is my "normal" message').should be_nil
|
29
|
+
}.should raise_error GrowlNotifyOsascript::GrowlNotFound
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'default' do
|
34
|
+
before do
|
35
|
+
GrowlNotifyOsascript.config do |config|
|
36
|
+
config.notifications = config.default_notifications = ["Compass Application"]
|
37
|
+
config.application_name = config.notifications.first
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should send a growl notification with icon" do
|
42
|
+
GrowlNotifyOsascript.send_notification(:title => 'GrowlNotifyOsascript Spec', :description => 'This is my descripton', :icon => ICON).should be_nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'no icon' do
|
47
|
+
before do
|
48
|
+
GrowlNotifyOsascript.config do |config|
|
49
|
+
config.notifications = config.default_notifications = ["Compass Application"]
|
50
|
+
config.application_name = config.notifications.first
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should send a growl notification with icon" do
|
55
|
+
GrowlNotifyOsascript.send_notification(:title => 'GrowlNotifyOsascript Spec', :description => 'This is my descripton no icon').should be_nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'config with icon' do
|
60
|
+
before do
|
61
|
+
GrowlNotifyOsascript.config do |config|
|
62
|
+
config.notifications = config.default_notifications = ["Compass Application"]
|
63
|
+
config.application_name = config.notifications.first
|
64
|
+
config.icon = ICON
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should send a growl notification with icon" do
|
69
|
+
GrowlNotifyOsascript.send_notification(:title => 'GrowlNotifyOsascript Spec', :description => 'This is my descripton with a global icon').should be_nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "helper methods" do
|
74
|
+
before do
|
75
|
+
GrowlNotifyOsascript.config do |config|
|
76
|
+
config.notifications = config.default_notifications = ["Compass Application"]
|
77
|
+
config.application_name = config.notifications.first
|
78
|
+
config.icon = ICON
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should send 'very low'" do
|
83
|
+
GrowlNotifyOsascript.very_low(:title => 'GrowlNotifyOsascript Spec', :description => 'This is my "very_low" message').should be_nil
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should send 'moderate'" do
|
87
|
+
GrowlNotifyOsascript.moderate(:title => 'GrowlNotifyOsascript Spec', :description => 'This is my "moderate" message').should be_nil
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should send 'normal'" do
|
91
|
+
GrowlNotifyOsascript.normal(:title => 'GrowlNotifyOsascript Spec', :description => 'This is my "normal" message').should be_nil
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should send 'high'" do
|
95
|
+
GrowlNotifyOsascript.high(:title => 'GrowlNotifyOsascript Spec', :description => 'This is my "high" message').should be_nil
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should send 'emergency'" do
|
99
|
+
GrowlNotifyOsascript.emergency(:title => 'GrowlNotifyOsascript Spec', :description => 'This is my "emergency" message').should be_nil
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should send 'sticky'" do
|
103
|
+
GrowlNotifyOsascript.sticky!(:title => 'GrowlNotifyOsascript Spec', :description => 'This is my "Sticky!" message').should be_nil
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: growl_notify_osascript
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- "Inge J\xC3\xB8rgensen"
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-11-24 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: guard-rspec
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: mocha
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :development
|
62
|
+
version_requirements: *id003
|
63
|
+
description: Port of Sam Davis' growl_notify gem without the Appscript dependency
|
64
|
+
email:
|
65
|
+
- inge@elektronaut.no
|
66
|
+
executables: []
|
67
|
+
|
68
|
+
extensions: []
|
69
|
+
|
70
|
+
extra_rdoc_files: []
|
71
|
+
|
72
|
+
files:
|
73
|
+
- .gitignore
|
74
|
+
- .rspec
|
75
|
+
- Gemfile
|
76
|
+
- Guardfile
|
77
|
+
- LICENSE.txt
|
78
|
+
- Rakefile
|
79
|
+
- Readme.md
|
80
|
+
- growl_notify_osascript.gemspec
|
81
|
+
- lib/growl_notify.rb
|
82
|
+
- lib/growl_notify_osascript.rb
|
83
|
+
- spec/growl_icon.png
|
84
|
+
- spec/growl_notify_osascript_spec.rb
|
85
|
+
- spec/spec_helper.rb
|
86
|
+
has_rdoc: true
|
87
|
+
homepage: https://github.com/elektronaut/growl_notify_osascript
|
88
|
+
licenses: []
|
89
|
+
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options: []
|
92
|
+
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
hash: 3
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
version: "0"
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
hash: 3
|
110
|
+
segments:
|
111
|
+
- 0
|
112
|
+
version: "0"
|
113
|
+
requirements: []
|
114
|
+
|
115
|
+
rubyforge_project: growl_notify_osascript
|
116
|
+
rubygems_version: 1.6.2
|
117
|
+
signing_key:
|
118
|
+
specification_version: 3
|
119
|
+
summary: Port of Sam Davis' growl_notify gem without the Appscript dependency
|
120
|
+
test_files:
|
121
|
+
- spec/growl_icon.png
|
122
|
+
- spec/growl_notify_osascript_spec.rb
|
123
|
+
- spec/spec_helper.rb
|