test_notifier 0.1.4 → 0.2.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.
data/README.rdoc CHANGED
@@ -17,7 +17,7 @@ file anyway in order to clean up the failures/errors).
17
17
 
18
18
  * Install Growl - http://growl.info/
19
19
  * Install the growlnotify script located on the "Extras" directory
20
- * Open the Growl Preference Page (System > Growl) and activate the options "Listen for incoming notifications" and "Allow remote application registration" on the Network tab.
20
+ * Open the Growl Preference Panel (System > Growl) and activate "Listen for incoming notifications" and "Allow remote application registration" options on the Network tab.
21
21
 
22
22
  === Linux
23
23
 
@@ -38,16 +38,13 @@ Then, install the gem with <tt>sudo gem install test_notifier</tt>
38
38
 
39
39
  == Usage
40
40
 
41
- If you're using Test::Unit you should add <tt>require "test_notifier/test_unit"</tt>
41
+ If you're using Test::Unit you should add <tt>require "test_notifier/runner/test_unit"</tt> to your <tt>test_helper.rb</tt> file.
42
42
 
43
- If you're using RSpec you should add <tt>require "test_notifier/rspec"</tt>
43
+ If you're using RSpec you should add <tt>require "test_notifier/runner/spec"</tt> to your <tt>spec_helper.rb</tt> file. If you're using Rails 2, you need to add <tt>require "test_notifier/runner/rspec"</tt> instead.
44
44
 
45
- If you're using Autotest you should add <tt>require test_notifier/autotest"</tt> to
45
+ If you're using Autotest you should add <tt>require test_notifier/runner/autotest"</tt> to
46
46
  the file <tt>~/.autotest</tt>
47
47
 
48
- If you want to customize the images, create a directory at <tt>~/.test_notifier</tt>
49
- and save the images <tt>none.png</tt>, <tt>passed.png<tt>, <tt>failure.png</tt> and <tt>error.png</tt>.
50
-
51
48
  == Maintainer
52
49
 
53
50
  * Nando Vieira - http://simplesideias.com.br
data/lib/test_notifier.rb CHANGED
@@ -1,136 +1,39 @@
1
1
  module TestNotifier
