spotlight 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -9,15 +9,24 @@ Description goes here.
9
9
  === Finds files matching a given query
10
10
 
11
11
  query = Spotlight::Query.new('kMDItemKind = "JPEG image" && kMDItemPixelHeight > 2000')
12
+ query.scopes << '/Users/youpy/'
12
13
  query.execute.map {|item|
13
14
  puts item.get(:kMDItemPath)
14
15
  }
15
16
 
16
- === Gets the metadata attributes for the specified file
17
+ === Creates query from .savedSearch
18
+
19
+ query = Spotlight::Query.from_saved_search('foo.savedSearch')
20
+
21
+ === Gets the metadata attribute for the specified file
17
22
 
18
23
  item = Spotlight::Item.new('/Users/youpy/foo')
19
24
  item.get(:kMDItemKind)
20
25
 
26
+ === Gets the metadata attribute names for the specified file
27
+
28
+ item.attribute_names
29
+
21
30
  == Note on Patches/Pull Requests
22
31
 
23
32
  * Fork the project.
@@ -9,7 +9,73 @@ struct ItemObject {
9
9
  CFStringRef CString2CFString(char *str) {
10
10
  return CFStringCreateWithCString(kCFAllocatorDefault,
11
11
  str,
12
- CFStringGetSystemEncoding());
12
+ kCFStringEncodingUTF8);
13
+ }
14
+
15
+ VALUE CFString2RString(CFStringRef str) {
16
+ int stringSize;
17
+ char *tmpptr;
18
+ VALUE result;
19
+
20
+ stringSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8) + 1;
21
+ tmpptr = (char *)malloc(sizeof(char) * stringSize);
22
+ CFStringGetCString(str, tmpptr, stringSize, kCFStringEncodingUTF8);
23
+ result = rb_str_new2(tmpptr);
24
+ free(tmpptr);
25
+
26
+ return result;
27
+ }
28
+
29
+ VALUE CFType2Value(CFTypeRef thing) {
30
+ int i;
31
+ double doubleValue;
32
+ CFNumberType numberType;
33
+ CFAbsoluteTime timeNow;
34
+ CFGregorianDate current;
35
+ VALUE result;
36
+
37
+ /* CFStringRef stringValue = CFCopyDescription(thing); */
38
+ /* rb_p(CFString2RString(stringValue)); */
39
+ /* CFRelease(stringValue); */
40
+
41
+ if(CFGetTypeID(thing) == CFStringGetTypeID()) {
42
+ result = CFString2RString((CFStringRef)thing);
43
+ } else if(CFGetTypeID(thing) == CFNumberGetTypeID()) {
44
+ numberType = CFNumberGetType((CFNumberRef)thing);
45
+ switch(numberType) {
46
+ case kCFNumberFloat64Type:
47
+ CFNumberGetValue((CFNumberRef)thing, numberType, &doubleValue);
48
+ result = rb_float_new(doubleValue);
49
+ break;
50
+ case kCFNumberSInt32Type:
51
+ case kCFNumberSInt64Type:
52
+ default:
53
+ CFNumberGetValue((CFNumberRef)thing, kCFNumberDoubleType, &doubleValue);
54
+ result = INT2FIX((double)doubleValue);
55
+ break;
56
+ }
57
+ } else if(CFGetTypeID(thing) == CFDateGetTypeID()) {
58
+ timeNow = CFDateGetAbsoluteTime((CFDateRef)thing);
59
+ current = CFAbsoluteTimeGetGregorianDate(timeNow, NULL);
60
+ result = rb_funcall(rb_cTime, rb_intern("gm"), 6,
61
+ INT2FIX((unsigned int)current.year),
62
+ INT2FIX((unsigned int)current.month),
63
+ INT2FIX((unsigned int)current.day),
64
+ INT2FIX((unsigned int)current.hour),
65
+ INT2FIX((unsigned int)current.minute),
66
+ INT2FIX((unsigned int)current.second));
67
+ } else if(CFGetTypeID(thing) == CFBooleanGetTypeID()) {
68
+ result = CFBooleanGetValue(thing) ? Qtrue : Qfalse;
69
+ } else if(CFGetTypeID(thing) == CFArrayGetTypeID()) {
70
+ result = rb_ary_new();
71
+ for(i = 0; i < CFArrayGetCount(thing); i ++) {
72
+ rb_ary_push(result, CFType2Value(CFArrayGetValueAtIndex(thing, i)));
73
+ }
74
+ } else {
75
+ result = Qnil;
76
+ }
77
+
78
+ return result;
13
79
  }
14
80
 
