spotlight 0.0.2 → 0.0.3

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/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: