mac-spotlight 0.0.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/MIT-LICENSE.txt +19 -0
- data/Manifest +10 -0
- data/README.rdoc +28 -0
- data/Rakefile +21 -0
- data/TODO +2 -0
- data/ext/spotlight/extconf.rb +6 -0
- data/ext/spotlight/spotlight.c +236 -0
- data/lib/spotlight.rb +41 -0
- data/mac-spotlight.gemspec +41 -0
- data/test/test_file.txt +1 -0
- data/test/test_spotlight.rb +58 -0
- metadata +118 -0
data/MIT-LICENSE.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2010 Li Xiao, iam@li-xiao.com
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/Manifest
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
= Spotlight -- Ruby interface to Mac OSX Spotlight
|
2
|
+
|
3
|
+
Not done yet, see TODO what's missed currently
|
4
|
+
|
5
|
+
== Install
|
6
|
+
|
7
|
+
You may need setup environment ARCHFLAGS="-arch i386" when installing the gem
|
8
|
+
|
9
|
+
== Limitation
|
10
|
+
|
11
|
+
It only works on Mac.
|
12
|
+
|
13
|
+
= Other stuff
|
14
|
+
|
15
|
+
Author: Li Xiao <iam@li-xiao.com>
|
16
|
+
|
17
|
+
Requires: Ruby 1.8.6 or later
|
18
|
+
|
19
|
+
License: Copyright 2010 by Li Xiao.
|
20
|
+
Released under an MIT-LICENSE. See the MIT-LICENSE.txt file
|
21
|
+
included in the distribution.
|
22
|
+
|
23
|
+
== Warranty
|
24
|
+
|
25
|
+
This software is provided "as is" and without any express or
|
26
|
+
implied warranties, including, without limitation, the implied
|
27
|
+
warranties of merchantibility and fitness for a particular
|
28
|
+
purpose.
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
ENV["ARCHFLAGS"]="-arch i386"
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'echoe'
|
6
|
+
require 'rake/extensiontask'
|
7
|
+
|
8
|
+
Echoe.new('mac-spotlight', '0.0.1') do |p|
|
9
|
+
p.description = "Spotlight - Ruby interface to Mac OSX Spotlight"
|
10
|
+
p.url = "https://github.com/xli/spotlight"
|
11
|
+
p.author = "Li Xiao"
|
12
|
+
p.email = "iam@li-xiao.com"
|
13
|
+
p.ignore_pattern = "*.gemspec"
|
14
|
+
p.development_dependencies = ['rake', 'echoe', 'rake-compiler']
|
15
|
+
p.test_pattern = "test/test_*.rb"
|
16
|
+
p.rdoc_options = %w(--main README.rdoc --inline-source --line-numbers --charset UTF-8)
|
17
|
+
end
|
18
|
+
|
19
|
+
Rake::ExtensionTask.new('spotlight') do |ext|
|
20
|
+
ext.lib_dir = 'lib/spotlight'
|
21
|
+
end
|
@@ -0,0 +1,236 @@
|
|
1
|
+
/*
|
2
|
+
* spotlight.c
|
3
|
+
* spotlight
|
4
|
+
*
|
5
|
+
* Created by xli on 4/26/10.
|
6
|
+
* Copyright 2010 ThoughtWorks. All rights reserved.
|
7
|
+
*/
|
8
|
+
|
9
|
+
#include <ruby.h>
|
10
|
+
#include <CoreServices/CoreServices.h>
|
11
|
+
|
12
|
+
#define RELEASE_IF_NOT_NULL(ref) { if (ref) { CFRelease(ref); } }
|
13
|
+
|
14
|
+
void MDItemSetAttribute(MDItemRef item, CFStringRef name, CFTypeRef value);
|
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);
|
37
|
+
}
|
38
|
+
|
39
|
+
CFStringRef rbstr2cfstring(VALUE str) {
|
40
|
+
return CFStringCreateWithCString(kCFAllocatorDefault, StringValuePtr(str), kCFStringEncodingUTF8);
|
41
|
+
}
|
42
|
+
|
43
|
+
CFStringRef date_string(CFDateRef date) {
|
44
|
+
CFLocaleRef locale = CFLocaleCopyCurrent();
|
45
|
+
CFDateFormatterRef formatter = CFDateFormatterCreate(kCFAllocatorDefault, locale, kCFDateFormatterFullStyle, kCFDateFormatterFullStyle);
|
46
|
+
CFStringRef result = CFDateFormatterCreateStringWithDate(kCFAllocatorDefault, formatter, date);
|
47
|
+
RELEASE_IF_NOT_NULL(formatter);
|
48
|
+
RELEASE_IF_NOT_NULL(locale);
|
49
|
+
return result;
|
50
|
+
}
|
51
|
+
|
52
|
+
VALUE convert2rb_type(CFTypeRef ref) {
|
53
|
+
VALUE result = Qnil;
|
54
|
+
double double_result;
|
55
|
+
int int_result;
|
56
|
+
long long_result;
|
57
|
+
int i;
|
58
|
+
if (ref != nil) {
|
59
|
+
if (CFGetTypeID(ref) == CFStringGetTypeID()) {
|
60
|
+
result = cfstring2rbstr(ref);
|
61
|
+
} else if (CFGetTypeID(ref) == CFDateGetTypeID()) {
|
62
|
+
// 978307200.0 == (January 1, 2001 00:00 GMT) - (January 1, 1970 00:00 UTC)
|
63
|
+
// CFAbsoluteTime => January 1, 2001 00:00 GMT
|
64
|
+
// ruby Time => January 1, 1970 00:00 UTC
|
65
|
+
double_result = (double) CFDateGetAbsoluteTime(ref) + 978307200;
|
66
|
+
result = rb_funcall(rb_cTime, rb_intern("at"), 1, rb_float_new(double_result));
|
67
|
+
} else if (CFGetTypeID(ref) == CFArrayGetTypeID()) {
|
68
|
+
result = rb_ary_new();
|
69
|
+
for (i = 0; i < CFArrayGetCount(ref); i++) {
|
70
|
+
rb_ary_push(result, convert2rb_type(CFArrayGetValueAtIndex(ref, i)));
|
71
|
+
}
|
72
|
+
} else if (CFGetTypeID(ref) == CFNumberGetTypeID()) {
|
73
|
+
if (CFNumberIsFloatType(ref)) {
|
74
|
+
CFNumberGetValue(ref, CFNumberGetType(ref), &double_result);
|
75
|
+
result = rb_float_new(double_result);
|
76
|
+
} else {
|
77
|
+
CFNumberGetValue(ref, CFNumberGetType(ref), &long_result);
|
78
|
+
result = LONG2NUM(long_result);
|
79
|
+
}
|
80
|
+
}
|
81
|
+
}
|
82
|
+
return result;
|
83
|
+
}
|
84
|
+
|
85
|
+
CFTypeRef convert2cf_type(VALUE obj) {
|
86
|
+
CFTypeRef result = nil;
|
87
|
+
double double_result;
|
88
|
+
int int_result;
|
89
|
+
long long_result;
|
90
|
+
int i, len;
|
91
|
+
VALUE tmp[1];
|
92
|
+
CFAbsoluteTime time;
|
93
|
+
|
94
|
+
switch (TYPE(obj)) {
|
95
|
+
case T_NIL:
|
96
|
+
result = nil;
|
97
|
+
break;
|
98
|
+
case T_TRUE:
|
99
|
+
result = kCFBooleanTrue;
|
100
|
+
break;
|
101
|
+
case T_FALSE:
|
102
|
+
result = kCFBooleanFalse;
|
103
|
+
break;
|
104
|
+
case T_FLOAT:
|
105
|
+
double_result = NUM2DBL(obj);
|
106
|
+
result = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &double_result);
|
107
|
+
break;
|
108
|
+
case T_BIGNUM:
|
109
|
+
long_result = NUM2LONG(obj);
|
110
|
+
result = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongType, &long_result);
|
111
|
+
break;
|
112
|
+
case T_FIXNUM:
|
113
|
+
int_result = FIX2INT(obj);
|
114
|
+
result = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &int_result);
|
115
|
+
break;
|
116
|
+
case T_STRING:
|
117
|
+
result = rbstr2cfstring(obj);
|
118
|
+
break;
|
119
|
+
case T_DATA:
|
120
|
+
case T_OBJECT:
|
121
|
+
// todo : check type is Time
|
122
|
+
// 978307200.0 == (January 1, 2001 00:00 GMT) - (January 1, 1970 00:00 UTC)
|
123
|
+
// CFAbsoluteTime => January 1, 2001 00:00 GMT
|
124
|
+
// ruby Time => January 1, 1970 00:00 UTC
|
125
|
+
if (rb_obj_is_kind_of(obj, rb_cTime)) {
|
126
|
+
time = (CFAbsoluteTime) (NUM2DBL(rb_funcall(obj, rb_intern("to_f"), 0)) - 978307200.0);
|
127
|
+
result = CFDateCreate(kCFAllocatorDefault, time);
|
128
|
+
}
|
129
|
+
break;
|
130
|
+
case T_ARRAY:
|
131
|
+
len = RARRAY(obj)->len;
|
132
|
+
CFTypeRef *values = (CFTypeRef *)malloc(sizeof(CFTypeRef) * len);
|
133
|
+
for (i = 0; i < len; i++) {
|
134
|
+
tmp[0] = INT2NUM(i);
|
135
|
+
values[i] = convert2cf_type(rb_ary_aref(1, tmp, obj));
|
136
|
+
}
|
137
|
+
result = CFArrayCreate(kCFAllocatorDefault, (const void **)values, len, nil);
|
138
|
+
free(values);
|
139
|
+
break;
|
140
|
+
}
|
141
|
+
return result;
|
142
|
+
}
|
143
|
+
|
144
|
+
void set_search_scope(MDQueryRef query, VALUE scopeDirectories) {
|
145
|
+
int i;
|
146
|
+
int len = RARRAY(scopeDirectories)->len;
|
147
|
+
CFStringRef *scopes = (CFStringRef *)malloc(sizeof(CFStringRef) * len);
|
148
|
+
for (i=0; i<len; i++) {
|
149
|
+
scopes[i] = rbstr2cfstring(rb_ary_pop(scopeDirectories));
|
150
|
+
}
|
151
|
+
|
152
|
+
CFArrayRef scopesRef = CFArrayCreate(kCFAllocatorDefault, (const void **)scopes, len, nil);
|
153
|
+
free(scopes);
|
154
|
+
|
155
|
+
MDQuerySetSearchScope(query, scopesRef, 0);
|
156
|
+
RELEASE_IF_NOT_NULL(scopesRef);
|
157
|
+
}
|
158
|
+
|
159
|
+
VALUE method_search(VALUE self, VALUE queryString, VALUE scopeDirectories) {
|
160
|
+
VALUE result = Qnil;
|
161
|
+
int i;
|
162
|
+
CFStringRef path;
|
163
|
+
MDItemRef item;
|
164
|
+
|
165
|
+
CFStringRef qs = rbstr2cfstring(queryString);
|
166
|
+
MDQueryRef query = MDQueryCreate(kCFAllocatorDefault, qs, nil, nil);
|
167
|
+
RELEASE_IF_NOT_NULL(qs);
|
168
|
+
|
169
|
+
if (query) {
|
170
|
+
set_search_scope(query, scopeDirectories);
|
171
|
+
if (MDQueryExecute(query, kMDQuerySynchronous)) {
|
172
|
+
result = rb_ary_new();
|
173
|
+
for(i = 0; i < MDQueryGetResultCount(query); ++i) {
|
174
|
+
item = (MDItemRef) MDQueryGetResultAtIndex(query, i);
|
175
|
+
path = MDItemCopyAttribute(item, kMDItemPath);
|
176
|
+
rb_ary_push(result, cfstring2rbstr(path));
|
177
|
+
}
|
178
|
+
}
|
179
|
+
RELEASE_IF_NOT_NULL(path);
|
180
|
+
RELEASE_IF_NOT_NULL(query);
|
181
|
+
}
|
182
|
+
|
183
|
+
return result;
|
184
|
+
}
|
185
|
+
|
186
|
+
VALUE method_attributes(VALUE self, VALUE path) {
|
187
|
+
int i;
|
188
|
+
CFStringRef attrNameRef;
|
189
|
+
CFTypeRef attrValueRef;
|
190
|
+
CFStringRef pathRef = rbstr2cfstring(path);
|
191
|
+
MDItemRef mdi = MDItemCreate(kCFAllocatorDefault, pathRef);
|
192
|
+
RELEASE_IF_NOT_NULL(pathRef);
|
193
|
+
CFArrayRef attrNamesRef = MDItemCopyAttributeNames(mdi);
|
194
|
+
VALUE result = rb_hash_new();
|
195
|
+
for (i = 0; i < CFArrayGetCount(attrNamesRef); i++) {
|
196
|
+
attrNameRef = CFArrayGetValueAtIndex(attrNamesRef, i);
|
197
|
+
attrValueRef = MDItemCopyAttribute(mdi, attrNameRef);
|
198
|
+
rb_hash_aset(result, cfstring2rbstr(attrNameRef), convert2rb_type(attrValueRef));
|
199
|
+
RELEASE_IF_NOT_NULL(attrValueRef);
|
200
|
+
}
|
201
|
+
|
202
|
+
RELEASE_IF_NOT_NULL(mdi);
|
203
|
+
RELEASE_IF_NOT_NULL(attrNamesRef);
|
204
|
+
|
205
|
+
return result;
|
206
|
+
}
|
207
|
+
|
208
|
+
VALUE method_get_attribute(VALUE self, VALUE path, VALUE name) {
|
209
|
+
MDItemRef mdi = MDItemCreate(kCFAllocatorDefault, rbstr2cfstring(path));
|
210
|
+
CFStringRef nameRef = rbstr2cfstring(name);
|
211
|
+
CFTypeRef valueRef = MDItemCopyAttribute(mdi, nameRef);
|
212
|
+
|
213
|
+
VALUE result = convert2rb_type(valueRef);
|
214
|
+
|
215
|
+
RELEASE_IF_NOT_NULL(valueRef);
|
216
|
+
RELEASE_IF_NOT_NULL(nameRef);
|
217
|
+
RELEASE_IF_NOT_NULL(mdi);
|
218
|
+
|
219
|
+
return result;
|
220
|
+
}
|
221
|
+
|
222
|
+
VALUE method_set_attribute(VALUE self, VALUE path, VALUE name, VALUE value) {
|
223
|
+
MDItemRef item = MDItemCreate(kCFAllocatorDefault, rbstr2cfstring(path));
|
224
|
+
CFStringRef nameRef = rbstr2cfstring(name);
|
225
|
+
CFTypeRef valueRef = convert2cf_type(value);
|
226
|
+
|
227
|
+
MDItemSetAttribute(item, nameRef, valueRef);
|
228
|
+
|
229
|
+
RELEASE_IF_NOT_NULL(valueRef);
|
230
|
+
RELEASE_IF_NOT_NULL(nameRef);
|
231
|
+
RELEASE_IF_NOT_NULL(item);
|
232
|
+
|
233
|
+
return Qtrue;
|
234
|
+
}
|
235
|
+
|
236
|
+
|
data/lib/spotlight.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spotlight/spotlight'
|
2
|
+
|
3
|
+
module Spotlight
|
4
|
+
VERSION = "0.0.1"
|
5
|
+
|
6
|
+
def self.search(query_string, *scope_directories)
|
7
|
+
Intern.search(query_string, scope_directories).collect {|path| MDItem.new(path)}
|
8
|
+
end
|
9
|
+
|
10
|
+
class MDItem
|
11
|
+
VALID_ATTRIBUTE_VALUE_TYPE = [String, Time, Fixnum, Bignum, Float, Array]
|
12
|
+
|
13
|
+
class InvalidAttributeValueTypeError < StandardError
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :path
|
17
|
+
def initialize(path)
|
18
|
+
@path = path
|
19
|
+
end
|
20
|
+
def attributes
|
21
|
+
Intern.attributes(@path)
|
22
|
+
end
|
23
|
+
def [](attr_name)
|
24
|
+
Intern.get_attribute(@path, attr_name)
|
25
|
+
end
|
26
|
+
def []=(attr_name, attr_value)
|
27
|
+
validate(attr_value)
|
28
|
+
Intern.set_attribute(@path, attr_name, attr_value)
|
29
|
+
end
|
30
|
+
def reload
|
31
|
+
self
|
32
|
+
end
|
33
|
+
def ==(obj)
|
34
|
+
obj.is_a?(MDItem) && @path == obj.path
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate(value)
|
38
|
+
raise InvalidAttributeValueTypeError, "Invalid attribute value type #{value.class.inspect}, valid types: #{VALID_ATTRIBUTE_VALUE_TYPE.join(", ")}" unless VALID_ATTRIBUTE_VALUE_TYPE.include?(value.class)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{mac-spotlight}
|
5
|
+
s.version = "0.0.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Li Xiao"]
|
9
|
+
s.date = %q{2010-05-03}
|
10
|
+
s.description = %q{Spotlight - Ruby interface to Mac OSX Spotlight}
|
11
|
+
s.email = %q{iam@li-xiao.com}
|
12
|
+
s.extensions = ["ext/spotlight/extconf.rb"]
|
13
|
+
s.extra_rdoc_files = ["README.rdoc", "TODO", "ext/spotlight/extconf.rb", "ext/spotlight/spotlight.c", "lib/spotlight.rb"]
|
14
|
+
s.files = ["MIT-LICENSE.txt", "Manifest", "README.rdoc", "Rakefile", "TODO", "ext/spotlight/extconf.rb", "ext/spotlight/spotlight.c", "lib/spotlight.rb", "test/test_file.txt", "test/test_spotlight.rb", "mac-spotlight.gemspec"]
|
15
|
+
s.homepage = %q{https://github.com/xli/spotlight}
|
16
|
+
s.rdoc_options = ["--main", "README.rdoc", "--inline-source", "--line-numbers", "--charset", "UTF-8"]
|
17
|
+
s.require_paths = ["lib", "ext"]
|
18
|
+
s.rubyforge_project = %q{mac-spotlight}
|
19
|
+
s.rubygems_version = %q{1.3.6}
|
20
|
+
s.summary = %q{Spotlight - Ruby interface to Mac OSX Spotlight}
|
21
|
+
s.test_files = ["test/test_spotlight.rb"]
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 3
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
s.add_development_dependency(%q<rake>, [">= 0"])
|
29
|
+
s.add_development_dependency(%q<echoe>, [">= 0"])
|
30
|
+
s.add_development_dependency(%q<rake-compiler>, [">= 0"])
|
31
|
+
else
|
32
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
33
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
34
|
+
s.add_dependency(%q<rake-compiler>, [">= 0"])
|
35
|
+
end
|
36
|
+
else
|
37
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
38
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
39
|
+
s.add_dependency(%q<rake-compiler>, [">= 0"])
|
40
|
+
end
|
41
|
+
end
|
data/test/test_file.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
just for test
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "spotlight"
|
3
|
+
|
4
|
+
class TestSpotlight < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@dir = File.expand_path(File.dirname(__FILE__))
|
8
|
+
@item = Spotlight::MDItem.new(File.join(@dir, 'test_file.txt'))
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_search
|
12
|
+
assert_equal [@item], Spotlight.search("kMDItemDisplayName == 'test_file.txt'", @dir)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_search_with_multi_scope_directories
|
16
|
+
@lib_dir = File.expand_path(File.dirname(__FILE__) + "/../lib")
|
17
|
+
assert_equal [@item], Spotlight.search("kMDItemDisplayName == 'test_file.txt'", @lib_dir, @dir)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_search_attribute_just_set
|
21
|
+
time_now = Time.now.to_i
|
22
|
+
@item['kMDItemNow'] = time_now
|
23
|
+
assert_equal [@item], Spotlight.search("kMDItemNow == #{time_now}", @dir)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_attributes
|
27
|
+
assert_equal "test_file.txt", @item.attributes['kMDItemDisplayName']
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_could_not_set_attribute_value_when_it_is_not_time_string_int_and_float
|
31
|
+
assert_raise Spotlight::MDItem::InvalidAttributeValueTypeError do
|
32
|
+
assert_attribute_set('kMDItemTestLongType', Hash.new)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_get_attribute
|
37
|
+
assert_equal "test_file.txt", @item['kMDItemDisplayName']
|
38
|
+
assert_equal ["public.plain-text", "public.text", "public.data", "public.item", "public.content"], @item['kMDItemContentTypeTree']
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_set_attribute
|
42
|
+
assert_attribute_set('kMDItemTestStringType', "Time.now: #{Time.now}")
|
43
|
+
assert_attribute_set('kMDItemTestLongType', Time.now.to_i)
|
44
|
+
assert_attribute_set('kMDItemTestIntType', Time.now.to_i.to_s[-3..-1].to_i)
|
45
|
+
assert_attribute_set('kMDItemTestFloatType', 1.123456688)
|
46
|
+
assert_attribute_set('kMDItemTestArrayTypeWithString', ["public.plain-text", "public.text"])
|
47
|
+
assert_attribute_set('kMDItemTestArrayTypeWithLong', [123456789])
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_set_date_attribute
|
51
|
+
assert_attribute_set('kMDItemTestDateType', Time.now)
|
52
|
+
end
|
53
|
+
|
54
|
+
def assert_attribute_set(name, value)
|
55
|
+
@item[name] = value
|
56
|
+
assert_equal value, @item.reload[name]
|
57
|
+
end
|
58
|
+
end
|
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mac-spotlight
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Li Xiao
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-05-03 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rake
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :development
|
31
|
+
version_requirements: *id001
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: echoe
|
34
|
+
prerelease: false
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
segments:
|
40
|
+
- 0
|
41
|
+
version: "0"
|
42
|
+
type: :development
|
43
|
+
version_requirements: *id002
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: rake-compiler
|
46
|
+
prerelease: false
|
47
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
type: :development
|
55
|
+
version_requirements: *id003
|
56
|
+
description: Spotlight - Ruby interface to Mac OSX Spotlight
|
57
|
+
email: iam@li-xiao.com
|
58
|
+
executables: []
|
59
|
+
|
60
|
+
extensions:
|
61
|
+
- ext/spotlight/extconf.rb
|
62
|
+
extra_rdoc_files:
|
63
|
+
- README.rdoc
|
64
|
+
- TODO
|
65
|
+
- ext/spotlight/extconf.rb
|
66
|
+
- ext/spotlight/spotlight.c
|
67
|
+
- lib/spotlight.rb
|
68
|
+
files:
|
69
|
+
- MIT-LICENSE.txt
|
70
|
+
- Manifest
|
71
|
+
- README.rdoc
|
72
|
+
- Rakefile
|
73
|
+
- TODO
|
74
|
+
- ext/spotlight/extconf.rb
|
75
|
+
- ext/spotlight/spotlight.c
|
76
|
+
- lib/spotlight.rb
|
77
|
+
- test/test_file.txt
|
78
|
+
- test/test_spotlight.rb
|
79
|
+
- mac-spotlight.gemspec
|
80
|
+
has_rdoc: true
|
81
|
+
homepage: https://github.com/xli/spotlight
|
82
|
+
licenses: []
|
83
|
+
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options:
|
86
|
+
- --main
|
87
|
+
- README.rdoc
|
88
|
+
- --inline-source
|
89
|
+
- --line-numbers
|
90
|
+
- --charset
|
91
|
+
- UTF-8
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
- ext
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
segments:
|
100
|
+
- 0
|
101
|
+
version: "0"
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
segments:
|
107
|
+
- 1
|
108
|
+
- 2
|
109
|
+
version: "1.2"
|
110
|
+
requirements: []
|
111
|
+
|
112
|
+
rubyforge_project: mac-spotlight
|
113
|
+
rubygems_version: 1.3.6
|
114
|
+
signing_key:
|
115
|
+
specification_version: 3
|
116
|
+
summary: Spotlight - Ruby interface to Mac OSX Spotlight
|
117
|
+
test_files:
|
118
|
+
- test/test_spotlight.rb
|