sup_tag 0.1.2 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -6,37 +6,102 @@ A gem to make tagging messages in sup cleaner.
6
6
  Usage
7
7
  =====
8
8
 
9
- This currently supports two methods to add tags, tag and archive. Tag adds tags
10
- but does not remove the inbox tag. Archive will add a tag and remove the inbox
11
- tag.
9
+ Messages are tagged using by either the tag or archive block. The tag block will
10
+ add the labels while archive adds labels and removes the inbox tag. Each block
11
+ consists of methods of the message to call, what they should match against and
12
+ the tags to add if the messages match. Tags must always be a symbol, while the
13
+ queries may be either strings or regular expressions. It's easiest to see with
14
+ an example:
12
15
 
13
- Example
14
- -------
15
-
16
- My before-add-message.rb looks like:
16
+ tag do
17
+ from 'blake', :self
18
+ end
17
19
 
18
- require 'sup_tag'
19
- require 'sup_tag/extensions/object'
20
+ This would tag any message from 'blake' with self. If no tag is provided then
21
+ the given queries are converted to strings and used as labels. For example:
20
22
 
21
- # Tag messages
22
23
  tag do
23
- from /jnls.cust.serv@oxfordjournals.org/i, :oxford
24
- from /some_email/i, :tag1, :tag2
24
+ from /blake/i
25
+ end
26
+
27
+ Here if a message is from 'blake' the message would be tagged as 'blake'. It is
28
+ possible to use several queries in one rule as well.
29
+
30
+ archive do
31
+ from /blake/, /sweeney/, :self
32
+ end
33
+
34
+ This would archive any message where the from matches both 'blake' and
35
+ 'sweeney' as self and the inbox tag would be removed. If the self tag had not
36
+ been provided then the message would have been tagged as both 'blake' and
37
+ 'sweeney'. Tag and archive blocks may have many rules. For example:
38
+
39
+ tag
40
+ from /blake/, :self
41
+ subj /sup-talk/i
42
+ end
43
+
44
+ Here messages from 'blake' are marked as self, while messages with 'sup-talk' in
45
+ the subject line are marked as sup talk.
46
+
47
+ If you wish to tag against several different fields then simply use a multi
48
+ block. A multi block will require that all rules in the block hit in order to
49
+ tag.
50
+
51
+ tag
52
+ multi :ann, 'ruby-talk'.to_sym do
53
+ recipients /ruby-talk/
54
+ subj /ANN/
55
+ end
25
56
  end
26
57
 
27
- # Archive messages
58
+ This would tag any messages going to 'ruby-talk' with 'ANN' in the subject line.
59
+ If tags are provided to the rules in the multi block they will be ignored.
60
+
61
+ There are some other probably less useful options. It is possible to archive a
62
+ message directly without adding any tags. To do this provide a nil as the tag.
63
+
28
64
  archive do
29
- subj /sup-talk/i # Tag messages with sup-talk in subject as sup-talk
65
+ from /Boring/i, nil
30
66
  end
31
67
 
32
- This tags messages from jnls as oxford and leaves them in my inbox. Messages
33
- from some\_email are given tag1, tag2. Messages from sup-talk are given the
34
- sup-talk label and the inbox label is removed.
68
+ This will archive any message from 'Boring' without adding any tags.
69
+
70
+ Example
71
+ -------
72
+
73
+ My before-add-message.rb looks something like:
74
+
75
+ require 'sup_tag'
76
+ require "sup_tag/extensions/object"
77
+
78
+ archive do
79
+ subj /sup-talk/i
80
+ subj /MongoMapper/i, :MM
81
+ subj /easyb-users/i, :easyb
82
+ recipients /ruby-talk/i
83
+ recipients /vim(_|-)mac/i, :vim
84
+ recipients /buildr.apache.org/i, :buildr
85
+
86
+ multi :ann do
87
+ recipients /ruby-talk/i
88
+ subj /ANN/i
89
+ end
90
+ end
35
91
 
92
+ tag do
93
+ subj /BIOL\.1010/, :ta
94
+ subj /BIOL\.5870/, :ta
95
+ from /Mbuthia/, :ta
96
+ subj /Nucl. Acids Res/, :nar
97
+ subj /Database Table of Contents/, :biodb
98
+ from /rna@faseb.org/i, :rna
99
+ from /jnls.cust.serv@oxfordjournals.org/, :oxford
100
+ end
36
101
 
37
102
  Note on Patches/Pull Requests
38
103
  =============================
39
-
104
+
40
105
  * Fork the project.
41
106
  * Make your feature addition or bug fix.
42
107
  * Add tests for it. This is important so I don't break it in a
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.2.1
data/lib/sup_tag.rb CHANGED
@@ -6,6 +6,7 @@ class SupTag
6
6
  # @param [Redwood::Message] message A Message to tag.
7
7
  def initialize(message)
8
8
  @message = message
9
+ @add = true
9
10
  end
10
11
 
11
12
  # Remove the given tags from the message.
@@ -23,9 +24,8 @@ class SupTag
23
24
  # @param [Block] block Block to add tags.
24
25
  # @return [Array] Tags on the message.
25
26
  def archive(&block)
26
- @match = false
27
- cloaker(&block).bind(self).call
28
- remove(:inbox) if @match
27
+ tag(&block)
28
+ remove(:inbox) if @labels
29
29
  return @message.labels
30
30
  end
31
31
 
@@ -34,8 +34,27 @@ class SupTag
34
34
  # @param [Block] Block for adding tags.
35
35
  # @return [Array] The tags on the message.
36
36
  def tag(&block)
37
+ @labels = nil
37
38
  cloaker(&block).bind(self).call
38
- @message.labels
39
+ @labels.each { |l| @message.add_label(l) } if @labels
40
+ return @message.labels
41
+ end
42
+
43
+ # Test queries across several feilds to add tags.
44
+ #
45
+ # @param [Symbol, Array] labels Labels to add.
46
+ # @param [Block] Block for adding tags.
47
+ # @return [Array] The tags on the message
48
+ def multi(*labels, &block)
49
+ @multi = true
50
+ @add = false
51
+ cloaker(&block).bind(self).call
52
+ @add = true
53
+ if @multi
54
+ @labels.concat(labels)
55
+ @match = true
56
+ end
57
+ return @message.labels
39
58
  end
40
59
 
41
60
  # Instance eval for blocks stolen from Trollop. Orignally from:
@@ -54,21 +73,52 @@ class SupTag
54
73
  end
55
74
  end
56
75
 
76
+ # Override to include methods from messages.
57
77
  def respond_to?(method, include_private = false)
58
78
  return @message.respond_to?(method) || super
59
79
  end
60
80
 
61
- def method_missing(method, *args)
81
+ # Override method missing to allow for matching the results of
82
+ # a method on message against some queries.
83
+ def method_missing(method, *args, &block)
62
84
  super if !respond_to?(method)
63
-
64
- match = args.shift
65
- match_string = (match.is_a?(Regexp) ? match.source : match.to_s)
66
- tags = (args.empty? ? [match_string.downcase] : args).compact
67
- query = @message.send(method)
68
- if (!query.is_a?(Array) && query.to_s.match(match)) ||
69
- (query.is_a?(Array) && query.any? { |q| q.to_s.match(match) } )
70
- @match = true
71
- tags.map { |t| @message.add_label(t) }
85
+ parts = split_args(args)
86
+ queries = parts.first
87
+ results = Array(@message.send(method))
88
+ count = match_args(results, queries)
89
+ if count.size == queries.size
90
+ @labels ||= []
91
+ @multi &= true
92
+ @labels.concat(parts.last.compact) if @add
93
+ else
94
+ @multi = false
72
95
  end
73
96
  end
97
+
98
+ private
99
+ # Split the arguments into labels and queries.
100
+ #
101
+ # @param [Array] arguments Arguments to split.
102
+ def split_args(arguments)
103
+ parts = arguments.partition { |e| !e.is_a?(Symbol) && e }
104
+
105
+ # Generate labels if none given
106
+ if parts[1].empty?
107
+ parts[1] = parts[0].map do |part|
108
+ (part.is_a?(Regexp) ? part.source : part.to_s).downcase
109
+ end
110
+ end
111
+
112
+ return parts
113
+ end
114
+
115
+ # Match the results against the queries and count how many match.
116
+ #
117
+ # @param [Array] results Results to check.
118
+ # @param [Array] queries Queries to look for.
119
+ def match_args(results, queries)
120
+ queries.map do |query|
121
+ (results.any? { |r| r.to_s.match(query) } ? 1 : nil)
122
+ end.compact
123
+ end
74
124
  end
@@ -1,3 +1,4 @@
1
+ require 'sup_tag/extensions/binding'
1
2
  # Modify Object to support tag and archive methods.
2
3
 
3
4
  class Object
@@ -25,6 +26,6 @@ class Object
25
26
  # @param [Block] A Block to generate the tagger object with.
26
27
  # @return [SupTag] A SupTag object.
27
28
  def get_tagger(&block)
28
- return SupTag.new(eval("lambda { message }", block.binding).call)
29
+ return SupTag.new(block.binding[:message])
29
30
  end
30
31
  end
@@ -0,0 +1,12 @@
1
+ # Modify Binding to extract value.
2
+
3
+ class Binding
4
+
5
+ # Get the value of a variable of method in this binding.
6
+ #
7
+ # @param [Symbol, String] name Object to get value of.
8
+ # @return [Object] The value.
9
+ def [](name)
10
+ return eval("lambda { #{name.to_s} }", self).call
11
+ end
12
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
  require 'sup_tag'
