aaronp-meow 1.0.0 → 1.1.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.
@@ -1,3 +1,11 @@
1
+ === 1.1.0 / 2008-06-13
2
+
3
+ * 3 major enhancements
4
+
5
+ * Added click callbacks so that Meow can be notified of clicks.
6
+ * Added Meow.run() to block and wait for clicks
7
+ * Meow.import_image() returns an image suitable for icon use
8
+
1
9
  === 1.0.0 / 2008-06-05
2
10
 
3
11
  * 1 major enhancement
@@ -3,7 +3,9 @@ Manifest.txt
3
3
  README.rdoc
4
4
  Rakefile
5
5
  lib/meow.rb
6
+ lib/meow/notifier.rb
6
7
  meow.gemspec
8
+ test/assets/aaron.jpeg
7
9
  test/helper.rb
8
10
  test/test_meow.rb
9
11
  vendor/hoe.rb
@@ -11,6 +11,12 @@ Send Growl notifications via Ruby.
11
11
  meep = Meow.new('Meow Test')
12
12
  meep.notify('Title', 'Description')
13
13
 
14
+ ## Handle clicks
15
+ meep.notify('Click Me', 'Do it!') do
16
+ puts "I got clicked!"
17
+ end
18
+ Meow.start # Start blocks
19
+
14
20
  == REQUIREMENTS:
15
21
 
16
22
  * Growl: http://growl.info
@@ -28,7 +34,7 @@ Thanks to the Growl team! This code is heavily based on their ruby example.
28
34
 
29
35
  (The MIT License)
30
36
 
31
- Copyright (c) 2008 Aaron Patterson
37
+ Copyright (c) 2008 Aaron Patterson, Evan Phoenix, Eric Hodel
32
38
 
33
39
  Permission is hereby granted, free of charge, to any person obtaining
34
40
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require './vendor/hoe.rb'
5
- require './lib/meow.rb'
5
+
6
+ $LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
7
+ require 'meow'
6
8
 
7
9
  Hoe.new('meow', Meow::VERSION) do |p|
8
10
  p.readme = 'README.rdoc'
@@ -1,7 +1,8 @@
1
1
  require 'osx/cocoa'
2
+ require 'meow/notifier'
2
3
 
3
4
  class Meow
4
- VERSION = '1.0.0'
5
+ VERSION = '1.1.0'
5
6
  PRIORITIES = { :very_low => -2,
6
7
  :moderate => -1,
7
8
  :normal => 0,
@@ -9,6 +10,18 @@ class Meow
9
10
  :emergency => 2,
10
11
  }
11
12
 
13
+ GROWL_IS_READY = "Lend Me Some Sugar; I Am Your Neighbor!"
14
+ GROWL_NOTIFICATION_CLICKED = "GrowlClicked!"
15
+ GROWL_NOTIFICATION_TIMED_OUT = "GrowlTimedOut!"
16
+ GROWL_KEY_CLICKED_CONTEXT = "ClickedContext"
17
+
18
+ # This sets up shared state properly that Cocoa uses.
19
+ @@application = OSX::NSApplication.sharedApplication
20
+
21
+ # Holds blocks waiting for clicks
22
+ @@callbacks = Notifier.new
23
+ @@callbacks.setup
24
+
12
25
  class << self
13
26
  ###
14
27
  # Send a message in one call.
@@ -18,6 +31,41 @@ class Meow
18
31
  def notify(name, title, description, opts = {})
19
32
  new(name).notify(title, description, opts)
20
33
  end
