public
Description: Generic support for extracting GMail-style search keywords/values from strings
Homepage: http://codefluency.rubyforge.org/keyword_search
Clone URL: git://github.com/bruce/keyword_search.git
Added support for ()-based grouping: name:(frank "mr. buttons" jim) #=> 
["frank", "mr. buttons", "jim"]
codahale (author)
Tue May 20 18:28:29 -0700 2008
commit  cb21a1eead56436e9325883b59e5a04432e63754
tree    92e2c1476672a70dbccf97f7a7bf2ffb290c72f5
parent  893988c70e6ef6cc3b24af4d940c30234fbec333
...
 
 
 
 
1
2
3
...
1
2
3
4
5
6
7
0
@@ -1,3 +1,7 @@
0
+= HEAD
0
+
0
+* Added support for ()-based grouping: name:(frank "mr. buttons" jim) #=> ["frank", "mr. buttons", "jim"]
0
+
0
 = 1.3.1 / 2007-10-09
0
 
0
 * Tests/README update for case sensitivity change
...
7
8
9
10
 
11
12
13
...
34
35
36
37
 
 
38
39
40
...
42
43
44
45
46
 
 
 
47
48
49
...
51
52
53
54
55
56
 
 
 
 
 
 
 
57
58
59
...
61
62
63
64
65
 
 
 
66
67
68
...
71
72
73
74
 
 
75
76
77
...
79
80
81
82
83
 
 
 
84
85
86
...
88
89
90
91
92
93
94
 
 
 
 
 
 
 
 
 
95
96
97
...
99
100
101
102
103
104
105
 
 
 
 
 
 
 
 
 
106
107
108
...
112
113
114
115
 
116
117
118
...
123
124
125
126
 
127
128
129
...
131
132
133
134
 
135
136
137
138
139
140
 
141
142
 
143
144
145
...
233
234
235
236
 
 
 
 
 
237
238
239
240
241
 
242
243
244
 
245
246
 
247
248
249
 
250
251
 
252
253
254
255
 
 
256
257
258
...
264
265
266
267
 
268
269
270
 
 
271
272
273
...
7
8
9
 
10
11
12
13
...
34
35
36
 
37
38
39
40
41
...
43
44
45
 
 
46
47
48
49
50
51
...
53
54
55
 
 
 
56
57
58
59
60
61
62
63
64
65
...
67
68
69
 
 
70
71
72
73
74
75
...
78
79
80
 
81
82
83
84
85
...
87
88
89
 
 
90
91
92
93
94
95
...
97
98
99
 
 
 
 
100
101
102
103
104
105
106
107
108
109
110
111
...
113
114
115
 
 
 
 
116
117
118
119
120
121
122
123
124
125
126
127
...
131
132
133
 
134
135
136
137
...
142
143
144
 
145
146
147
148
...
150
151
152
 
153
154
 
 
155
156
 
157
158
 
159
160
161
162
...
250
251
252
 
253
254
255
256
257
258
259
260
261
 
262
263
264
 
265
266
 
267
268
269
 
270
271
 
272
273
274
 
 
275
276
277
278
279
...
285
286
287
 
288
289
 
 
290
291
292
293
294
0
@@ -7,7 +7,7 @@ module KeywordSearch
0
       
0
   class << self
0
   
0
- # line 48 "lib/keyword_search.rl"
0
+ # line 53 "lib/keyword_search.rl"
0
 
0
     
0
     def search(input_string, definition=nil, &block)
0
@@ -34,7 +34,8 @@ end
0
 self._parser_actions = [
0
   0, 1, 3, 1, 5, 1, 6, 2,
0
   0, 2, 2, 1, 0, 3, 0, 2,
0
- 4, 3, 1, 0, 4
0
+ 4, 3, 1, 0, 4, 3, 1, 0,
0
+ 5
0
 ]
0
 
0
 class << self
0
@@ -42,8 +43,9 @@ class << self
0
   private :_parser_key_offsets, :_parser_key_offsets=