2
- # create a .test_notifier at your home
3
- # directory and save the images as passed.png,
4
- # failure.png and error.png for custom images
5
- PASSED_IMAGE = "passed.png"
6
- FAILURE_IMAGE = "failure.png"
7
- ERROR_IMAGE = "error.png"
8
- FAILURE_TITLE = "FAILED"
9
- PASSED_TITLE = "Passed"
10
-
11
- RSPEC_REGEX = /(\d+) examples?, (\d+) failures?(, (\d+) pendings?)?/
12
- TEST_UNIT_REGEX = /(\d+)\stests,\s(\d+)\sassertions,\s(\d+)\sfailures,\s(\d+)\serrors/
13
-
14
- GROWL_REGISTER_FILE = File.expand_path("~/.test_notifier-growl")
15
-
16
- HELP_HINT = "For more information see:\n" +
17
- " * http://github.com/fnando/test_notifier (online)\n" +
18
- " * #{File.dirname(__FILE__)}/README.markdown (offline)"
19
-
20
- def self.notify(image, title, message)
21
- image ||= "none.png"
22
-
23
- custom_image = File.join(File.expand_path("~/.test_notifier"), image)
24
- image = File.exists?(custom_image) ? custom_image : File.join(File.dirname(__FILE__), "test_notifier", "icons", image)
25
-
26
- if RUBY_PLATFORM =~ /darwin/
27
- if `ps -Al | grep GrowlHelper` && `which growlnotify` && $? == 0
28
- unless File.file?(GROWL_REGISTER_FILE)
29
- script = File.dirname(__FILE__) + "/test_notifier/register-growl.scpt"
30
- system "osascript #{script} > #{GROWL_REGISTER_FILE}"
31
- end
32
- system "growlnotify -n test_notifier --image #{image} -p 2" +
33
- "-m \"#{message}\" -t \"#{title}\""
34
- else
35
- puts "No compatible popup notification system installed."
36
- puts "Try installing these:\n* Growl"
37
- puts HELP_HINT
38
- end
39
- elsif RUBY_PLATFORM =~ /(mswin|mingw)/
40
- begin
41
- require 'snarl'
42
- rescue LoadError
43
- puts 'To be notified by a popup please install Snarl and a ruby gem "ruby-snarl".'
44
- puts HELP_HINT
45
- else
46
- Snarl.show_message(title, message, image)
47
- end
48
- elsif RUBY_PLATFORM =~ /(linux|freebsd)/
49
- # if osd_cat is avaible
50
- if `which osd_cat` && $? == 0
51
- require 'test_notifier/osd_cat'
52
- color = case image
53
- when /#{PASSED_IMAGE}/
54
- 'green'
55
- when /#{FAILURE_IMAGE}/
56
- 'orange'
57
- when /#{ERROR_IMAGE}/
58
- 'red'
59
- else
60
- 'white'
61
- end
62
- OsdCat.send "#{title} \n #{message}", color
63
- # if dcop server is running
64
- elsif `ps -Al | grep dcop` && $? == 0
65
- def self.knotify title, message
66
- system "dcop knotify default notify " +
67
- "eventname \'#{title}\' \'#{message}\' '' '' 16 2"
68
- end
69
- knotify title, message
70
- # if kdialog is available
71
- elsif `which kdialog` && $? == 0
72
- system("kdialog --title #{title} --passivepopup \"#{message}\" 5")
73
- # if notify-send is avaible
74
- elsif `which notify-send` && $? == 0
75
- system "notify-send -i #{image} #{title} \"#{message}\""
76
- else
77
- puts "No popup notification software installed."
78
- puts "Try installing one of this:\n" +
79
- " * osd_cat (apt-get install xosd-bin),\n" +
80
- " * knotify (use KDE),\n" +
81
- " * kdialog (use KDE4),\n" +
82
- " * notify-send (apt-get install libnotify-bin)"
83
- puts HELP_HINT
84
- end
85
- end
2
+ class << self
3
+ attr_accessor :__notifier
86
4
  end
87
5
 
88
- def self.rspec?(content)
89
- (RSPEC_REGEX =~ content)
90
- end
6
+ IMAGES = {
7
+ :fail => File.dirname(__FILE__) + "/../resources/fail.png",
8
+ :error => File.dirname(__FILE__) + "/../resources/error.png",
9
+ :success => File.dirname(__FILE__) + "/../resources/success.png"
10
+ }
91
11
 
92
- def self.notification_for_rspec(content)
93
- matches, *output = *content.to_s.match(RSPEC_REGEX)
94
- output = output.map {|i| i.to_i }
95
- e, f, none, p = output
12
+ TITLES = {
13
+ :fail => "Failed!",
14
+ :success => "Passed!"
15
+ }
96
16
 
97
- if f > 0
98
- # test has failed
99
- title = FAILURE_TITLE
100
- image = FAILURE_IMAGE
101
- elsif e > 0
102
- # everything's ok
103
- title = PASSED_TITLE
104
- image = PASSED_IMAGE
105
- else
106
- # no examples
107
- return
108
- end
17
+ def self.notify(options)
18
+ options.merge!({
19
+ :title => TITLES[options[:status]],
20
+ :image => IMAGES[options[:status]]
21
+ })
109
22
 
110
- message = "#{e} examples, #{f} failures, #{p} pending"
111
- notify(image, title, message)
23
+ notifier.notify(options)
112
24
  end
113
25
 
114
- def self.notification_for_test_unit(content)
115
- matches, *output = *content.to_s.match(TEST_UNIT_REGEX)
116
- output = output.map {|i| i.to_i }
117
- t, a, f, e = output
26
+ def self.notifier
27
+ self.__notifier ||= begin
28
+ TestNotifier::Notifier.constants.sort.collect do |const|
29
+ self.__notifier = TestNotifier::Notifier.const_get(const)
30
+ break if self.__notifier.supported?
31
+ end
118
32
 
