mac-spotlight 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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