4
+ require 'sup_tag/extensions/object'
5
+ require 'sup_tag/extensions/binding'
4
6
  require "rubygems"
5
7
  require "sup"
6
- require 'spec'
7
- require 'spec/autorun'
8
8
  require 'stringio'
9
9
  require 'rmail'
10
10
  require 'uri'
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Binding' do
4
+ context '[]' do
5
+ it 'can get the value of a variable' do
6
+ @message = 'hi'
7
+ binding[:@message].should == 'hi'
8
+ end
9
+ it 'can get the value of a method' do
10
+ def bob
11
+ return 'jones'
12
+ end
13
+ binding['bob'].should == 'jones'
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
- require 'sup_tag/extensions/object'
1
+ require 'spec_helper'
3
2
 
4
3
  describe 'Object' do
5
4
  before do
@@ -1,6 +1,11 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe "SupTag" do
4
+ before do
5
+ @mess = get_short_message
6
+ @tagger = SupTag.new(@mess)
7
+ end
8
+
4
9
  context 'respond_to' do
5
10
  it 'responds to taggable methods' do
6
11
  [ :from, :subj, :to, :replyto ].each do |meth|
@@ -10,11 +15,6 @@ describe "SupTag" do
10
15
  end
11
16
 
12
17
  context 'tags' do
13
- before do
14
- @mess = get_short_message
15
- @tagger = SupTag.new(@mess)
16
- end
17
-
18
18
  context 'removing tags' do
19
19
  it 'can remove a given tag' do
20
20
  @mess.add_label(:t)
@@ -84,6 +84,51 @@ describe "SupTag" do
84
84
  end
85
85
  @mess.labels.should == Set[:old]
86
86
  end
87
+ it 'can tag using several criteria at once' do
88
+ @tagger.tag do
89
+ date /2/, /7/, :self
90
+ end
91
+ @mess.labels.should == Set[:self]
92
+ end
93
+ it 'requires all criteria to match' do
94
+ @tagger.tag do
95
+ date /2/, /blake/, :me
96
+ end
97
+ @mess.labels.should == Set.new
98
+ end
99
+ it 'uses all requirements as the labels if none given' do
100
+ @tagger.tag do
101
+ date /2/, /7/
102
+ end
103
+ @mess.labels.should == Set['2'.to_sym, '7'.to_sym]
104
+ end
105
+ it 'can use a multi tag block to specify requirements on several results' do
106
+ @tagger.tag do
107
+ multi :bob do
108
+ subj /test/i
109
+ date /2/
110
+ end
111
+ end
112
+ @mess.labels.should == Set[:bob]
113
+ end
114
+ it 'requires that all queries in the multi block match to tag' do
115
+ @tagger.tag do
116
+ multi :bob do
117
+ subj /test/i
118
+ date '-1'
119
+ end
120
+ end
121
+ @mess.labels.should == Set[]
122
+ end
123
+ it 'can add several tags with a multi block' do
124
+ @tagger.tag do
125
+ multi :jo, :bob do
126
+ subj /test/i
127
+ date /2/
128
+ end
129
+ end
130
+ @mess.labels.should == Set[:jo, :bob]
131
+ end
87
132
  end
88
133
 
89
134
  context 'adding tags' do
@@ -144,6 +189,15 @@ describe "SupTag" do
144
189
  end
145
190
  @mess.labels.should == Set[]
146
191
  end
192
+ it 'will archive if all querires in a multi block hit' do
193
+ @tagger.archive do
194
+ multi :me do
195
+ subj /Test/
196
+ date '2'
197
+ end
198
+ end
199
+ @mess.labels.should == Set[:me]
200
+ end
147
201
  end
148
202
 
149
203
  context 'archiving' do
@@ -180,5 +234,68 @@ describe "SupTag" do
180
234
  end
181
235
  @mess.labels.should == Set[:me]
182
236
  end