15
81
  MDItemRef getItem(VALUE obj) {
@@ -27,6 +93,7 @@ void cMDItemNative_free(void *ptr) {
27
93
  }
28
94
 
29
95
  free(ptr);
96
+
30
97
  /* printf("cMDItemNative_free()\n"); */
31
98
  }
32
99
 
@@ -53,7 +120,7 @@ static VALUE cMDItemNative_new(int argc, VALUE *argv, VALUE klass)
53
120
  if(item != NULL) {
54
121
  obj = createInstanceFromMDItem(item);
55
122
  } else {
56
- rb_raise(rb_eArgError, "no such file or directory");
123
+ rb_raise(rb_eArgError, "no such file or directory: %s", filename);
57
124
  }
58
125
 
59
126
  CFRelease(cfFilename);
@@ -64,11 +131,10 @@ static VALUE cMDItemNative_new(int argc, VALUE *argv, VALUE klass)
64
131
  static VALUE cMDItemNative_get(int argc, VALUE *argv, VALUE self)
65
132
  {
66
133
  MDItemRef item = getItem(self);
67
- CFStringRef itemValue, cfAttrName;
134
+ CFTypeRef itemValue;
135
+ CFStringRef cfAttrName;
68
136
  VALUE attrName, result;
69
- char *tmpptr;
70
- int stringSize;
71
-
137
+
72
138
  rb_scan_args(argc, argv, "1", &attrName);
73
139
 
74
140
  if(TYPE(attrName) == T_SYMBOL) {
@@ -77,23 +143,41 @@ static VALUE cMDItemNative_get(int argc, VALUE *argv, VALUE self)
77
143
  cfAttrName = (CFStringRef)CString2CFString(StringValuePtr(attrName));
78
144
  }
79
145
 
80
- itemValue = (CFStringRef)MDItemCopyAttribute(item, cfAttrName);
146
+ /* rb_p(CFString2RString(cfAttrName)); */
147
+
148
+ itemValue = MDItemCopyAttribute(item, cfAttrName);
149
+
150
+ CFRelease(cfAttrName);
81
151
 
82
152
  if(itemValue != NULL) {
83
- stringSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(itemValue), kCFStringEncodingUTF8) + 1;
84
- tmpptr = (char *)malloc(sizeof(char) * stringSize);
153
+ result = CFType2Value(itemValue);
154
+ CFRelease(itemValue);
155
+ return result;
156
+ }
85
157
 
86
- CFStringGetCString(itemValue, tmpptr, stringSize, kCFStringEncodingUTF8);
158
+ return Qnil;
159
+ }
87
160
 
88
- result = rb_str_new2(tmpptr);
161
+ static VALUE cMDItemNative_attribute_names(int argc, VALUE *argv, VALUE self)
162
+ {
163
+ MDItemRef item = getItem(self);
164
+ CFArrayRef cfAttributeNames;
165
+ VALUE result = rb_ary_new();
166
+ int numAttributes, i;
89
167
 
90
- free(tmpptr);
91
- CFRelease(cfAttrName);
92
- CFRelease(itemValue);
93
- } else {
94
- return Qnil;
168
+ rb_scan_args(argc, argv, "0");
169
+
170
+ cfAttributeNames = MDItemCopyAttributeNames(item);
171
+
172
+ if(cfAttributeNames != NULL) {
173
+ numAttributes = (int)CFArrayGetCount(cfAttributeNames);
174
+ for(i = 0; i < numAttributes; i ++) {
175
+ rb_ary_push(result, CFString2RString((CFStringRef)CFArrayGetValueAtIndex(cfAttributeNames, i)));
176
+ }
95
177
  }
96
178
 
179
+ CFRelease(cfAttributeNames);
180
+
97
181
  return result;
98
182
  }
99
183
 
@@ -104,4 +188,5 @@ void Init_md_item_native(void){
104
188
  rb_cMDItemNative = rb_define_class_under(rb_mSpotlight, "MDItemNative", rb_cObject);
105
189
  rb_define_singleton_method(rb_cMDItemNative, "new", cMDItemNative_new, -1);
106
190
  rb_define_method(rb_cMDItemNative, "get", cMDItemNative_get, -1);
191
+ rb_define_method(rb_cMDItemNative, "attribute_names", cMDItemNative_attribute_names, -1);
107
192
  }
@@ -3,6 +3,8 @@
3
3
 
4
4
  #include <ruby.h>
5
5
  #include </System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Headers/MDItem.h>
6
+ #include </System/Library/Frameworks/CoreFoundation.framework/Versions/A/Headers/CFDate.h>
7
+ #include </System/Library/Frameworks/CoreFoundation.framework/Versions/A/Headers/CFNumber.h>
6
8
 