119
- if f > 0 || e > 0
120
- # test has failed or raised an error
121
- title = FAILURE_TITLE
122
- image = e > 0 ? ERROR_IMAGE : FAILURE_IMAGE
123
- elsif a > 0
124
- # everything's ok
125
- title = PASSED_TITLE
126
- image = PASSED_IMAGE
127
- else
128
- # no assertions
129
- return
33
+ self.__notifier
130
34
  end
131
-
132
- message = "#{t} tests, #{a} assertions, #{f} failures, #{e} errors"
133
- notify(image, title, message)
134
35
  end
135
- end
136
36
 
37
+ autoload :Notifier, "test_notifier/notifier"
38
+ autoload :Runner, "test_notifier/runner"
39
+ end
@@ -1,12 +1,7 @@
1
- require 'test_notifier'
1
+ require "test_notifier/runner/autotest"
2
2
 
3
- Autotest.add_hook :ran_command do |at|
4
- begin
5
- content = at.results.to_s
6
-
7
- TestNotifier.rspec?(content) ?
8
- TestNotifier.notification_for_rspec(content) :
9
- TestNotifier.notification_for_test_unit(content)
10
- rescue
11
- end
12
- end
3
+ warn <<-TXT
4
+ [TestNotifier] Using `require "test_notifier/autotest"` is deprecated and
5
+ will be removed in the future. Please update your `~/.autotest` file to use
6
+ `require "test_notifier/runner/autotest"` instead.
7
+ TXT
@@ -0,0 +1,10 @@
1
+ module TestNotifier
2
+ module Notifier
3
+ autoload :Growl, "test_notifier/notifier/growl"
4
+ autoload :Snarl, "test_notifier/notifier/snarl"
5
+ autoload :OsdCat, "test_notifier/notifier/osd_cat"
6
+ autoload :Knotify, "test_notifier/notifier/knotify"
7
+ autoload :Kdialog, "test_notifier/notifier/kdialog"
8
+ autoload :NotifySend, "test_notifier/notifier/notify_send"
9
+ end
10
+ end
@@ -0,0 +1,25 @@
1
+ module TestNotifier
2
+ module Notifier
3
+ module Growl
4
+ extend self
5
+
6
+ SCRIPT = File.dirname(__FILE__) + "/../../../resources/register-growl.scpt"
7
+ FILE = File.expand_path("~/.test_notifier-growl")
8
+
9
+ def supported?
10
+ RUBY_PLATFORM =~ /darwin/ && `ps -Al | grep GrowlHelper` && `which growlnotify` && $? == 0
11
+ end
12
+
13
+ def notify(options)
14
+ Thread.new do
15
+ `growlnotify -n test_notifier --image #{options[:image]} -p 2 -m '#{options[:message]}' -t '#{options[:title]}'`
16
+ end
17
+ end
18
+
19
+ def register
20
+ return if File.file?(FILE)
21
+ system "osascript #{SCRIPT} > #{FILE}"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ module TestNotifier
2
+ module Notifier
3
+ module Kdialog
4
+ extend self
5
+
6
+ def supported?
7
+ RUBY_PLATFORM =~ /(linux|freebsd)/ && `which kdialog` && $? == 0
8
+ end
9
+
10
+ def notify(options)
11
+ Thread.new do
12
+ `kdialog --title #{options[:title]} --passivepopup \"#{options[:message]}\" 5`
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module TestNotifier
2
+ module Notifier
3
+ module Knotify
4
+ extend self
5
+
6
+ def supported?
7
+ RUBY_PLATFORM =~ /(linux|freebsd)/ && `ps -Al | grep dcop` && $? == 0
8
+ end
9
+
10
+ def notify(options)
11
+ Thread.new do
12
+ `dcop knotify default notify eventname \'#{options[:title]}\' \'#{options[:message]}\' '' '' 16 2`
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module TestNotifier
2
+ module Notifier
3
+ module NotifySend
4
+ extend self
5
+
6
+ def supported?
7
+ RUBY_PLATFORM =~ /(linux|freebsd)/ && `which notify-send` && $? == 0
8
+ end
9
+
10
+ def notify(options)
11
+ Thread.new do
12
+ `notify-send -i #{options[:image]} #{options[:title]} \"#{options[:message]}\"`
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ module TestNotifier
2
+ module Notifier
3
+ module OsdCat
4
+ extend self
5
+
6
+ FONT = "-bitstream-charter-bold-r-normal--33-240-100-100-p-206-iso8859-1"
7
+ POSITION = "top"
8
+ POSITION_OFFSET = "0"
9
+ ALIGN = "center"
10
+ COLORS = {
11
+ :fail => "orange",
12
+ :success => "green"
13
+ }
14
+
15
+ def supported?
16
+ RUBY_PLATFORM =~ /(linux|freebsd)/ && `which osd_cat` && $? == 0
17
+ end
18
+
19
+ def notify(options)
20
+ Thread.new do
21
+ `echo #{options[:message].inspect} | osd_cat --font=#{FONT} --shadow=0 --pos=#{POSITION} -o #{POSITION_OFFSET} --delay=4 --outline=4 --align=#{ALIGN} -c #{COLORS[options[:status]]}`
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ module TestNotifier
2
+ module Notifier
3
+ module Snarl
4
+ extend self
5
+
6
+ def supported?
7
+ return false unless RUBY_PLATFORM =~ /(mswin|mingw)/
8
+
9
+ begin
10
+ require "snarl" unless defined?(Snarl)
11
+ true
12
+ rescue LoadError
13
+ false
14
+ end
15
+ end
16
+
17
+ def notify(options)
18
+ Snarl.show_message(options[:title], options[:message], options[:image])
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,26 +1,11 @@
1
- require 'test_notifier'
2
- require 'spec/runner/formatter/base_text_formatter'
1
+ if defined?(RSpec)
2
+ require "test_notifier/runner/rspec"
3
+ else
4
+ require "test_notifier/runner/spec"
5
+ end
3
6
 
