mac-spotlight 0.0.1 → 0.0.2

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/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'rubygems'
5
5
  require 'echoe'
6
6
  require 'rake/extensiontask'
7
7
 
8
- Echoe.new('mac-spotlight', '0.0.1') do |p|
8
+ Echoe.new('mac-spotlight', '0.0.2') do |p|
9
9
  p.description = "Spotlight - Ruby interface to Mac OSX Spotlight"
10
10
  p.url = "https://github.com/xli/spotlight"
11
11
  p.author = "Li Xiao"
@@ -11,36 +11,25 @@
11
11
 
12
12
  #define RELEASE_IF_NOT_NULL(ref) { if (ref) { CFRelease(ref); } }
13
13
 
14
- void MDItemSetAttribute(MDItemRef item, CFStringRef name, CFTypeRef value);
14
+ Boolean MDItemSetAttribute(MDItemRef item, CFStringRef name, CFTypeRef value);
15
15
 
16
- VALUE method_search(VALUE self, VALUE queryString, VALUE scopeDirectory);
17
- VALUE method_attributes(VALUE self, VALUE path);
18
- VALUE method_set_attribute(VALUE self, VALUE path, VALUE name, VALUE value);
19
- VALUE method_get_attribute(VALUE self, VALUE path, VALUE name);
20
-
21
- void Init_spotlight (void)
22
- {
23
- VALUE Spotlight = rb_define_module("Spotlight");
24
- VALUE SpotlightIntern = rb_define_module_under(Spotlight, "Intern");
25
- rb_define_module_function(SpotlightIntern, "search", method_search, 2);
26
- rb_define_module_function(SpotlightIntern, "attributes", method_attributes, 1);
27
- rb_define_module_function(SpotlightIntern, "set_attribute", method_set_attribute, 3);
28
- rb_define_module_function(SpotlightIntern, "get_attribute", method_get_attribute, 2);
29
- }
30
-
31
- VALUE cfstring2rbstr(CFStringRef str) {
32
- CFIndex len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8);
33
- char *result = (char *)malloc(sizeof(char) * len);
34
- CFStringGetCString(str, result, len, kCFStringEncodingUTF8);
35
- free(result);
36
- return rb_str_new2(result);
16
+ static VALUE cfstring2rbstr(CFStringRef str) {
17
+ const char *result;
18
+ VALUE rb_result = Qnil;
19
+ CFDataRef data = CFStringCreateExternalRepresentation(kCFAllocatorDefault, str, kCFStringEncodingUTF8, 0);
20
+ if (data) {
21
+ result = (const char *)CFDataGetBytePtr(data);
22
+ rb_result = rb_str_new2(result);
23
+ }
24
+ RELEASE_IF_NOT_NULL(data)
25
+ return rb_result;
37
26
  }
38
27
 