7
9
  VALUE createInstanceFromMDItem(MDItemRef item);
8
10
 
@@ -1,8 +1,18 @@
1
+ require 'rubygems'
2
+ require 'plist'
3
+
1
4
  module Spotlight
2
5
  class Query
3
6
  attr_reader :query_string
4
7
  attr_accessor :scopes
5
8
 
9
+ def self.from_saved_search(filename)
10
+ plist = Plist::parse_xml(filename)
11
+ query = new(plist['RawQuery'])
12
+ query.scopes = plist['SearchCriteria']['FXScopeArrayOfPaths']
13
+ query
14
+ end
15
+
6
16
  def initialize(query_string)
7
17
  @query_string = query_string
8
18
  @scopes = []
@@ -2,19 +2,30 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe Spotlight::MDItemNative do
4
4
  before do
5
- @query = Spotlight::MDItemNative.new(__FILE__)
5
+ @item = Spotlight::MDItemNative.new(__FILE__)
6
+ @filename = File.basename(__FILE__)
6
7
  end
7
8
 
8
9
  it "should instanciate" do
9
- @query.should be_an_instance_of(Spotlight::MDItemNative)
10
+ @item.should be_an_instance_of(Spotlight::MDItemNative)
10
11
  end
11
12
 
12
13
  it "should get attribute by name" do
13
- @query.get('kMDItemKind').should eql('Ruby Source File')
14
- @query.get(:kMDItemKind).should eql('Ruby Source File')
14
+ @item.get('kMDItemKind').should eql('Ruby Source File')
15
+ @item.get(:kMDItemKind).should eql('Ruby Source File')
16
+ @item.get(:kMDItemFSName).should eql(@filename)
17
+ @item.get(:kMDItemFSCreationDate).should be_an_instance_of(Time)
18
+ @item.get(:kMDItemFSOwnerUserID).should be_an_instance_of(Fixnum)
19
+ @item.get(:kMDItemFSIsExtensionHidden).should be_an_instance_of(FalseClass)
15
20
  end
16
21
 
17
22
  it "should get nil if attribute is not found" do
18
- @query.get('kMDXXXXXX').should be_nil
23
+ @item.get('kMDXXXXXX').should be_nil
24
+ end
25
+
26
+ it "should get attribute names" do
27
+ attribute_names = @item.attribute_names
28
+ attribute_names.should be_an_instance_of(Array)
29
+ attribute_names.should be_include('kMDItemKind')
19
30
  end
20
31
  end
data/spec/spec_helper.rb CHANGED
@@ -4,6 +4,10 @@ require 'spotlight'
4
4
  require 'spec'
5
5
  require 'spec/autorun'
6
6
 
7
+ system('mdimport ' + File.dirname(__FILE__))
8
+
7
9
  Spec::Runner.configure do |config|
8
-
10
+ def fixture(filename)
11
+ File.dirname(__FILE__) + '/fixtures/' + filename
12
+ end
9
13
  end
@@ -5,6 +5,12 @@ describe Spotlight::Query do
5
5
  @query = Spotlight::Query.new('kMDItemDisplayName = "spotlight_query_spec.rb"')
6
6
  end
7
7
 
8
+ it "should create query from saved search" do
9
+ query = Spotlight::Query.from_saved_search(fixture('test.savedSearch'))
10
+ query.query_string.should eql('((true) && (true)) && ((* = "test*"cdw || kMDItemTextContent = "test*"cdw))')
11
+ query.scopes.should eql(['kMDQueryScopeComputer'])
12
+ end
13
+
8
14
  it "should have query string" do
9
15
  @query.query_string.should eql('kMDItemDisplayName = "spotlight_query_spec.rb"')
10
16
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spotlight
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - youpy
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-16 00:00:00 +09:00
12
+ date: 2010-02-18 00:00:00 +09:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -32,6 +32,16 @@ dependencies:
32
32
  - !ruby/object:Gem::Version
33
33
  version: "0"
34
34
  version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: plist
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
35
45
  description: Library to use Spotlight from Ruby
36
46
  email: youpy@buycheapviagraonlinenow.com
37
47
  executables: []
@@ -51,7 +61,7 @@ files:
51
61
  - LICENSE
52
62
  - README.rdoc
53
63
  has_rdoc: true
54
- homepage: http://github.com/youpy/spotlight
64
+ homepage: http://github.com/youpy/ruby-spotlight
55
65
  licenses: []
56
66
 
57
67
  post_install_message: