experiment 0.0.1 → 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.
@@ -5,11 +5,15 @@ Rakefile
5
5
  lib/experiment.rb
6
6
  lib/experiment/config.rb
7
7
  lib/experiment/stats.rb
8
+ lib/experiment/runner.rb
8
9
  lib/experiment/generator/readme_template.txt
9
10
  lib/experiment/generator/experiment_template.rb
10
11
  lib/experiment/generator/Rakefile
11
12
  lib/experiment/base.rb
12
13
  lib/experiment/notify.rb
14
+ lib/experiment/work_server.rb
15
+ lib/experiment/distributed.rb
13
16
  test/test_experiment.rb
14
17
  test/test_helper.rb
15
- bin/experiment
18
+ bin/experiment
19
+ bin/growl.sh
@@ -27,7 +27,7 @@ Experiments are set up in the experiments directory. The first thing you need to
27
27
 
28
28
  For a typical experiment you will need to do some setup work (eg. initialize your classes, calculate parametres, etc.), run the experiment and maybe do cleanup (remove temp. files).
29
29
 
30
- You do all this work in the `run_the_experiment` method. Remember to pass the raw output via `<<` to the `output` variable and wrap the experiment in a benchmark block. This will be automatically saved to the results directory for further analysis.
30
+ You do all this work in the `run_the_experiment` method. Use the `measure` method to wrap your measurements. These will be autmatically benchmarked and their ouput will be automatically saved to the results directory for further analysis.
31
31
 
32
32
  The `test_data` method lets you specify an array of data points that you want split for cross-validation (see below). This will be passed to in `run_the_experiment` in the input variable.
33
33
 
@@ -102,7 +102,7 @@ Then your final config will look like this:
102
102
  :master_dir => "/Users/kubowo/Desktop/points-vals/s015",
103
103
  :alpha => 0.6 }
104
104
 
105
- Flexible, eh?
105
+ Flexible, eh? **NEW** Check out the *get* method. It has features like interpolation and defaults.
106
106
 
107
107
  == Cross Validation
108
108
 