0
 end
0
 self._parser_key_offsets = [
0
- 0, 0, 5, 8, 12, 15, 16, 17,
0
- 18
0
+ 0, 0, 6, 9, 14, 17, 18, 19,
0
+ 20, 24, 25, 29, 35, 37, 39, 41,
0
+ 43, 45
0
 ]
0
 
0
 class << self
0
@@ -51,9 +53,13 @@ class << self
0
   private :_parser_trans_keys, :_parser_trans_keys=
0
 end
0
 self._parser_trans_keys = [
0
- 0, 32, 34, 39, 58, 32, 34, 58,
0
- 32, 34, 39, 58, 32, 34, 58, 34,
0
- 32, 39, 32, 34, 58, 0
0
+ 0, 32, 34, 39, 40, 58, 32, 34,
0
+ 58, 32, 34, 39, 40, 58, 32, 34,
0
+ 58, 34, 32, 39, 32, 34, 41, 58,
0
+ 41, 32, 34, 41, 58, 32, 34, 39,
0
+ 40, 41, 58, 34, 41, 32, 41, 32,
0
+ 34, 39, 41, 32, 39, 32, 34, 58,
0
+ 0
0
 ]
0
 
0
 class << self
0
@@ -61,8 +67,9 @@ class << self
0
   private :_parser_single_lengths, :_parser_single_lengths=
0
 end
0
 self._parser_single_lengths = [
0
- 0, 5, 3, 4, 3, 1, 1, 1,
0
- 3
0
+ 0, 6, 3, 5, 3, 1, 1, 1,
0
+ 4, 1, 4, 6, 2, 2, 2, 2,
0
+ 2, 3
0
 ]
0
 
0
 class << self
0
@@ -71,7 +78,8 @@ class << self
0
 end
0
 self._parser_range_lengths = [
0
   0, 0, 0, 0, 0, 0, 0, 0,
0
- 0
0
+ 0, 0, 0, 0, 0, 0, 0, 0,
0
+ 0, 0
0
 ]
0
 
0
 class << self
0
@@ -79,8 +87,9 @@ class << self
0
   private :_parser_index_offsets, :_parser_index_offsets=
0
 end
0
 self._parser_index_offsets = [
0
- 0, 0, 6, 10, 15, 19, 21, 23,
0
- 25
0
+ 0, 0, 7, 11, 17, 21, 23, 25,
0
+ 27, 32, 34, 39, 46, 49, 52, 55,
0
+ 58, 61
0
 ]
0
 
0
 class << self
0
@@ -88,10 +97,15 @@ class << self
0
   private :_parser_trans_targs_wi, :_parser_trans_targs_wi=
0
 end
0
 self._parser_trans_targs_wi = [
0
- 8, 0, 5, 7, 0, 2, 1, 0,
0
- 3, 2, 0, 5, 7, 0, 4, 1,
0
- 0, 0, 4, 6, 5, 1, 0, 6,
0
- 7, 1, 0, 3, 2, 0
0
+ 17, 0, 5, 7, 10, 0, 2, 1,
0
+ 0, 3, 2, 0, 5, 7, 8, 0,
0
+ 4, 1, 0, 0, 4, 6, 5, 1,
0
+ 0, 6, 7, 9, 9, 4, 9, 8,
0
+ 6, 9, 9, 9, 2, 11, 10, 9,
0
+ 12, 15, 8, 4, 9, 8, 13, 14,
0
+ 12, 9, 6, 9, 5, 6, 5, 13,
0
+ 16, 15, 7, 6, 7, 1, 0, 3,
0
+ 2, 0
0
 ]
0
 
0
 class << self
0
@@ -99,10 +113,15 @@ class << self
0
   private :_parser_trans_actions_wi, :_parser_trans_actions_wi=
0
 end