34
+
35
+ ##
36
+ # Convert +image+ to an NSImage that displays nicely in growl. If
37
+ # +image+ is a String, it's assumed to be the path to an image
38
+ # on disk and is loaded.
39
+ def import_image(image, size=128)
40
+ if image.kind_of? String
41
+ image = OSX::NSImage.alloc.initWithContentsOfFile image
42
+ end
43
+
44
+ return image if image.size.width.to_i == 128
45
+
46
+ new_image = OSX::NSImage.alloc.initWithSize(OSX.NSMakeSize(size, size))
47
+ new_image.lockFocus
48
+ image.drawInRect_fromRect_operation_fraction(
49
+ OSX.NSMakeRect(0, 0, size, size),
50
+ OSX.NSMakeRect(0, 0, image.size.width, image.size.height),
51
+ OSX::NSCompositeSourceOver, 1.0)
52
+ new_image.unlockFocus
53
+
54
+ return new_image
55
+ end
56
+
57
+ ##
58
+ # Call this if you have passed blocks to #notify. This blocks forever, but
59
+ # it's the only way to properly get events.
60
+ def run
61
+ OSX::NSApp.run
62
+ end
63
+
64
+ ##
65
+ # Call this to cause Meow to stop running.
66
+ def stop
67
+ OSX::NSApp.stop(nil)
68
+ end
21
69
  end
22
70
 
23
71
  attr_accessor :name, :note_type, :icon
@@ -36,6 +84,17 @@ class Meow
36
84
  @icon = icon
37
85
  @note_type = note_type
38
86
  @registered = []
87
+
88
+ @pid = OSX::NSProcessInfo.processInfo.processIdentifier
89
+
90
+ # The notification name to look for when someone clicks on a notify bubble.
91
+ @clicked_name = "#{name}-#{@pid}-GrowlClicked!"
92
+
93
+ notify_center = OSX::NSDistributedNotificationCenter.defaultCenter
94
+ notify_center.addObserver_selector_name_object_ @@callbacks,
95
+ "clicked:",
96
+ @clicked_name,
97
+ nil
39
98
  end
40
99
 
41
100
  ###
@@ -44,6 +103,8 @@ class Meow
44
103
  # * +title+ will be the title of the message.
45
104
  # * +description+ is the description of the message
46
105
  # * +opts+ is a hash of options.
106
+ # * +block+ is an optional block passed to +notify+. The block
107
+ # is called when someone clicks on the growl bubble.
47
108
  #
48
109
  # Possible values for +opts+ are:
49
110
  # * :priority => Set the note priority
@@ -54,32 +115,36 @@ class Meow
54
115
  #
55
116
  # Example:
56
117
  # note.notify('title', 'description', :priority => :very_low)
57
- def notify(title, description, opts = {})
118
+ def notify(title, description, opts = {}, &block)
58
119
  opts = {
59
120
  :icon => icon,
60
121
  :sticky => false,
61
122
  :note_type => note_type,
123
+ :priority => 0
62
124
  }.merge(opts)
63
125
 
64
126
  register(opts[:note_type]) unless @registered.include?(opts[:note_type])
65
127
 
66
128
  notification = {
67
- 'NotificationName' => opts[:note_type],
68
- 'ApplicationName' => name,
69
- 'NotificationTitle' => title,
70
- 'NotificationDescription' => description,
71
- 'NotificationIcon' => opts[:icon].TIFFRepresentation(),
129
+ :ApplicationName => name,
130
+ :ApplicationPID => @pid,
131
+ :NotificationName => opts[:note_type],
132
+ :NotificationTitle => title,
133
+ :NotificationDescription => description,
134
+ :NotificationIcon => opts[:icon].TIFFRepresentation(),
135
+ :NotificationPriority => opts[:priority].to_i
72
136
  }
73
137
 
74
- notification['NotificationAppIcon'] = opts[:app_icon].TIFFRepresentation if opts[:app_icon]
75
- notification['NotificationSticky'] = OSX::NSNumber.numberWithBool_(true) if opts[:stick]
138
+ notification[:NotificationAppIcon] = opts[:app_icon].TIFFRepresentation if opts[:app_icon]
139
+ notification[:NotificationSticky] = OSX::NSNumber.numberWithBool_(true) if opts[:stick]
140
+
141
+ notify_center = OSX::NSDistributedNotificationCenter.defaultCenter
76
142
 
77
- if opts[:priority]
78
- notification['NotificationPriority'] = OSX::NSNumber.numberWithInt_(PRIORITIES[opts[:priority]])
143
+ if block
144
+ notification[:NotificationClickContext] = @@callbacks.add(block)
79
145
  end
80
146
 