39
- CFStringRef rbstr2cfstring(VALUE str) {
28
+ static CFStringRef rbstr2cfstring(VALUE str) {
40
29
  return CFStringCreateWithCString(kCFAllocatorDefault, StringValuePtr(str), kCFStringEncodingUTF8);
41
30
  }
42
31
 
43
- CFStringRef date_string(CFDateRef date) {
32
+ static CFStringRef date_string(CFDateRef date) {
44
33
  CFLocaleRef locale = CFLocaleCopyCurrent();
45
34
  CFDateFormatterRef formatter = CFDateFormatterCreate(kCFAllocatorDefault, locale, kCFDateFormatterFullStyle, kCFDateFormatterFullStyle);
46
35
  CFStringRef result = CFDateFormatterCreateStringWithDate(kCFAllocatorDefault, formatter, date);
@@ -49,13 +38,13 @@ CFStringRef date_string(CFDateRef date) {
49
38
  return result;
50
39
  }
51
40
 
52
- VALUE convert2rb_type(CFTypeRef ref) {
41
+ static VALUE convert2rb_type(CFTypeRef ref) {
53
42
  VALUE result = Qnil;
54
43
  double double_result;
55
44
  int int_result;
56
45
  long long_result;
57
46
  int i;
58
- if (ref != nil) {
47
+ if (ref) {
59
48
  if (CFGetTypeID(ref) == CFStringGetTypeID()) {
60
49
  result = cfstring2rbstr(ref);
61
50
  } else if (CFGetTypeID(ref) == CFDateGetTypeID()) {
@@ -82,18 +71,19 @@ VALUE convert2rb_type(CFTypeRef ref) {
82
71
  return result;
83
72
  }
84
73
 
85
- CFTypeRef convert2cf_type(VALUE obj) {
86
- CFTypeRef result = nil;
74
+ static CFTypeRef convert2cf_type(VALUE obj) {
75
+ CFTypeRef result = NULL;
87
76
  double double_result;
88
77
  int int_result;
89
78
  long long_result;
90
79
  int i, len;
91
80
  VALUE tmp[1];
92
81
  CFAbsoluteTime time;
82
+ CFMutableArrayRef array_result;
93
83
 
94
84
  switch (TYPE(obj)) {
95
85
  case T_NIL:
96
- result = nil;
86
+ result = NULL;
97
87
  break;
98
88
  case T_TRUE:
99
89
  result = kCFBooleanTrue;
@@ -129,29 +119,28 @@ CFTypeRef convert2cf_type(VALUE obj) {
129
119
  break;
130
120
  case T_ARRAY:
131
121
  len = RARRAY(obj)->len;
132
- CFTypeRef *values = (CFTypeRef *)malloc(sizeof(CFTypeRef) * len);
122
+ array_result = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
133
123
  for (i = 0; i < len; i++) {
134
124
  tmp[0] = INT2NUM(i);
135
- values[i] = convert2cf_type(rb_ary_aref(1, tmp, obj));
125
+ CFArrayAppendValue(array_result, convert2cf_type(rb_ary_aref(1, tmp, obj)));
136
126
  }
137
- result = CFArrayCreate(kCFAllocatorDefault, (const void **)values, len, nil);
138
- free(values);
127
+ result = array_result;
128
+ break;
129
+ default:
130
+ rb_raise(rb_eTypeError, "not valid value");
139
131
  break;
140
132
  }
141
133
  return result;
142
134
  }
143
135
 
144
- void set_search_scope(MDQueryRef query, VALUE scopeDirectories) {
136
+ static void set_search_scope(MDQueryRef query, VALUE scopeDirectories) {
145
137
  int i;
146
138
  int len = RARRAY(scopeDirectories)->len;
147
- CFStringRef *scopes = (CFStringRef *)malloc(sizeof(CFStringRef) * len);
139
+ CFMutableArrayRef scopesRef = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
148
140
  for (i=0; i<len; i++) {
149
- scopes[i] = rbstr2cfstring(rb_ary_pop(scopeDirectories));
141
+ CFArrayAppendValue(scopesRef, rbstr2cfstring(rb_ary_pop(scopeDirectories)));
150
142
  }
151
143
 
152
- CFArrayRef scopesRef = CFArrayCreate(kCFAllocatorDefault, (const void **)scopes, len, nil);
153
- free(scopes);
154
-
155
144
  MDQuerySetSearchScope(query, scopesRef, 0);
156
145
  RELEASE_IF_NOT_NULL(scopesRef);
157
146
  }
@@ -163,33 +152,56 @@ VALUE method_search(VALUE self, VALUE queryString, VALUE scopeDirectories) {
163
152
  MDItemRef item;
164
153
 
165
154
  CFStringRef qs = rbstr2cfstring(queryString);
166
- MDQueryRef query = MDQueryCreate(kCFAllocatorDefault, qs, nil, nil);
155
+ MDQueryRef query = MDQueryCreate(kCFAllocatorDefault, qs, NULL, NULL);
167
156
  RELEASE_IF_NOT_NULL(qs);
168
-
169
157
  if (query) {
170
158
  set_search_scope(query, scopeDirectories);
171
159
  if (MDQueryExecute(query, kMDQuerySynchronous)) {
172
160
  result = rb_ary_new();
173
161
  for(i = 0; i < MDQueryGetResultCount(query); ++i) {
174
162
  item = (MDItemRef) MDQueryGetResultAtIndex(query, i);
175
- path = MDItemCopyAttribute(item, kMDItemPath);
176
- rb_ary_push(result, cfstring2rbstr(path));
163
+ if (item) {
164
+ path = MDItemCopyAttribute(item, kMDItemPath);
165
+ rb_ary_push(result, cfstring2rbstr(path));
166
+ RELEASE_IF_NOT_NULL(path);
167
+ }
177
168
  }
178
169
  }
179
- RELEASE_IF_NOT_NULL(path);
180
170
  RELEASE_IF_NOT_NULL(query);
181
171
  }
182
172
 
183
173
  return result;
184
174
  }
185
175
 
176
+ static MDItemRef createMDItemByPath(VALUE path) {
177
+ CFStringRef pathRef = rbstr2cfstring(path);
178
+ MDItemRef mdi = MDItemCreate(kCFAllocatorDefault, pathRef);
179
+ RELEASE_IF_NOT_NULL(pathRef);
180
+ if (!mdi) {
181
+ rb_raise(rb_eTypeError, "Could not find MDItem by given path");
182
+ }
183
+ return mdi;
184
+ }
185
+
186
+ static int each_attribute(VALUE name, VALUE value, MDItemRef mdi) {
187
+ CFStringRef nameRef = rbstr2cfstring(name);
188
+ CFTypeRef valueRef = convert2cf_type(value);
189
+
190
+ if(!MDItemSetAttribute(mdi, nameRef, valueRef)) {
191
+ printf("set %s failed\n", StringValuePtr(name));
192
+ }
193
+
194
+ RELEASE_IF_NOT_NULL(valueRef);
195
+ RELEASE_IF_NOT_NULL(nameRef);
196
+ }
197
+
198
+
186
199
  VALUE method_attributes(VALUE self, VALUE path) {
187
200
  int i;
188
201
  CFStringRef attrNameRef;
189
202
  CFTypeRef attrValueRef;
190
- CFStringRef pathRef = rbstr2cfstring(path);
191
- MDItemRef mdi = MDItemCreate(kCFAllocatorDefault, pathRef);
192
- RELEASE_IF_NOT_NULL(pathRef);
203
+ MDItemRef mdi = createMDItemByPath(path);
204
+
193
205
  CFArrayRef attrNamesRef = MDItemCopyAttributeNames(mdi);
194
206
  VALUE result = rb_hash_new();
195
207
  for (i = 0; i < CFArrayGetCount(attrNamesRef); i++) {
@@ -206,7 +218,7 @@ VALUE method_attributes(VALUE self, VALUE path) {
206
218
  }
207
219
 
208
220
  VALUE method_get_attribute(VALUE self, VALUE path, VALUE name) {
209
- MDItemRef mdi = MDItemCreate(kCFAllocatorDefault, rbstr2cfstring(path));
221
+ MDItemRef mdi = createMDItemByPath(path);
210
222
  CFStringRef nameRef = rbstr2cfstring(name);
211
223
  CFTypeRef valueRef = MDItemCopyAttribute(mdi, nameRef);
212
224
 
@@ -220,17 +232,34 @@ VALUE method_get_attribute(VALUE self, VALUE path, VALUE name) {
220
232
  }
221
233
 
222
234
  VALUE method_set_attribute(VALUE self, VALUE path, VALUE name, VALUE value) {
223
- MDItemRef item = MDItemCreate(kCFAllocatorDefault, rbstr2cfstring(path));
235
+ MDItemRef mdi = createMDItemByPath(path);
224
236
  CFStringRef nameRef = rbstr2cfstring(name);
225
237
  CFTypeRef valueRef = convert2cf_type(value);
226
238
 
227
- MDItemSetAttribute(item, nameRef, valueRef);
239
+ if(!MDItemSetAttribute(mdi, nameRef, valueRef)) {
240
+ printf("set %s failed\n", StringValuePtr(name));
241
+ }
228
242
 
229
243
  RELEASE_IF_NOT_NULL(valueRef);
230
244
  RELEASE_IF_NOT_NULL(nameRef);
231
- RELEASE_IF_NOT_NULL(item);
245
+ RELEASE_IF_NOT_NULL(mdi);
232
246
 
233
247
  return Qtrue;
234
248
  }
235
249
 
250
+ VALUE method_set_attributes(VALUE self, VALUE path, VALUE attributes) {
251
+ MDItemRef mdi = createMDItemByPath(path);
252
+ rb_hash_foreach(attributes, each_attribute, (VALUE) mdi);
253
+ RELEASE_IF_NOT_NULL(mdi);
254
+ }
236
255
 
256
+ void Init_spotlight (void)
257
+ {
258
+ VALUE Spotlight = rb_define_module("Spotlight");
259
+ VALUE SpotlightIntern = rb_define_module_under(Spotlight, "Intern");
260
+ rb_define_module_function(SpotlightIntern, "search", method_search, 2);
261
+ rb_define_module_function(SpotlightIntern, "attributes", method_attributes, 1);
262
+ rb_define_module_function(SpotlightIntern, "set_attribute", method_set_attribute, 3);
263
+ rb_define_module_function(SpotlightIntern, "get_attribute", method_get_attribute, 2);
264
+ rb_define_module_function(SpotlightIntern, "set_attributes", method_set_attributes, 2);
265
+ }
@@ -1,14 +1,14 @@
1
1
  require 'spotlight/spotlight'
2
2
 
3
3
  module Spotlight
4
- VERSION = "0.0.1"
4
+ VERSION = "0.0.2"
5
5
 
6
6
  def self.search(query_string, *scope_directories)
7
7
  Intern.search(query_string, scope_directories).collect {|path| MDItem.new(path)}
8
8
  end
9
9
 
10
10
  class MDItem
11
- VALID_ATTRIBUTE_VALUE_TYPE = [String, Time, Fixnum, Bignum, Float, Array]
11
+ VALID_ATTRIBUTE_VALUE_TYPE = [String, Time, Fixnum, Bignum, Float, Array, NilClass]
12
12
 
13
13
  class InvalidAttributeValueTypeError < StandardError
14
14
  end
@@ -20,6 +20,9 @@ module Spotlight
20
20
  def attributes
21
21
  Intern.attributes(@path)
22
22
  end
23
+ def attributes=(attributes)
24
+ Intern.set_attributes(@path, attributes)
25
+ end
23
26
  def [](attr_name)
24
27
  Intern.get_attribute(@path, attr_name)
25
28
  end
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{mac-spotlight}
5
- s.version = "0.0.1"
5
+ s.version = "0.0.2"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Li Xiao"]
9
- s.date = %q{2010-05-03}
9
+ s.date = %q{2010-05-09}
10
10
  s.description = %q{Spotlight - Ruby interface to Mac OSX Spotlight}
11
11
  s.email = %q{iam@li-xiao.com}
12
12
  s.extensions = ["ext/spotlight/extconf.rb"]
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.rdoc_options = ["--main", "README.rdoc", "--inline-source", "--line-numbers", "--charset", "UTF-8"]
17
17
  s.require_paths = ["lib", "ext"]
18
18
  s.rubyforge_project = %q{mac-spotlight}
19
- s.rubygems_version = %q{1.3.6}
19
+ s.rubygems_version = %q{1.3.5}
20
20
  s.summary = %q{Spotlight - Ruby interface to Mac OSX Spotlight}
21
21
  s.test_files = ["test/test_spotlight.rb"]
22
22
 
@@ -23,6 +23,14 @@ class TestSpotlight < Test::Unit::TestCase
23
23
  assert_equal [@item], Spotlight.search("kMDItemNow == #{time_now}", @dir)
24
24
  end
25
25
 
26
+ def test_search_with_multi_attribute
27
+ @item['kMDItemAttr1'] = 1
28
+ @item['kMDItemAttr2'] = 2
29
+ assert_equal [], Spotlight.search("kMDItemAttr1 == 2 && kMDItemAttr2 == 3", @dir)
30
+ assert_equal [], Spotlight.search("kMDItemAttr1 == 1 && kMDItemAttr2 == 3", @dir)
31
+ assert_equal [@item], Spotlight.search("kMDItemAttr1 == 1 && kMDItemAttr2 == 2", @dir)
32
+ end
33
+
26
34
  def test_attributes
27
35
  assert_equal "test_file.txt", @item.attributes['kMDItemDisplayName']
28
36
  end
@@ -36,9 +44,11 @@ class TestSpotlight < Test::Unit::TestCase
36
44
  def test_get_attribute
37
45
  assert_equal "test_file.txt", @item['kMDItemDisplayName']
38
46
  assert_equal ["public.plain-text", "public.text", "public.data", "public.item", "public.content"], @item['kMDItemContentTypeTree']
47
+ assert_nil @item['kMDItemNotExist']
39
48
  end
40
49
 
41
50
  def test_set_attribute
51
+ assert_attribute_set('kMDItemTestNilType', nil)
42
52
  assert_attribute_set('kMDItemTestStringType', "Time.now: #{Time.now}")
43
53
  assert_attribute_set('kMDItemTestLongType', Time.now.to_i)
44
54
  assert_attribute_set('kMDItemTestIntType', Time.now.to_i.to_s[-3..-1].to_i)
@@ -47,6 +57,14 @@ class TestSpotlight < Test::Unit::TestCase
47
57
  assert_attribute_set('kMDItemTestArrayTypeWithLong', [123456789])
48
58
  end
49
59
 
60
+ def test_set_attributes
61
+ attributes = {'TimeNow' => "Time.now: #{Time.now}", 'SomeThing' => Time.now.to_i}
62
+ @item.attributes = attributes
63
+ attributes.each do |key, value|
64
+ assert_equal value, @item.reload[key]
65
+ end
66
+ end
67
+
50
68
  def test_set_date_attribute
51
69
  assert_attribute_set('kMDItemTestDateType', Time.now)
52
70
  end
metadata CHANGED
@@ -1,12 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mac-spotlight
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 1
9
- version: 0.0.1
4
+ version: 0.0.2
10
5
  platform: ruby
11
6
  authors:
12
7
  - Li Xiao
@@ -14,45 +9,39 @@ autorequire:
14
9
  bindir: bin
15
10
  cert_chain: []
16
11
 
17
- date: 2010-05-03 00:00:00 -07:00
12
+ date: 2010-05-09 00:00:00 -07:00
18
13
  default_executable:
19
14
  dependencies:
20
15
  - !ruby/object:Gem::Dependency
21
16
  name: rake
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
24
20
  requirements:
25
21
  - - ">="
26
22
  - !ruby/object:Gem::Version
27
- segments:
28
- - 0
29
23
  version: "0"
30
- type: :development
31
- version_requirements: *id001
24
+ version:
32
25
  - !ruby/object:Gem::Dependency
33
26
  name: echoe
34
- prerelease: false
35
- requirement: &id002 !ruby/object:Gem::Requirement
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
36
30
  requirements:
37
31
  - - ">="
38
32
  - !ruby/object:Gem::Version
39
- segments:
40
- - 0
41
33
  version: "0"
42
- type: :development
43
- version_requirements: *id002
34
+ version:
44
35
  - !ruby/object:Gem::Dependency
45
36
  name: rake-compiler
46
- prerelease: false
47
- requirement: &id003 !ruby/object:Gem::Requirement
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
48
40
  requirements:
49
41
  - - ">="
50
42
  - !ruby/object:Gem::Version
51
- segments:
52
- - 0
53
43
  version: "0"
54
- type: :development
55
- version_requirements: *id003
44
+ version:
56
45
  description: Spotlight - Ruby interface to Mac OSX Spotlight
57
46
  email: iam@li-xiao.com
58
47
  executables: []
@@ -96,21 +85,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
96
85
  requirements:
97
86
  - - ">="
98
87
  - !ruby/object:Gem::Version
99
- segments:
100
- - 0
101
88
  version: "0"
89
+ version:
102
90
  required_rubygems_version: !ruby/object:Gem::Requirement
103
91
  requirements:
104
92
  - - ">="
105
93
  - !ruby/object:Gem::Version
106
- segments:
107
- - 1
108
- - 2
109
94
  version: "1.2"
95
+ version:
110
96
  requirements: []
111
97
 
112
98
  rubyforge_project: mac-spotlight
113
- rubygems_version: 1.3.6
99
+ rubygems_version: 1.3.5
114
100
  signing_key:
115
101
  specification_version: 3
116
102
  summary: Spotlight - Ruby interface to Mac OSX Spotlight