0
 self._parser_trans_actions_wi = [
0
- 7, 5, 13, 13, 5, 7, 1, 0,
0
- 0, 0, 0, 17, 17, 0, 10, 1,
0
- 0, 0, 0, 3, 0, 1, 0, 3,
0
- 0, 1, 0, 0, 0, 0
0
+ 7, 5, 13, 13, 13, 5, 7, 1,
0
+ 0, 0, 0, 0, 17, 17, 17, 0,
0
+ 10, 1, 0, 0, 0, 3, 0, 1,
0
+ 0, 3, 0, 1, 0, 3, 0, 0,
0
+ 3, 0, 1, 0, 3, 0, 0, 0,
0
+ 17, 17, 17, 21, 0, 10, 3, 3,
0
+ 0, 1, 3, 0, 1, 3, 0, 3,
0
+ 3, 0, 1, 3, 0, 1, 0, 0,
0
+ 0, 0
0
 ]
0
 
0
 class << self
0
@@ -112,7 +131,7 @@ self.parser_start = 1;
0
 class << self
0
   attr_accessor :parser_first_final
0
 end
0
-self.parser_first_final = 8;
0
+self.parser_first_final = 17;
0
 class << self
0
   attr_accessor :parser_error
0
 end
0
@@ -123,7 +142,7 @@ class << self
0
 end
0
 self.parser_en_main = 1;
0
 
0
-# line 66 "lib/keyword_search.rl"
0
+# line 71 "lib/keyword_search.rl"
0
       p = 0
0
       pe = data.length
0
       key = nil
0
@@ -131,15 +150,13 @@ self.parser_en_main = 1;
0
       results = {}
0
       quotes = 0
0
       
0
-# line 135 "lib/keyword_search.rb"
0
+# line 154 "lib/keyword_search.rb"
0
 begin
0
- p ||= 0
0
- pe ||= data.length
0
   cs = parser_start
0
 end
0
-# line 73 "lib/keyword_search.rl"
0
+# line 78 "lib/keyword_search.rl"
0
       
0
-# line 143 "lib/keyword_search.rb"
0
+# line 160 "lib/keyword_search.rb"
0
 begin
0
   _klen, _trans, _keys, _acts, _nacts = nil
0
   if p != pe
0
@@ -233,26 +250,30 @@ when 3:
0
     begin
0
 
0
         value = data[tokstart..p-1]
0
- value = value[1..-2] if ["'", '"'].include?(value[0,1])
0
+ if ["("].include?(value[0,1])
0
+ value = parse(value[1..-2])[:default]
0
+ elsif ["'", '"'].include?(value[0,1])
0
+ value = value[1..-2]
0
+ end
0
         (results[key || :default] ||= []) << value
0
           end
0
 # line 26 "lib/keyword_search.rl"
0
 when 4:
0
-# line 32 "lib/keyword_search.rl"
0
+# line 36 "lib/keyword_search.rl"
0
     begin
0
  quotes += 1     end
0
-# line 32 "lib/keyword_search.rl"
0
+# line 36 "lib/keyword_search.rl"
0
 when 5:
0
-# line 34 "lib/keyword_search.rl"
0
+# line 38 "lib/keyword_search.rl"
0
     begin
0
  quotes -= 1     end
0
-# line 34 "lib/keyword_search.rl"
0
+# line 38 "lib/keyword_search.rl"
0
 when 6:
0
-# line 46 "lib/keyword_search.rl"
0
+# line 51 "lib/keyword_search.rl"
0
     begin
0
  raise ParseError, "At offset #{p}, near: '#{data[p,10]}'"     end
0
-# line 46 "lib/keyword_search.rl"
0
-# line 256 "lib/keyword_search.rb"
0
+# line 51 "lib/keyword_search.rl"
0
+# line 277 "lib/keyword_search.rb"
0
     end # action switch
0
   end
0
   end while false
0
@@ -264,10 +285,10 @@ when 6:
0
   end
0
   end
0
   end
0
-# line 74 "lib/keyword_search.rl"
0
+# line 79 "lib/keyword_search.rl"
0
       