81
147
  d = OSX::NSDictionary.dictionaryWithDictionary_(notification)
82
- notify_center = OSX::NSDistributedNotificationCenter.defaultCenter
83
148
  notify_center.postNotificationName_object_userInfo_deliverImmediately_('GrowlNotification', nil, d, true)
84
149
  end
85
150
 
@@ -100,4 +165,5 @@ class Meow
100
165
  notify_center = OSX::NSDistributedNotificationCenter.defaultCenter
101
166
  notify_center.postNotificationName_object_userInfo_deliverImmediately_('GrowlApplicationRegistrationNotification', nil, dictionary, true)
102
167
  end
168
+
103
169
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = %q{meow}
3
- s.version = "1.0.0"
3
+ s.version = "1.1.0"
4
4
 
5
5
  s.specification_version = 2 if s.respond_to? :specification_version=
6
6
 
@@ -1,6 +1,12 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "helper"))
2
2
 
3
3
  class MeowTest < Test::Unit::TestCase
4
+ ASSETS = File.expand_path(File.join(File.dirname(__FILE__), "assets"))
5
+
6
+ def my_method_name
7
+ /`(.*?)'/.match(caller.first)[1]
8
+ end
9
+
4
10
  def test_initialize
5
11
  meep = nil
6
12
  assert_nothing_raised {
@@ -11,28 +17,51 @@ class MeowTest < Test::Unit::TestCase
11
17
 
12
18
  def test_meow_has_static_method
13
19
  assert_nothing_raised {
14
- Meow.notify('Meow Test', 'Title', 'Description', :priority => :very_high)
20
+ Meow.notify('Meow Test', 'Title', my_method_name, :priority => :very_high)
15
21
  }
16
22
  end
17
23
 
18
24
  def test_meow_can_notify_with_type
19
25
  meep = Meow.new('Meow Test')
20
26
  assert_nothing_raised {
21
- meep.notify('Title', 'Description', :type => 'Awesome')
27
+ meep.notify('Title', my_method_name, :type => 'Awesome')
22
28
  }
23
29
  end
24
30
 
25
31
  def test_meow_can_notify_with_priority
26
32
  meep = Meow.new('Meow Test')
27
33
  assert_nothing_raised {
28
- meep.notify('Title', 'Description', :priority => :very_high)
34
+ meep.notify('Title', my_method_name, :priority => :very_high)
29
35
  }
30
36
  end
31
37
 
32
38
  def test_meow_can_notify_without_register
33
39
  meep = Meow.new('Meow Test')
34
40
  assert_nothing_raised {
35
- meep.notify('Title', 'Description')
41
+ meep.notify('Title', my_method_name)
42
+ }
43
+ end
44
+
45
+ def test_import_image
46
+ icon = Meow.import_image(File.join(ASSETS, 'aaron.jpeg'))
47
+ assert_kind_of(OSX::NSImage, icon)
48
+ meep = Meow.new('Meow Test')
49
+ assert_nothing_raised {
50
+ meep.notify('Icon', my_method_name, :icon => icon)
51
+ }
52
+ end
53
+
54
+ def test_clicks_work
55
+ $RUBYCOCOA_SUPPRESS_EXCEPTION_LOGGING = true
56
+ block_called = false
57
+ assert_raises(RuntimeError) {
58
+ meep = Meow.new('Meow Test')
59
+ meep.notify('Click Here', my_method_name) do
60
+ block_called = true
61
+ raise 'I do not know how to get run to stop blocking!'
62
+ end
63
+ Meow.run
36
64
  }
65
+ assert block_called
37
66
  end
38
67
  end
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require 'rake'
5
- require 'rake/contrib/sshpublisher'
6
5
  require 'rake/gempackagetask'
7
6
  require 'rake/rdoctask'
8
7
  require 'rake/testtask'
@@ -64,8 +63,8 @@ require 'yaml'
64
63
  # exclude:: A regular expression of files to exclude from
65
64
  # +check_manifest+.
66
65
  # publish_on_announce:: Run +publish_docs+ when you run +release+.
67
- # signing_key_file:: Signs your gems with this private key.
68
- # signing_cert_file:: Signs your gem with this certificate.
66
+ # signing_key_file:: Signs your gems with this private key.
67
+ # signing_cert_file:: Signs your gem with this certificate.
69
68
  # blogs:: An array of hashes of blog settings.
70
69
  #
71
70
  # Run +config_hoe+ and see ~/.hoerc for examples.
@@ -116,7 +115,7 @@ require 'yaml'
116
115
  #
117
116
 
118
117
  class Hoe
119
- VERSION = '1.5.1'
118
+ VERSION = '1.5.3'
120
119
 
121
120
  ruby_prefix = Config::CONFIG['prefix']
122
121
  sitelibdir = Config::CONFIG['sitelibdir']
@@ -214,6 +213,11 @@ class Hoe
214
213
 
215
214
  attr_accessor :lib_files # :nodoc:
216
215
 
216
+ ##
217
+ # Optional: Array of incompatible versions for multiruby filtering. Used as a regex.
218
+
219
+ attr_accessor :multiruby_skip
220
+
217
221
  ##
218
222
  # *MANDATORY*: The name of the release.
219
223
 
@@ -229,6 +233,11 @@ class Hoe
229
233
 
230
234
  attr_accessor :need_zip
231
235
 
236
+ ##
237
+ # Optional: A post-install message to be displayed when gem is installed.
238
+
239
+ attr_accessor :post_install_message
240
+
232
241
  ##
233
242
  # Optional: A regexp to match documentation files against the manifest.
234
243
 
@@ -310,6 +319,7 @@ class Hoe
310
319
  self.description_sections = %w(description)
311
320
  self.email = []
312
321
  self.extra_deps = []
322
+ self.multiruby_skip = []
313
323
  self.need_tar = true
314
324
  self.need_zip = false
315
325
  self.rdoc_pattern = /^(lib|bin|ext)|(txt|rdoc)$/
@@ -321,12 +331,18 @@ class Hoe
321
331
  self.test_globs = ['test/**/test_*.rb']
322
332
  self.readme = 'README.txt'
323
333
  self.history = 'History.txt'
334
+ self.post_install_message = nil
324
335
 
325
336
  yield self if block_given?
326
337
 
327
338
  # Intuit values:
328
339
 
329
- readme = File.read(self.readme).split(/^(=+ .*)$/)[1..-1]
340
+ def missing name
341
+ warn "** #{name} is missing or in the wrong format for auto-intuiting."
342
+ warn " run `sow blah` and look at its text files"
343
+ end
344
+
345
+ readme = File.read(self.readme).split(/^(=+ .*)$/)[1..-1] rescue ''
330
346
  unless readme.empty? then
331
347
  sections = readme.map { |s|
332
348
  s =~ /^=/ ? s.strip.downcase.chomp(':').split.last : s.strip
@@ -336,14 +352,20 @@ class Hoe
336
352
  summ = desc.split(/\.\s+/).first(summary_sentences).join(". ")
337
353
 
338
354
  self.description ||= desc
339
- self.changes ||= File.read(self.history).split(/^(===.*)/)[1..2].join.strip
340
355
  self.summary ||= summ
341
356
  self.url ||= readme[1].gsub(/^\* /, '').split(/\n/).grep(/\S+/)
342
357
  else
343
- warn "** README.txt is in the wrong format for auto-intuiting."
344
- warn " run sow blah and look at it's text files"
358
+ missing 'README.txt'
345
359
  end
346
360
 
361
+ self.changes ||= begin
362
+ h = File.read(self.history)
363
+ h.split(/^(===.*)/)[1..2].join.strip
364
+ rescue
365
+ missing 'History.txt'
366
+ ''
367
+ end
368
+
347
369
  %w(email author).each do |field|
348
370
  value = self.send(field)
349
371
  if value.nil? or value.empty? then
@@ -351,7 +373,7 @@ class Hoe
351
373
  warn "Hoe #{field} value not set - Fix by 2008-04-01!"
352
374
  self.send "#{field}=", "doofus"
353
375
  else
354
- abort "Hoe #{field} value not set"
376
+ abort "Hoe #{field} value not set. aborting"
355
377
  end
356
378
  end
357
379
  end
@@ -455,6 +477,8 @@ class Hoe
455
477
  s.extra_rdoc_files = s.files.grep(/txt$/)
456
478
  s.has_rdoc = true
457
479
 
480
+ s.post_install_message = post_install_message
481
+
458
482
  if test ?f, "test/test_all.rb" then
459
483
  s.test_file = "test/test_all.rb"
460
484
  else
@@ -471,13 +495,11 @@ class Hoe
471
495
  if ENV['INLINE'] then
472
496
  s.platform = ENV['FORCE_PLATFORM'] || Gem::Platform::CURRENT
473
497
  # name of the extension is CamelCase
474
- if name =~ /[A-Z]/
475
- # ClassName => class_name
476
- alternate_name = name.reverse.scan(%r/[A-Z]+|[^A-Z]*[A-Z]+?/).reverse.map { |word| word.reverse.downcase }.join('_')
477
- elsif name =~ /_/
478
- # class_name = ClassName
479
- alternate_name = name.strip.split(/\s*_+\s*/).map! { |w| w.downcase.sub(/^./) { |c| c.upcase } }.join
480
- end
498
+ alternate_name = if name =~ /[A-Z]/ then
499
+ name.gsub(/([A-Z])/, '_\1').downcase.sub(/^_/, '')
500
+ elsif name =~ /_/ then
501
+ name.capitalize.gsub(/_([a-z])/) { $1.upcase }
502
+ end
481
503
 
482
504
  # Try collecting Inline extensions for +name+
483
505
  if defined?(Inline) then
@@ -539,7 +561,7 @@ class Hoe
539
561
  puts "rf.add_file #{rubyforge_name.inspect}, #{name.inspect}, release_id, \"#{pkg}.gem\""
540
562
  end
541
563
 
542
- rf = RubyForge.new
564
+ rf = RubyForge.new.configure
543
565
  puts "Logging in"
544
566
  rf.login
545
567
 
@@ -609,7 +631,7 @@ class Hoe
609
631
  task :clean => [ :clobber_docs, :clobber_package ] do
610
632
  clean_globs.each do |pattern|
611
633
  files = Dir[pattern]
612
- rm_rf files unless files.empty?
634
+ rm_rf files, :verbose => true unless files.empty?
613
635
  end
614
636
  end
615
637
 
@@ -688,7 +710,7 @@ class Hoe
688
710
  require 'rubyforge'
689
711
  subject, title, body, urls = announcement
690
712
 
691
- rf = RubyForge.new
713
+ rf = RubyForge.new.configure
692
714
  rf.login
693
715
  rf.post_news(rubyforge_name, subject, "#{title}\n\n#{body}")
694
716
  puts "Posted to rubyforge"
@@ -703,7 +725,8 @@ class Hoe
703
725
  require 'find'
704
726
  files = []
705
727
  with_config do |config, _|
706
- exclusions = config["exclude"] || /tmp$|CVS|\.svn/
728
+ exclusions = config["exclude"]
729
+ abort "exclude entry missing from .hoerc. Aborting." if exclusions.nil?
707
730
  Find.find '.' do |path|
708
731
  next unless File.file? path
709
732
  next if path =~ exclusions
@@ -742,7 +765,7 @@ class Hoe
742
765
 
743
766
  puts "Installed key and certificate."
744
767
 
745
- rf = RubyForge.new
768
+ rf = RubyForge.new.configure
746
769
  rf.login
747
770
 
748
771
  cert_package = "#{rubyforge_name}-certificates"
@@ -788,7 +811,11 @@ class Hoe
788
811
  tests.map! {|f| %Q(require "#{f}")}
789
812
  "#{RUBY_FLAGS} -e '#{tests.join("; ")}' #{FILTER}"
790
813
  end
814
+
815
+ excludes = multiruby_skip.join(":")
816
+ ENV['EXCLUDED_VERSIONS'] = excludes
791
817
  cmd = "multiruby #{cmd}" if multi
818
+
792
819
  send msg, cmd
793
820
  end
794
821
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aaronp-meow
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Patterson