4
- class Spec::Runner::Formatter::BaseTextFormatter
5
- alias dump_summary_original dump_summary
6
-
7
- def dump_summary(duration, examples, failed, pending)
8
- dump_summary_original(duration, examples, failed, pending)
9
-
10
- begin
11
- return if examples == 0
12
-
13
- if failed > 0
14
- title = TestNotifier::FAILURE_TITLE
15
- image = TestNotifier::ERROR_IMAGE
16
- else
17
- title = TestNotifier::PASSED_TITLE
18
- image = TestNotifier::PASSED_IMAGE
19
- end
20
-
21
- message = "#{examples} examples, #{failed} failed, #{pending} pending"
22
- TestNotifier::notify(image, title, message)
23
- rescue
24
- end
25
- end
26
- end
7
+ warn <<-TXT
8
+ [TestNotifier] Using `require "test_notifier/rspec"` is deprecated and
9
+ will be removed in the future. Please use `require "test_notifier/runner/spec"`
10
+ or `require "test_notifier/runner/rspec"` for RSpec 2 instead.
11
+ TXT
@@ -0,0 +1,7 @@
1
+ module TestNotifier
2
+ module Runner
3
+ autoload :RSpec, "test_notifier/runner/rspec"
4
+ autoload :Spec, "test_notifier/runner/spec"
5
+ autoload :TestUnit, "test_notifier/runner/test_unit"
6
+ end
7
+ end
@@ -0,0 +1,23 @@
1
+ require "test_notifier"
2
+
3
+ Autotest.add_hook :ran_command do |at|
4
+ begin
5
+ content = at.results.to_s
6
+ rspec_matches = content.match(/(\d+) examples?, (\d+) failures?(, (\d+) pendings?)?/)
7
+ test_unit_matches = content.match(/(\d+) tests, (\d+) assertions, (\d+) failures, (\d+) errors/)
8
+
9
+ if rspec_matches
10
+ _, examples, failures, pending = *rspec_matches
11
+ status = failures.to_i > 0 ? :fail : :success
12
+ message = "#{examples} examples, #{failures} failed, #{pending} pending"
13
+ TestNotifier.notify(:status => status, :message => message) unless examples.to_i.zero?
14
+ elsif test_unit_matches
15
+ _, tests, assertions, failures, errors = *test_unit_matches
16
+
17
+ status = failures.to_i > 0 ? :fail : :success
18
+ message = "#{tests} tests, #{assertions} assertions, #{failures} failures, #{errors} errors"
19
+ TestNotifier.notify(:status => status, :message => message) unless tests.to_i.zero?
20
+ end
21
+ rescue
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ require "test_notifier"
2
+ require "rspec/core/formatters/base_text_formatter"
3
+
4
+ class RSpec::Core::Formatters::BaseTextFormatter
5
+ alias dump_summary_original dump_summary
6
+
7
+ def dump_summary(duration, examples, failed, pending)
8
+ dump_summary_original(duration, examples, failed, pending)
9
+
10
+ begin
11
+ return if examples == 0
12
+ status = failed > 0 ? :fail : :success
13
+ message = "#{examples} examples, #{failed} failed, #{pending} pending"
14
+ TestNotifier.notify(:status => status, :message => message)
15
+ rescue
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ require "test_notifier"
2
+ require "spec/runner/formatter/base_text_formatter"
3
+
4
+ class Spec::Runner::Formatter::BaseTextFormatter
5
+ alias dump_summary_original dump_summary
6
+
7
+ def dump_summary(duration, examples, failed, pending)
8
+ dump_summary_original(duration, examples, failed, pending)
9
+
10
+ begin
11
+ return if examples == 0
12
+ status = failed > 0 ? :fail : :success
13
+ message = "#{examples} examples, #{failed} failed, #{pending} pending"
14
+ TestNotifier.notify(:status => status, :message => message)
15
+ rescue
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ require "test_notifier"
2
+ require "test/unit/ui/console/testrunner"
3
+
4
+ class Test::Unit::UI::Console::TestRunner
5
+ alias finished_original finished
6
+
7
+ def finished(elapsed_time)
8
+ finished_original(elapsed_time)
9
+
10
+ begin
11
+ re = /(\d+) tests, (\d+) assertions, (\d+) failures, (\d+) errors/
12
+ _, tests, assertions, failures, errors = *@result.to_s.match(re)
13
+
14
+ return if tests.to_i == 0
15
+
16
+ status = (failures.to_i + errors.to_i) > 0 ? :fail : :success
17
+ message = "#{tests} tests, #{assertions} assertions, #{failures} failures, #{errors} errors"
18
+ TestNotifier.notify(:status => status, :message => message)
19
+ rescue
20
+ end
21
+ end
22
+ end
@@ -1,16 +1,6 @@
1
- require 'test_notifier'
2
- require 'test/unit/ui/console/testrunner'
1
+ require "test_notifier/runner/test_unit"
3
2
 