0
-# line 270 "lib/keyword_search.rb"
0
-# line 75 "lib/keyword_search.rl"
0
+# line 291 "lib/keyword_search.rb"
0
+# line 80 "lib/keyword_search.rl"
0
       unless quotes.zero?
0
        raise ParseError, "Unclosed quotes"
0
       end
...
25
26
27
28
 
 
 
 
 
29
30
31
...
36
37
38
39
40
 
 
 
41
42
43
...
25
26
27
 
28
29
30
31
32
33
34
35
...
40
41
42
 
 
43
44
45
46
47
48
0
@@ -25,7 +25,11 @@ module KeywordSearch
0
       
0
       action value {
0
         value = data[tokstart..p-1]
0
- value = value[1..-2] if ["'", '"'].include?(value[0,1])
0
+ if ["("].include?(value[0,1])
0
+ value = parse(value[1..-2])[:default]
0
+ elsif ["'", '"'].include?(value[0,1])
0
+ value = value[1..-2]
0
+ end
0
         (results[key || :default] ||= []) << value
0
       }
0
       
0
@@ -36,8 +40,9 @@ module KeywordSearch
0
       bareword = [^ '":] [^ ":]*; # allow apostrophes
0
       dquoted = '"' @ quote any* :>> '"' @ unquote;
0
       squoted = '\'' @ quote any* :>> '\'' @ unquote;
0
-
0
- value = ( dquoted | squoted | bareword );
0
+ grouped = '(' @ quote any* :>> ')' @ unquote;
0
+
0
+ value = ( grouped | dquoted | squoted | bareword );
0
       
0
       pair = (bareword > start ':') % key value > start % value ;
0
       
...
13
14
15
 
 
 
16
17
18
...
35
36
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
39
40
...
13
14
15
16
17
18
19
20
21
...
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
0
@@ -13,6 +13,9 @@ context "KeywordSearch" do
0
   DEFAULT_AGE_WITH_QUOTED_AGE = %<26 name:"bruce williams">
0
   DEFAULT_AGE_WITH_SINGLE_QUOTED_AGE = %<26 name:'bruce williams'>
0
   NAME_WITH_NESTED_SINGLE_QUOTES = %<"d'arcy d'uberville" age:28>
0
+ NAME_AND_GROUPED_AGE = %<coda hale age:(27)>
0
+ NAME_AND_GROUPED_QUOTED_AGE = %<coda hale age:("27")>
0
+ NAME_AND_GROUPED_QUOTED_AGES = %<coda hale age:("27" 34 "48")>
0
   
0
   specify "default keyword" do
0
     result = nil
0
@@ -35,6 +38,36 @@ context "KeywordSearch" do
0
     assert_equal 26, result
0
   end
0
   
0
+ specify "unquoted grouped keyword term" do
0
+ result = nil
0
+ KeywordSearch.search(NAME_AND_GROUPED_AGE) do |with|
0
+ with.keyword :age do |values|
0
+ result = Integer(values.first.first)
0
+ end
0
+ end
0
+ assert_equal 27, result
0
+ end
0
+
0
+ specify "quoted grouped keyword term" do
0
+ result = nil
0
+ KeywordSearch.search(NAME_AND_GROUPED_QUOTED_AGE) do |with|
0
+ with.keyword :age do |values|
0
+ result = Integer(values.first.first)
0
+ end
0
+ end
0
+ assert_equal 27, result
0
+ end
0
+
0
+ specify "mixed grouped keyword terms" do
0
+ result = nil
0
+ KeywordSearch.search(NAME_AND_GROUPED_QUOTED_AGES) do |with|
0
+ with.keyword :age do |values|
0
+ result = values.first.map { |v| v.to_i }
0
+ end
0
+ end
0
+ assert_equal [27, 34, 48], result
0
+ end
0
+
0
   specify "quoted default keyword term" do
0
     result = nil
0
     KeywordSearch.search(NAME_QUOTED_AND_AGE) do |with|

Comments

    No one has commented yet.