@@ -116,8 +116,17 @@ Surprise, surprise. This will create two files in your `report` directory (BTW,
116
116
 
117
117
  The second file created is the `data.csv` file which contains the data from all your experiments. It should be importable to Numbers, Excel even Matlab for further analysis and charting.
118
118
 
119
+
120
+ == Distributed computing support
121
+
122
+ Newly this library supports a simple distributed model of running experiments. Setup worker computers with the
123
+
124
+ $ experiment worker --address IP_OF_COMPUTER_WHERE_YOU_RUN_EXPERIMENTS
125
+
126
+ and then run experiments with --distributed flag.
127
+
119
128
  == Misc
120
129
 
121
- So that's pretty much the gist of experiment. There's a few other features (and a few soon to come to a gem near you ;-)
130
+ So that's pretty much the gist of experiment. There's a few other features (and a few soon to come to a gem near you ;-) Growl notifications are now supported. Turn them of by setting growl_notifications to false in your config file.
122
131
 
123
132
  Also check out the RDocs: http://rdoc.info/github/gampleman/Experiment/master/frames
data/Rakefile CHANGED
@@ -14,7 +14,7 @@ $hoe = Hoe.spec 'experiment' do
14
14
  self.developer 'Jakub Hampl', 'honitom@seznam.cz'
15
15
  #self.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
16
16
  self.rubyforge_name = self.name # TODO this is default value
17
- # self.extra_deps = [['activesupport','>= 2.0.2']]
17
+ #self.extra_deps = [['ruby-growl','>= 1.0']]
18
18
 
19
19
  end
20
20
 
@@ -1,47 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # == Synopsis
4
- # This program will run an experimental batch or generate files
5
- # for a new experiment
6
- #
7
- # == Examples
8
- # Running an experiment
9
- # experiment --env dice experiment1 experiment2 ...
10
- #
11
- # Generating a new experiment with 2 cross validations
12
- # experiment new experiment_name --cv 2
13
- #
14
- # List all available experiments
15
- # experiment list
16
- #
17
- #
18
- # == Usage
19
- # experiment command [options]
20
- #
21
- # For help use: experiment -h
22
- #
23
- # == Options
24
- # -h, --help Displays help message
25
- # -v, --version Display the version, then exit
26
- # -q, --quiet Output as little as possible, overrides verbose
27
- # -V, --verbose Verbose output
28
- # -e, --env Sets the environment to run in
29
- # Defaults to development
30
- # -c, --cv Number of Cross validations to run
31
- # -m, --description A description of the current experiment
32
- #
33
- # == Author
34
- # Jakub Hampl
35
- #
36
-
37
- #require "rubygems"
38
3
  require 'optparse'
39
- #require 'rdoc/usage'
40
4
  require 'ostruct'
41
- #require File.dirname(__FILE__) + "/experiment"
5
+ require "rdoc"
6
+ require "rdoc/rdoc"
7
+
8
+ require File.dirname(__FILE__) + "/../lib/experiment/runner"
42
9
 
43
10
  class App
44
- VERSION = '1.0'
11
+ VERSION = '0.2.0'
45
12
 
46
13
  attr_reader :options
47
14
 
@@ -55,11 +22,10 @@ class App
55
22
  @options.quiet = false
56
23
  @options.env = :development
57
24
  @options.cv = 5
58
- @options.n_classes = 10
59
- @options.kind = "d"
60
25
  @options.description = ""
61
- @options.opts = {}
62
-
26
+ @options.opts = ""
27
+ @options.distributed = false
28
+ @options.master = "localhost"
63
29
  end
64
30
 
65
31
  # Parse options, check arguments, then process the command
@@ -69,10 +35,7 @@ class App
69
35
 
70
36
  puts "Start at #{DateTime.now}\n\n" if @options.verbose
71
37
 
72
- output_options if @options.verbose # [Optional]
73
- require File.dirname(__FILE__) + "/vendor/backports/backports" if @options.env == :dice
74
-
75
- process_arguments
38
+ output_options if @options.verbose # [Optional]
76
39
  process_command
77
40
 
78
41
  puts "\nFinished at #{DateTime.now}" if @options.verbose
@@ -88,20 +51,20 @@ class App
88
51
  def parsed_options?
89
52
 
90
53
  # Specify options
91
- opts = OptionParser.new
92
- opts.on('-v', '--version') { output_version ; exit 0 }
93
- opts.on('-h', '--help') { output_help }
94
- opts.on('-V', '--verbose') { @options.verbose = true }
95
- opts.on('-q', '--quiet') { @options.quiet = true }
96
- opts.on('-e', '--env [ENV]', [:development, :dice]) { |v| @options.env = v }
97
- opts.on('-c', '--cv CV', Integer) { |v| @options.cv = v }
98
- opts.on('-n', '--number NUMBER', Integer) { |v| @options.n_classes = v }
99
- opts.on('-k', '--kind KIND', String) { |v| @options.kind = v }
100
- opts.on('-m', '--description M', String) { |v| @options.description = v }
101
- opts.on('-o', '--options OPTSTRING', String) do |v|
54
+ @opts = OptionParser.new
55
+ @opts.on('-v', '--version') { output_version ; exit 0 }
56
+ @opts.on('-h', '--help') { output_help }
57
+ @opts.on('-V', '--verbose') { @options.verbose = true }
58
+ @opts.on('-q', '--quiet') { @options.quiet = true }
59
+ @opts.on('-e', '--env [ENV]', [:development, :compute], "Sets the environment to run in.") { |v| @options.env = v }
60
+ @opts.on('-c', '--cv CV', Integer, "The number of cross validations to run.") { |v| @options.cv = v }
61
+ @opts.on('-m', '--description M', String, "Description or hypothesis for the condition being generated.") { |v| @options.description = v }
62
+ @opts.on('-o', '--options OPTSTRING', String, "Options to override config with. key1:val1,key2:val2") do |v|
102
63
  @options.opts = v
103
64
  end
104
- opts.parse!(@arguments) rescue return false
65
+ @opts.on('-D', '--distributed', "Run with a distributed computing mode. This will be the master server/work cue.") { @options.distributed = true }
66
+ @opts.on('-a', '--address MODE', String, "Address to the master machine.") { |v| @options.master = v }
67
+ @opts.parse!(@arguments) #rescue return false
105
68
 
106
69
  process_options
107
70
  true
@@ -122,21 +85,45 @@ class App
122
85
 
123
86
  # True if required arguments were provided
124
87
  def arguments_valid?
125
- true if @arguments.length > 0
126
- end
127
-
128
- # Setup the arguments
129
- def process_arguments
130
- # TO DO - place in local vars, etc
88
+ true #if @arguments.length > 0
131
89
  end
132
90
 
133
91
  def output_help
134
92
  output_version
135
- RDoc::usage() #exits app
93
+ puts "= Synopsis
94
+ This program will run an experimental batch or generate files
95
+ for a new experiment"
96
+ puts
97
+ output_usage
98
+ puts
99
+ puts "= Options"
100
+ puts @opts.help
101
+ puts
102
+ puts "= Commands"
103
+ # Bizzare hax to make RDoc parse the files
104
+ top_level = RDoc::TopLevel.new File.dirname(__FILE__) + "/../lib/experiment/runner.rb"
105
+ opts = RDoc::Options.new
106
+ stats = RDoc::Stats.new 1
107
+ parser = RDoc::Parser.for top_level, File.dirname(__FILE__) + "/../lib/experiment/runner.rb", File.read(File.dirname(__FILE__) + "/../lib/experiment/runner.rb"), opts, stats
108
+ d = parser.scan
109
+ d.modules.first.classes.first.method_list.each do |m|
110
+ if m.comment != ""
111
+ puts "== #{m.name == 'new_project' ? 'new' : m.name}"
112
+ puts m.comment
113
+ puts
114
+ end
115
+ end
116
+
117
+ puts "----"
118
+ exit 0
136
119
  end
137
120
 
138
121
  def output_usage
139
- RDoc::usage('usage') # gets usage from comments above
122
+ puts "= Usage
123
+ experiment command [options]
124
+
125
+ For help use: experiment -h"
126
+
140
127
  end
141
128
 
142
129
  def output_version
@@ -144,130 +131,19 @@ class App
144
131
  end
145
132
 
146
133
  def process_command
147
- if @arguments.first == 'generate'
148
- dir = "./experiments/" + @arguments[1]
149
- Dir.mkdir(dir)
150
- File.open(dir + "/" + @arguments[1] + ".rb", "w") do |req_file|
151
- req_file.puts "# ## #{as_human_name @arguments[1]} ##"
152
- req_file.puts "# "+@options.description.split("\n").join("\n# ")
153
- req_file.puts
154
- req_file.puts
155
- req_file.puts "# The first contious block of comment will be included in your report."
156
- req_file.puts "# This includes the reference implementation."
157
- req_file.puts "# Override any desired files in this directory."
158
- Dir["./app/**/*.rb"].each do |f|
159
- p = f.split("/") - File.expand_path(".").split("/")
160
- req_file.puts "require File.dirname(__FILE__) + \"/../../#{p.join("/")}\""
161
- end
162
- req_file.puts "\nclass #{as_class_name @arguments[1]} < MyExperiment\n\t\nend"
163
- end
164
- File.open(dir + "/config.yaml", "w") do |f|
165
- f << "---\nexperiment:\n development:\n compute:\n"
166
- end
167
-
168
- elsif @arguments.first == "new" # generate a new project
169
- require 'fileutils'
170
- dir = "./" + @arguments[1]
171
- Dir.mkdir(dir)
172
- %w[app config experiments report results test tmp vendor].each do |d|
173
- Dir.mkdir(dir + "/" + d)
174
- end
175
- basedir = File.dirname(__FILE__) + "/.."
176
- File.open(File.join(dir, "config", "config.yaml"), "w") do |f|
177
- f << "---\nenvironments:\n development:\n compute:\n"
178
- end
179
- File.open(File.join(dir, ".gitignore"), "w") do |f|
180
- f << "tmp/*"
181
- end
182
- FileUtils::cp File.join(basedir, "lib/experiment/generator/readme_template.txt"), File.join(dir, "README")
183
- FileUtils::cp File.join(basedir, "lib/experiment/generator/Rakefile"), File.join(dir, "Rakefile")
184
- FileUtils::cp File.join(basedir, "lib/experiment/generator/experiment_template.rb"), File.join(dir, "experiments", "experiment.rb")
185
- elsif @arguments.first == "list"
186
- puts "Available experiments:"
187
- puts " " + Dir["./experiments/*"].map{|a| File.basename(a) }.join(", ")
188
- elsif @arguments.first == "report"
189
- dir = "./report/"
190
- File.open(dir + "method.mmd", "w") do |f|
191
- f.puts "# Methods #"
192
- Dir["./experiments/*/*.rb"].each do |desc|
193
- if File.basename(desc) == File.basename(File.dirname(desc)) + ".rb"
194
- File.read(desc).split("\n").each do |line|
195
- if m = line.match(/^\# (.+)/)
196
- f.puts m[1]
197
- else
198
- break
199
- end
200
- end
201
- f.puts
202
- f.puts
203
- end
204
- end
205
- end
206
- require 'csv'
207
- require "yaml"
208
- require File.dirname(__FILE__)+"/../lib/experiment/stats"
209
- CSV.open(dir + "/data.csv", "w") do |csv|
210
- data = {}
211
- Dir["./results/*/results.yaml"].each do |res|
212
- d = YAML::load_file(res)
213
- da = {}
214
- d.each do |k, vals|
215
- da[k.to_s + " mean"], da[k.to_s + " sd"] = Stats::mean(vals), Stats::standard_deviation(vals)
216
- vals.each_with_index do |v, i|
217
- da[k.to_s + " cv:" + i.to_s] = v
218
- end
219
- end
220
- array_merge(data, da)
221
- end
222
- data.keys.map do |key|
223
- # calculate stats
224
- a = data[key]
225
- [key] + a
226
- end.transpose.each do |row|
227
- csv << row
228
- end
229
- end
230
- elsif @arguments.shift == "run"
231
- require File.dirname(__FILE__) + "/../lib/experiment/base"
232
- require "experiments/experiment"
233
- @arguments.each do |exp|
234
- require "./experiments/#{exp}/#{exp}"
235
- cla = eval(as_class_name(exp))
236
- experiment = cla.new exp, @options.opts, @options.env
237
- experiment.run! @options.cv
238
- end
239
- else
240
- output_usage
241
- end
242
-
243
- end
244
-
245
-
246
- private
247
- def array_merge(h1, h2)
248
- h2.each do |key, value|
249
- h1[key] ||= []
250
- h1[key] << value
251
- end
252
- end
253
-
254
- def as_class_name(str)
255
- str.split(/[\_\-]+/).map(&:capitalize).join
256
- end
257
-
258
- def as_human_name(str)
259
- str.split(/[\_\-]+/).map(&:capitalize).join(" ")
134
+ command = @arguments.shift
135
+ runner = Experiment::Runner.new @arguments, options
136
+ command = "new_project" if command == 'new'
137
+ #begin
138
+ runner.send command.to_sym
139
+ #rescue NoMethodError => e
140
+ # puts "Wrong input #{e.inspect}"
141
+ # output_usage
142
+ #end
260
143
  end
261
144
 
262
145
  def process_standard_input
263
146
  input = @stdin.read
264
- # TO DO - process input
265
-
266
- # [Optional]
267
- # @stdin.each do |line|
268
- # # TO DO - process each line
269
- #end
270
-
271
147
  end
272
148
  end
273
149
 
@@ -0,0 +1,241 @@
1
+ #!/bin/sh
2
+ #-----------------------------------------------------------------------------
3
+ # growl - Send the a message to Mac OS X Growl <http://growl.info> via a
4
+ # Unix shell script.
5
+ #
6
+ # And if this is a Linux or Windows_NT box, use ssh to forward the
7
+ # growl notice to my Mac OS X workstation (taking advantage of
8
+ # previously exchanged ssh so no additional authentication is
9
+ # needed).
10
+ #
11
+ # This script should be somewhere in your PATH. I like to use
12
+ # $HOME/bin for personal scripts, and /usr/local/bin for system
13
+ # wide scripts, with appropriate entries added to PATH. The script
14
+ # needs to be executable:
15
+ #
16
+ # chmod +x $HOME/bin/growl
17
+ #
18
+ # The basics for the Growl Applescript came from the Growl
19
+ # documentation at:
20
+ # <http://growl.info/documentation/applescript-support.php>
21
+ #-----------------------------------------------------------------------------
22
+ # Bob Harris - 2-Jun-2007
23
+ #-----------------------------------------------------------------------------
24
+
25
+
26
+ #--- usage -------------------------------------------------------------------
27
+ usage()
28
+ {
29
+ echo 1>&2 ""
30
+ echo 1>&2 "Usage: growl [options] \"message to display\""
31
+ echo 1>&2 ""
32
+ echo 1>&2 " -sticky - Stays on screen until dismissed [Default]."
33
+ echo 1>&2 " -nosticky - Goes away after several seconds."
34
+ echo 1>&2 " -priority n - Priority -2,-1,0,1,2 [Default: 0]"
35
+ echo 1>&2 " -verylow - priority [-2]"
36
+ echo 1>&2 " -moderate - priority [-1]"
37
+ echo 1>&2 " -normal - priority [0] [Default]"
38
+ echo 1>&2 " -high - priority [1]"
39
+ echo 1>&2 " -emergency - priority [2]"
40
+ echo 1>&2 ""
41
+ echo 1>&2 " Interesting environment variables:"
42
+ echo 1>&2 " G_TITLE - Used as the Growl message title."
43
+ echo 1>&2 " G_APPLICATION_NAME - Used by Growl to manage a set of"
44
+ echo 1>&2 " G_WITH_NAME message configurations."
45
+ echo 1>&2 " See System Preferences -> Growl"
46
+ echo 1>&2 " G_ALL_NAMES - Used to specify 'ALL' the possible"
47
+ echo 1>&2 " G_WITH_NAME values this"
48
+ echo 1>&2 " G_APPLICATION_NAME will ever use."
49
+ echo 1>&2 " Specify something like:"
50
+ echo 1>&2 " G_ALL_NAMES='\"class1\",\"class2\"'"
51
+ echo 1>&2 " export G_ALL_NAMES"
52
+ echo 1>&2 " G_WITH_NAME - Used by Growl to associate a"
53
+ echo 1>&2 " message with a set of Growl"
54
+ echo 1>&2 " notification settings, such as"
55
+ echo 1>&2 " message style and colors associated"
56
+ echo 1>&2 " with different priorities. See"
57
+ echo 1>&2 " System preferences -> Growl"
58
+ echo 1>&2 " Specify something like:"
59
+ echo 1>&2 " G_WITH_NAME='class2'"
60
+ echo 1>&2 " export G_WITH_NAME"
61
+ echo 1>&2 " If G_WITH_NAME is not in"
62
+ echo 1>&2 " G_ALL_NAMES, nothing will be"
63
+ echo 1>&2 " displayed"
64
+ echo 1>&2 " G_APPLICATION_ICON - Display this application's icon in"
65
+ echo 1>&2 " the Growl message (default is"
66
+ echo 1>&2 " Terminal.app, as this is a shell"
67
+ echo 1>&2 " script generated Growl notice)."
68
+ echo 1>&2 ""
69
+ exit 1
70
+ }
71
+
72
+
73
+ #--- defaults ----------------------------------------------------------------
74
+ defaults()
75
+ {
76
+ #
77
+ # These 2 variables are used when this script notices that it is on a Linux
78
+ # or Windows_NT system, then this script uses ssh to forward the request to
79
+ # my Mac OS X workstation. This assumes that ssh keys have been exchanged
80
+ # between the systems so that no passwords are needed. If you don't know
81
+ # what this means, then do a Google search for something like
82
+ # "ssh nopassword key" and you should turn up a number of guides for
83
+ # configuring ssh.
84
+ #
85
+ G_REMOTE="${G_REMOTE:-juggle-mac.us.oracle.com}" # assumes ssh exchanged keys
86
+ G_REMOTE_GROWL="${G_REMOTE_GROWL:-bin/growl}" # growl script remote location
87
+
88
+ #
89
+ # G_APPLICATION_NAME is the name Growl will use in the Growl System
90
+ # Preferences to provide defaults for Display, and to collect each of your
91
+ # notification classes (See G_ALL_NAMES below).
92
+ #
93
+ G_APPLICATION_NAME="${G_APPLICATION_NAME:-Shell Script Growl Message}"
94
+ #
95
+ # G_ALL_NAMES contains a list of all the notification classes to be
96
+ # associated with the G_APPLICATION_NAME. Each notification class can have
97
+ # its own default Display, Priority, and Stickness settings in the Growl
98
+ # System Preferences.
99
+ #
100
+ G_ALL_NAMES="${G_ALL_NAMES:-\"Shell Script Growl Message\",\"Growl Message\"}"
101
+ #
102
+ # The default notification class this message should use, must be in the
103
+ # G_ALL_NAMES list above.
104
+ #
105
+ G_WITH_NAME="${G_WITH_NAME:-Shell Script Growl Message}" # default notification
106
+ #
107
+ G_TITLE="${G_TITLE:-Shell Script Growl Message}" # default title
108
+ G_APPLICATION_ICON="${G_APPLICATION_ICON:-Terminal.app}" # default icon to use
109
+ G_STICKY="${G_STICKY:-yes}" # default sticky setting
110
+ G_PRIORITY="${G_PRIORITY:-0}" # default priority (normal)
111
+ }
112
+
113
+
114
+ #--- growl -------------------------------------------------------------------
115
+ # notify v : Post a notification to be displayed via Growl
116
+ # notify
117
+ # with name string : name of the notification to display
118
+ # title string : title of the notification to display
119
+ # description string : full text of the notification to display
120
+ # application name string : name of the application posting the
121
+ # notification.
122
+ # [image from location location_reference]
123
+ # : Location of the image file to use for this
124
+ # notification. Accepts aliases, paths and
125
+ # file:/// URLs.
126
+ # [icon of file location_reference]
127
+ # : Location of the file whose icon should be
128
+ # used as the image for this notification.
129
+ # Accepts aliases, paths and file:/// URLs.
130
+ # e.g. 'file:///Applications'.
131
+ # [icon of application string]
132
+ # : Name of the application whose icon should
133
+ # be used for this notification. For
134
+ # example, 'Mail.app'.
135
+ # [image Image] : TIFF Image to be used for the
136
+ # notification.
137
+ # [pictImage Picture] : PICT Image to be used for the
138
+ # notification.
139
+ # [sticky boolean] : whether or not the notification displayed
140
+ # should time out. Defaults to 'no'.
141
+ # [priority integer] : The priority of the notification, from -2
142
+ # (low) to 0 (normal) to 2 (emergency).
143
+ #
144
+ growl()
145
+ {
146
+ typeset description="$*"
147
+
148
+ osascript <<EOD
149
+ -- From <http://growl.info/documentation/applescript-support.php>
150
+ --
151
+ tell application "GrowlHelperApp"
152
+ -- Make a list of all the notification types that this script will ever send:
153
+ set the allNotificationsList to {${G_ALL_NAMES}}
154
+
155
+ -- Make a list of the notifications that will be enabled by default.
156
+ -- Those not enabled by default can be enabled later in the 'Applications'
157
+ -- tab of the growl prefpane.
158
+ set the enabledNotificationsList to {"${G_WITH_NAME}"}
159
+
160
+ -- Register our script with growl. You can optionally (as here) set a
161
+ -- default icon for this script's notifications.
162
+ register as application "${G_APPLICATION_NAME}" all notifications allNotificationsList default notifications enabledNotificationsList icon of application "${G_APPLICATION_ICON}"
163
+
164
+ -- Send a Notification...
165
+ notify with name "${G_WITH_NAME}" title "${G_TITLE}" description "${description}" application name "${G_APPLICATION_NAME}" sticky ${G_STICKY} priority ${G_PRIORITY}
166
+
167
+ end tell
168
+ EOD
169
+ }
170
+
171
+
172
+ #--- main --------------------------------------------------------------------
173
+ #{
174
+ if [[ $# = 0 ]]; then
175
+ #
176
+ # No arguments, so give the usage message.
177
+ #
178
+ usage
179
+ exit 1
180
+ fi
181
+ while [[ "X$1" = X-* ]]
182
+ do
183
+ if [[ "X$1" = X-nos* ]]; then
184
+ G_STICKY=no
185
+ elif [[ "X$1" = X-s* ]]; then
186
+ G_STICKY=yes
187
+ elif [[ "X$1" = X-p* ]]; then
188
+ G_PRIORITY="$2"
189
+ G_TITLE="${G_TITLE:-Priority $2}"
190
+ OPTIONS="$OPTIONS $1"
191
+ shift
192
+ elif [[ "X$1" = X-v* ]]; then
193
+ G_PRIORITY="-2"
194
+ G_TITLE="${G_TITLE:-Very Low Priority}"
195
+ elif [[ "X$1" = X-m* ]]; then
196
+ G_PRIORITY="-1"
197
+ G_TITLE="${G_TITLE:-Moderate Priority}"
198
+ elif [[ "X$1" = X-n* ]]; then
199
+ G_PRIORITY="0"
200
+ G_TITLE="${G_TITLE:-Normal Priority}"
201
+ elif [[ "X$1" = X-h* ]]; then
202
+ G_PRIORITY="1"
203
+ G_TITLE="${G_TITLE:-High Priority}"
204
+ elif [[ "X$1" = X-e* ]]; then
205
+ G_PRIORITY="2"
206
+ G_TITLE="${G_TITLE:-Emergency Priority}"
207
+ else
208
+ break;
209
+ fi
210
+ OPTIONS="$OPTIONS $1"
211
+ shift
212
+ done
213
+
214
+ #
215
+ # If any of the option variables have not been set yet, then apply the
216
+ # default values now.
217
+ #
218
+ defaults
219
+
220
+ UNAME=$(uname)
221
+ if [[ "$UNAME" = Darwin ]]; then
222
+ #
223
+ # I'm assuming this is one of my systems where I have Growl
224
+ # installed.
225
+ #
226
+ growl "$*"
227
+ elif [[ "$UNAME" = *Linux* || "$UNAME" = *Windows_NT* ]]; then
228
+ #
229
+ # Must be one of the development systems I work on, so lets ship
230
+ # this request to my Mac OS X workstation.
231
+ #
232
+ ssh ${G_REMOTE} ${G_REMOTE_GROWL} $OPTIONS "$*"
233
+ else
234
+ #
235
+ # I don't know what this is, so I'll just try to Growl anyway. It
236
+ # will most likely fail (no osascript would be my guess), but what
237
+ # do I have to loose at this point!
238
+ #
239
+ growl "$*"
240
+ fi
241
+ #}