4
- class Test::Unit::UI::Console::TestRunner
5
- alias finished_original finished
6
-
7
- def finished(elapsed_time)
8
- finished_original(elapsed_time)
9
-
10
- begin
11
- content = @result.to_s
12
- TestNotifier.notification_for_test_unit(content)
13
- rescue
14
- end
15
- end
16
- end
3
+ warn <<-TXT
4
+ [TestNotifier] Using `require "test_notifier/test_unit"` is deprecated and
5
+ will be removed in the future. Please use `require "test_notifier/runner/test_unit"` instead.
6
+ TXT
@@ -0,0 +1,8 @@
1
+ module TestNotifier
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 2
5
+ PATCH = 0
6
+ STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
7
+ end
8
+ end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: test_notifier
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 23
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
- - 1
8
- - 4
9
- version: 0.1.4
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
10
11
  platform: ruby
11
12
  authors:
12
13
  - Nando Vieira
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-05-27 00:00:00 -03:00
18
+ date: 2010-07-26 00:00:00 -03:00
18
19
  default_executable:
19
20
  dependencies: []
20
21
 
@@ -34,13 +35,24 @@ files:
34
35
  - README.rdoc
35
36
  - lib/test_notifier.rb
36
37
  - lib/test_notifier/autotest.rb
