herpes 0.0.1.2 → 0.0.2.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/bin/herpes CHANGED
@@ -10,8 +10,8 @@ fail 'no configuration file passed' if ARGV.empty?
10
10
 
11
11
  herpes = Herpes.load(*ARGV)
12
12
 
13
- trap 'INT' do
14
- herpes.stop!
15
- end
13
+ END {
14
+ herpes.stop
15
+ }
16
16
 
17
- herpes.start!
17
+ herpes.start
data/examples/rss.rb CHANGED
@@ -2,6 +2,7 @@ require 'herpes/rss'
2
2
  require 'herpes/email'
3
3
 
4
4
  state '~/.herpes'
5
+ save_every 5.minutes
5
6
 
6
7
  # load the RSS module
7
8
  use :rss do
@@ -18,10 +19,7 @@ use :rss do
18
19
  register 'http://feeds.feedburner.com/incomaemeglio', :smeriglia
19
20
  register 'https://github.com/blog.atom'
20
21
  end
21
- end
22
22
 
23
- # only events coming from the RSS module
24
- from :rss do
25
23
  # define some common helper methods on every event
26
24
  before do |event|
27
25
  require 'nokogiri'
data/lib/herpes/email.rb CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  require 'pony'
12
12
 
13
- Herpes::Notifier.define :email, :mail do
13
+ Herpes::Module.define :email, :mail do
14
14
  @options = %w(from to cc bcc sender subject headers charset text_part_charset message_id via via_options attachments)
15
15
 
16
16
  plain_accessor *@options
data/lib/herpes/module.rb CHANGED
@@ -29,18 +29,45 @@ class Module
29
29
 
30
30
  attr_reader :name, :aliases, :owner
31
31
  def_delegators :owner, :state
32
+ plain_accessor :check_every
32
33
 
33
34
  def initialize (name, *aliases, &block)
34
35
  @name = name
35
36
  @aliases = aliases
36
37
 
38
+ @before = []
39
+ @matchers = []
40
+ @after = []
41
+
37
42
  instance_eval &block
38
43
  end
39
44
 
40
- def =~ (other)
41
- return true if self == other
45
+ def method_missing (id, *args, &block)
46
+ return owner.__send__ id, *args, &block if owner and owner.respond_to?(id)
42
47
 
43
- name.to_s.downcase == other.to_s.downcase || aliases.any? { |a| a.to_s.downcase == other.to_s.downcase }
48
+ super
49
+ end
50
+
51
+ def owner= (value)
52
+ @owner = value
53
+
54
+ owned(value) if respond_to? :owned
55
+
56
+ if respond_to? :check
57
+ owner.every(check_every, self, &method(:check))
58
+ end
59
+
60
+ @before.each {|matcher|
61
+ owner.before *matcher.arguments, &matcher.block
62
+ }
63
+
64
+ @matchers.each {|matcher|
65
+ owner.on *matcher.arguments, &matcher.block
66
+ }
67
+
68
+ @after.each {|matcher|
69
+ owner.after *matcher.arguments, &matcher.block
70
+ }
44
71
  end
45
72
 
46
73
  def default (&block)
@@ -57,34 +84,48 @@ class Module
57
84
  clone.tap { |o| o.instance_eval &block }
58
85
  end
59
86
 