237
+ it 'archives if all queries hit' do
238
+ @tagger.archive do
239
+ subj /t/, /e/, :hi
240
+ end
241
+ @mess.labels.should == Set[:hi]
242
+ end
243
+ it 'will not archive if all queries do not hit' do
244
+ @tagger.archive do
245
+ subj /t/, /J/, :hi
246
+ end
247
+ @mess.labels.should == Set[:inbox]
248
+ end
249
+ end
250
+
251
+ context 'complex tests' do
252
+ it 'can properly tag a block with many rules' do
253
+ @tagger.tag do
254
+ subj /something/
255
+ from /BAD/
256
+ subj /test/i, :bob, :other
257
+ to /WHO/
258
+ end
259
+ @mess.labels.should == Set[:bob, :other]
260
+ end
261
+ it 'can properly tag a block with a multi block' do
262
+ @tagger.tag do
263
+ subj /something/
264
+ from /BAD/
265
+ subj /test/i, :bob, :other
266
+ to /WHO/
267
+ multi :ann do
268
+ subj /test/i
269
+ from /Sender/i
270
+ end
271
+ to /Bob/
272
+ end
273
+ @mess.labels.should == Set[:bob, :other, :ann]
274
+ end
275
+ it 'can properly archive with a block of many rules' do
276
+ @mess.add_label(:inbox)
277
+ @tagger.archive do
278
+ subj /something/
279
+ from /BAD/
280
+ subj /test/i, :bob, :other
281
+ to /WHO/
282
+ end
283
+ @mess.labels.should == Set[:bob, :other]
284
+ end
285
+ it 'can properly archive a block with a multiblock rule' do
286
+ @mess.add_label(:inbox)
287
+ @tagger.archive do
288
+ subj /something/
289
+ from /BAD/
290
+ subj /test/i, :bob, :other
291
+ to /WHO/
292
+ multi :ann do
293
+ subj /test/i
294
+ from /Sender/i
295
+ end
296
+ to /Bob/
297
+ end
298
+ @mess.labels.should == Set[:bob, :other, :ann]
299
+ end
183
300
  end
184
301
  end
data/sup_tag.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{sup_tag}
8
- s.version = "0.1.2"
8
+ s.version = "0.2.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Blake Sweeney"]
12
- s.date = %q{2010-10-19}
12
+ s.date = %q{2010-11-08}
13
13
  s.description = %q{SupTag lets you clean up the before-add-hook script by providing a clean DSL}
14
14
  s.email = %q{blakes.85@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -25,11 +25,13 @@ Gem::Specification.new do |s|
25
25
  "VERSION",
26
26
  "lib/sup_tag.rb",
27
27
  "lib/sup_tag/extensions/Object.rb",
28
+ "lib/sup_tag/extensions/binding.rb",
28
29
  "spec/dummy_source.rb",
29
- "spec/object_spec.rb",
30
30
  "spec/spec.opts",
31
31
  "spec/spec_helper.rb",
32
- "spec/sup_tag_spec.rb",
32
+ "spec/sup_tag/extensions/binding_spec.rb",
33
+ "spec/sup_tag/extensions/object_spec.rb",
34
+ "spec/sup_tag/sup_tag_spec.rb",
33
35
  "sup_tag.gemspec"
34
36
  ]
35
37
  s.homepage = %q{http://github.com/blakesweeney/sup_tag}
@@ -39,9 +41,10 @@ Gem::Specification.new do |s|
39
41
  s.summary = %q{Make tagging messages in sup pretty}
40
42
  s.test_files = [
41
43
  "spec/dummy_source.rb",
42
- "spec/object_spec.rb",
43
44
  "spec/spec_helper.rb",
44
- "spec/sup_tag_spec.rb"
45
+ "spec/sup_tag/extensions/binding_spec.rb",
46
+ "spec/sup_tag/extensions/object_spec.rb",
47
+ "spec/sup_tag/sup_tag_spec.rb"
45
48
  ]
46
49
 
47
50
  if s.respond_to? :specification_version then
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
8
7
  - 2
9
- version: 0.1.2
8
+ - 1
9
+ version: 0.2.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Blake Sweeney
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-10-19 00:00:00 -04:00
17
+ date: 2010-11-08 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -74,11 +74,13 @@ files:
74
74
  - VERSION
75
75
  - lib/sup_tag.rb
76
76
  - lib/sup_tag/extensions/Object.rb
77
+ - lib/sup_tag/extensions/binding.rb
77
78
  - spec/dummy_source.rb
78
- - spec/object_spec.rb
79
79
  - spec/spec.opts
80
80
  - spec/spec_helper.rb
81
- - spec/sup_tag_spec.rb
81
+ - spec/sup_tag/extensions/binding_spec.rb
82
+ - spec/sup_tag/extensions/object_spec.rb
83
+ - spec/sup_tag/sup_tag_spec.rb
82
84
  - sup_tag.gemspec
83
85
  has_rdoc: true
84
86
  homepage: http://github.com/blakesweeney/sup_tag
@@ -112,6 +114,7 @@ specification_version: 3
112
114
  summary: Make tagging messages in sup pretty
113
115
  test_files:
114
116
  - spec/dummy_source.rb
115
- - spec/object_spec.rb
116
117
  - spec/spec_helper.rb
117
- - spec/sup_tag_spec.rb
118
+ - spec/sup_tag/extensions/binding_spec.rb
119
+ - spec/sup_tag/extensions/object_spec.rb
120
+ - spec/sup_tag/sup_tag_spec.rb