37
- - lib/test_notifier/icons/error.png
38
- - lib/test_notifier/icons/failure.png
39
- - lib/test_notifier/icons/passed.png
40
- - lib/test_notifier/osd_cat.rb
41
- - lib/test_notifier/register-growl.scpt
38
+ - lib/test_notifier/notifier.rb
39
+ - lib/test_notifier/notifier/growl.rb
40
+ - lib/test_notifier/notifier/kdialog.rb
41
+ - lib/test_notifier/notifier/knotify.rb
42
+ - lib/test_notifier/notifier/notify_send.rb
43
+ - lib/test_notifier/notifier/osd_cat.rb
44
+ - lib/test_notifier/notifier/snarl.rb
42
45
  - lib/test_notifier/rspec.rb
46
+ - lib/test_notifier/runner.rb
47
+ - lib/test_notifier/runner/autotest.rb
48
+ - lib/test_notifier/runner/rspec.rb
49
+ - lib/test_notifier/runner/spec.rb
50
+ - lib/test_notifier/runner/test_unit.rb
43
51
  - lib/test_notifier/test_unit.rb
52
+ - lib/test_notifier/version.rb
53
+ - resources/fail.png
54
+ - resources/register-growl.scpt
55
+ - resources/success.png
44
56
  has_rdoc: true
45
57
  homepage: http://github.com/fnando/test_notifier
46
58
  licenses: []
@@ -51,23 +63,27 @@ rdoc_options:
51
63
  require_paths:
52
64
  - lib
53
65
  required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
54
67
  requirements:
55
68
  - - ">="
56
69
  - !ruby/object:Gem::Version
70
+ hash: 3
57
71
  segments:
58
72
  - 0
59
73
  version: "0"
60
74
  required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
61
76
  requirements:
62
77
  - - ">="
63
78
  - !ruby/object:Gem::Version
79
+ hash: 3
64
80
  segments:
65
81
  - 0
66
82
  version: "0"
67
83
  requirements:
68
- - You'll need Growl (Mac OS X), Libnotify (Linux) or Snarl (Windows)
84
+ - You'll need Growl (Mac OS X), Libnotify, OSD or KDE (Linux) or Snarl (Windows)
69
85
  rubyforge_project:
70
- rubygems_version: 1.3.6
86
+ rubygems_version: 1.3.7
71
87
  signing_key:
72
88
  specification_version: 3
73
89
  summary: Display system notifications (dbus, growl and snarl) after running tests.
Binary file
@@ -1,20 +0,0 @@
1
- # Provides a method for popup notifications using osd_cat
2
- # Extracted from http://theadmin.org/articles/2008/2/10/fail-loudly-with-osd_cat-and-autotest
3
- module OsdCat
4
- # Use xlsfonts to find the different fonts
5
- FONT = "-bitstream-charter-bold-r-normal--33-240-100-100-p-206-iso8859-1"
6
-
7
- # Will display the message on the top of the screen centered, adjust these numbers to suit.
8
- POSITION = "top" # top|middle|bottom
9
- POSITION_OFFSET = "0" # Pixels from position to display (think CSS margin)
10
- ALIGN = "center" # left|right|center
11
-
12
- def self.send message, color='green'
13
- osd_command = "echo #{message.inspect} | osd_cat --font=#{FONT} --shadow=0 --pos=#{POSITION} -o #{POSITION_OFFSET} --delay=4 --outline=4 --align=#{ALIGN} -c #{color}"
14
-
15
- # osd_cat blocks so start a new thread, otherwise Autotest will wait
16
- Thread.new do
17
- `#{osd_command}`
18
- end
19
- end
20
- end