60
- def use (*)
61
- raise NotImplementedError, 'you have to use a specialized module'
62
- end
87
+ def use (owner, &block)
88
+ with {
89
+ self.owner = owner
63
90
 
64
- def inspect
65
- "#<#{self.class.name}(#{name}#{" [#{aliases.join ', '}]" unless aliases.empty?})>"
91
+ instance_eval &block
92
+ }
66
93
  end
67
- end
68
-
69
- class Generator < Module
70
- plain_accessor :check_every
71
94
 
72
- def initialize (*)
73
- super
95
+ def before (*args, &block)
96
+ if owner = self.owner
97
+ owner.from name do
98
+ owner.before *args do |*args|
99
+ owner.instance_exec *args, &block
100
+ end
101
+ end
102
+ else
103
+ @before << Struct.new(:arguments, :block).new(args, block)
104
+ end
74
105
  end
75
106
 
76
- def use (owner, &block)
77
- with(&block).tap {|o|
78
- o.instance_eval {
79
- @owner = owner
80
-
81
- owned if respond_to? :owned
107
+ def on (*args, &block)
108
+ if owner = self.owner
109
+ owner.from name do
110
+ owner.on *args do |*args|
111
+ owner.instance_exec *args, &block
112
+ end
113
+ end
114
+ else
115
+ @matchers << Struct.new(:arguments, :block).new(args, block)
116
+ end
117
+ end
82
118
 
83
- if respond_to? :check
84
- @owner.every(check_every, &method(:check))
119
+ def after (*args, &block)
120
+ if owner = self.owner
121
+ owner.from name do
122
+ owner.after *args do |*args|
123
+ owner.instance_exec *args, &block
85
124
  end
86
- }
87
- }
125
+ end
126
+ else
127
+ @after << Struct.new(:arguments, :block).new(args, block)
128
+ end
88
129
  end
89
130
 
90
131
  def dispatch (event = nil, &block)
@@ -98,31 +139,15 @@ class Generator < Module
98
139
 
99
140
  owner.dispatch(event)
100
141
  end
101
- end
102
-
103
- class Notifier < Module
104
- def initialize (*)
105
- @matchers = []
106
142
 
107
- super
108
- end
143
+ def =~ (other)
144
+ return true if self == other
109
145
 
110
- def on (*args, &block)
111
- @matchers << Struct.new(:arguments, :block).new(args, block)
146
+ name.to_s.downcase == other.to_s.downcase || aliases.any? { |a| a.to_s.downcase == other.to_s.downcase }
112
147
  end
113
148
 
114
- def use (owner, &block)
115
- with(&block).tap {|o|
116
- o.instance_eval {
117
- @owner = owner
118
-
119
- owned if respond_to? :owned
120
-
121
- @matchers.each {|matcher|
122
- @owner.on *matcher.arguments, &matcher.block
123
- }
124
- }
125
- }
149
+ def inspect
150
+ "#<#{self.class.name}(#{name}#{" [#{aliases.join ', '}]" unless aliases.empty?})>"
126
151
  end
127
152
  end
128
153
 
@@ -0,0 +1,18 @@
1
+ #--
2
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
3
+ # Version 2, December 2004
4
+ #
5
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
6
+ # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
7
+ #
8
+ # 0. You just DO WHAT THE FUCK YOU WANT TO.
9
+ #++
10
+
11
+ Herpes::Module.define :nerdz do
12
+ plain_accessor :username, :password
13
+
14
+ check_every 2.minutes
15
+
16
+ def check
17
+ end
18
+ end
data/lib/herpes/rss.rb CHANGED
@@ -11,7 +11,7 @@
11
11
  require 'rss'
12
12
  require 'open-uri'
13
13
 
14
- Herpes::Generator.define :rss do
14
+ Herpes::Module.define :rss do
15
15
  plain_accessor :digest
16
16
 
17
17
  check_every 5.minutes
@@ -21,18 +21,25 @@ Herpes::Generator.define :rss do
21
21
 
22
22
  def tag (*tags, &block)
23
23
  @tags.push tags
24
- instance_eval &block
24
+ result = instance_eval &block
25
25
  @tags.pop
26
+
27
+ result
26
28
  end
27
29
 
28
30
  def group (group, &block)
29
31
  @group, tmp = group, @group
30
- instance_eval &block
32
+ result = instance_eval &block
31
33
  @group = tmp
34
+
35
+ result
32
36
  end
33
37
 
34
38
  def register (url, name = nil)
35
39
  @rss << Struct.new(:url, :name, :tags, :group).new(url, name, @tags.flatten, @group)
40
+ @rss.uniq!
41
+
42
+ self
36
43
  end
37
44
 
38
45
  def check
@@ -0,0 +1,13 @@
1
+ #--
2
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
3
+ # Version 2, December 2004
4
+ #
5
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
6
+ # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
7
+ #
8
+ # 0. You just DO WHAT THE FUCK YOU WANT TO.
9
+ #++
10
+
11
+ Herpes::Module.define :server do
12
+ plain_accessor :bind, :port
13
+ end
@@ -10,6 +10,6 @@
10
10
 
11
11
  class Herpes
12
12
  def self.version
13
- '0.0.1.2'
13
+ '0.0.2.1'
14
14
  end
15
15
  end
data/lib/herpes.rb CHANGED
@@ -15,14 +15,15 @@ require 'herpes/module'
15
15
 
16
16
  class Herpes
17
17
  class Callback
18
- attr_reader :time, :block, :last
18
+ attr_reader :time, :discriminator, :block, :last
19
19
 
20
- def initialize (time, one_shot = false, &block)
20
+ def initialize (time, discriminator, one_shot = false, &block)
21
21
  raise ArgumentError, 'no block has been passed' unless block
22
22
 
23
- @time = time
24
- @one_shot = one_shot
25
- @block = block
23
+ @time = time
24
+ @discriminator = discriminator
25
+ @one_shot = one_shot
26
+ @block = block
26
27
 
27
28
  if !one_shot?
28
29
  @last = Time.now - time
@@ -48,7 +49,7 @@ class Herpes
48
49
  end
49
50
 
50
51
  def calling!
51
- @calling = :gonna
52
+ @calling = true
52
53
  end
53
54
 
54
55
  def called!
@@ -60,12 +61,14 @@ class Herpes
60
61
  @calling == true
61
62
  end
62
63
 
63
- def call (*args, &block)
64
+ def call (herpes, &block)
64
65
  return if calling?
65
66
 
66
67
  calling!
67
- @block.call(*args, &block)
68
+ @block.call(&block)
68
69
  called!
70
+
71
+ herpes.wake_up
69
72
  end
70
73
  end
71
74
 
@@ -103,12 +106,20 @@ class Herpes
103
106
  end
104
107
  end
105
108
 
109
+ def save_every (time)
110
+ cancel { |c| c.discriminator == self }
111
+
112
+ every time, self do save end
113
+ end
114
+
106
115
  def save
107
116
  return unless @state && @path
108
117
 
109
- dump = Marshal.dump(@state)
118
+ Marshal.dump(@state).tap {|dump|
119
+ File.open(@path, 'wb') { |f| f.write(dump) }
120
+ }
110
121
 
111
- File.open(@path, 'wb') { |f| f.write(dump) }
122
+ self
112
123
  end
113
124
 
114
125
  def load (*paths)
@@ -141,17 +152,30 @@ class Herpes
141
152
  end
142
153
 
143
154
  def before (&block)
144
- @before[@current] = block
155
+ return unless block
156
+
157
+ @before[@current] << block
158
+ @before[@current].uniq!
159
+
160
+ self
145
161
  end
146
162
 
147
163
  def on (matcher, &block)
148
164
  return unless block
149
165
 
150
166
  @matchers[@current] << Struct.new(:matcher, :block).new(matcher, block)
167
+ @matchers[@current].uniq!
168
+
169
+ self
151
170
  end
152
171
 
153
172
  def after (&block)
154
- @after[@current] = block
173
+ return unless block
174
+
175
+ @after[@current] << block
176
+ @after[@current].uniq!
177
+
178
+ self
155
179
  end
156
180
 
157
181
  def dispatch (event = nil, &block)
@@ -161,10 +185,10 @@ class Herpes
161
185
 
162
186
  raise ArgumentError, 'you did not pass an Event' unless event.is_a?(Event)
163
187
 
164
- @before.each {|name, block|
188
+ @before.each {|name, blocks|
165
189
  next unless name.nil? || (event.generated_by && event.generated_by =~ name)
166
190
 
167
- block.call(event)
191
+ blocks.each { |b| b.call(event) }
168
192
  }
169
193
 
170
194
  @matchers.each {|name, matchers|
@@ -184,62 +208,82 @@ class Herpes
184
208
  }
185
209
  }
186
210
 
187
- @after.each {|name, block|
211
+ @after.each {|name, blocks|
188
212
  next unless name.nil? || (event.generated_by && event.generated_by =~ name)
189
213
 
190
- block.call(event)
214
+ blocks.each { |b| b.call(event) }
191
215
  }
192
216
  end
193
217
 
194
- def every (time, &block)
195
- @callbacks << Callback.new(time, &block)
218
+ def every (time, discriminator = nil, &block)
219
+ @callbacks << Callback.new(time, discriminator, &block)
196
220
  wake_up
197
221
  end
198
222
 
199
- def after (time, &block)
200
- @callbacks << Callback.new(time, true, &block)
223
+ def once (time, discriminator = nil, &block)
224
+ @callbacks << Callback.new(time, discriminator, true, &block)
225
+ wake_up
226
+ end; alias once_after once
227
+
228
+ def cancel (&block)
229
+ @callbacks.reject!(&block)
201
230
  wake_up
202
231
  end
203
232
 
204
233
  def until_next
205
- next_in = @callbacks.min_by(&:next_in).next_in
234
+ callbacks = @callbacks.reject(&:calling?).reject(&:gonna_call?)
235
+
236
+ return if callbacks.empty?
237
+
238
+ next_in = callbacks.min_by(&:next_in).next_in
206
239
 
207
- next_in > 0 ? next_in : nil
208
- rescue
209
- nil
240
+ next_in > 0 ? next_in : 0
210
241
  end
211
242
 
212
- def running?; !!@running; end
213
- def stopped?; !@running; end
243
+ def running?; @running; end
244
+ def stopped?; @stopped; end
214
245
 
215
- def start!
246
+ def start
216
247
  @running = true
217
248
 
218
249
  while running?
219
- sleep until_next
250
+ begin
251
+ sleep until_next
252
+ rescue Interrupt
253
+ break
254
+ end
220
255
 
221
256
  @callbacks.select {|callback|
222
257
  callback.next_in <= 0
223
- }.uniq.each {|callback|
258
+ }.each {|callback|
224
259
  @callbacks.delete(callback) if callback.one_shot?
225
260
 
226
- next if callback.gonna_call?
261
+ next if callback.gonna_call? or callback.calling?
227
262
 
228
263
  callback.gonna_call!
229
264
 
230
265
  process {
231
- callback.call
266
+ callback.call(self)
232
267
  }
233
268
  }
234
269
  end
235
270
 
236
271
  save
272
+
273
+ @stopped = true
237
274
  end
238
275
 
239
276
  def stop!
240
277
  @running = false
278
+
241
279
  wake_up
242
280
 
243
281
  @pool.kill
244
282
  end
283
+
284
+ def stop
285
+ stop!
286
+
287
+ sleep 0.01 until stopped?
288
+ end
245
289
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: herpes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.2
4
+ version: 0.0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-25 00:00:00.000000000 Z
12
+ date: 2011-12-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: threadpool
16
- requirement: &19904260 !ruby/object:Gem::Requirement
16
+ requirement: &10404920 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *19904260
24
+ version_requirements: *10404920
25
25
  description:
26
26
  email: meh@paranoici.org
27
27
  executables:
@@ -39,7 +39,9 @@ files:
39
39
  - lib/herpes/event.rb
40
40
  - lib/herpes/extensions.rb
41
41
  - lib/herpes/module.rb
42
+ - lib/herpes/nerdz.rb
42
43
  - lib/herpes/rss.rb
44
+ - lib/herpes/server.rb
43
45
  - lib/herpes/version.rb
44
46
  homepage: http://github.com/meh/herpes
45
47
  licenses: []