accessibility_core 0.3.5 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.markdown CHANGED
@@ -1,3 +1,17 @@
1
+ # 0.4.0 - Fill in the gaps and other dubious requirements
2
+
3
+ * Add `Object#load_plist` to match MacRuby's `Object#load_plist`
4
+ * Add `URI::Generic#lastPathComponent` to match `NSURL#lastPathComponent`
5
+ * Add `URI::Generic#pathExtension` to match `NSURL#pathExtension`
6
+ * Add a 50% drop-in replacement for `NSData`
7
+ * Add a 50% drop-in replacement for `NSAttributedString`
8
+ * Add `Object#description` as a freedom patch on MRI
9
+ `NSObject#description` is the Objective-C equivalent to `Object#inspect` in Ruby.
10
+ While the intention is the same, the exact behaviour cannot be mimicked.
11
+
12
+ * Fixed some bugs related to converting arrays from Cocoa to Ruby
13
+
14
+
1
15
  # 0.3.5 - Add some missing bits for MRI
2
16
 
3
17
  * Add `Range#relative_to` to convert ranges to positive indicies
@@ -13,6 +13,8 @@ spin(double seconds)
13
13
 
14
14
  #ifdef NOT_MACRUBY
15
15
 
16
+ VALUE rb_cData;
17
+ VALUE rb_cAttributedString;
16
18
  VALUE rb_mAccessibility;
17
19
  VALUE rb_cElement;
18
20
  VALUE rb_cCGPoint;
@@ -255,20 +257,34 @@ VALUE wrap_array_refs(CFArrayRef array) { WRAP_ARRAY(wrap_ref) }
255
257
  VALUE
256
258
  wrap_string(CFStringRef string)
257
259
  {
258
- return wrap_nsstring((NSString*)string);
260
+ VALUE rb_str = Qnil;
261
+ CFDataRef data = CFStringCreateExternalRepresentation(
262
+ NULL,
263
+ string,
264
+ kCFStringEncodingUTF8,
265
+ 0
266
+ );
267
+ if (data) {
268
+ rb_str = rb_enc_str_new(
269
+ (char*)CFDataGetBytePtr(data),
270
+ CFDataGetLength(data),
271
+ rb_utf8_encoding()
272
+ );
273
+ CFRelease(data);
274
+ }
275
+ else {
276
+ CFRelease(data);
277
+ CFShow(string);
278
+ rb_raise(rb_eRuntimeError, "Could not convert a string to a Ruby string");
279
+ }
280
+
281
+ return rb_str;
259
282
  }
260
283
 
261
284
  VALUE
262
285
  wrap_nsstring(NSString* string)
263
286
  {
264
- // TODO: find a larger scope to apply this autoreleasepool
265
- @autoreleasepool{
266
- return rb_enc_str_new(
267
- [string UTF8String],
268
- [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding],
269
- rb_utf8_encoding()
270
- );
271
- }
287
+ return wrap_string((CFStringRef)string);
272
288
  }
273
289
 
274
290
  CFStringRef
@@ -297,6 +313,89 @@ VALUE wrap_array_nsstrings(NSArray* ary)
297
313
  }
298
314
 
299
315
 
316
+ VALUE
317
+ wrap_attributed_string(CFAttributedStringRef string)
318
+ {
319
+ return wrap_nsattributed_string((NSAttributedString*)string);
320
+ }
321
+
322
+ VALUE
323
+ wrap_nsattributed_string(NSAttributedString* obj)
324
+ {
325
+ WRAP_OBJC(rb_cAttributedString, objc_finalizer);
326
+ }
327
+
328
+ CFAttributedStringRef
329
+ unwrap_attributed_string(VALUE string)
330
+ {
331
+ return (CFAttributedStringRef)unwrap_nsattributed_string(string);
332
+ }
333
+
334
+ NSAttributedString*
335
+ unwrap_nsattributed_string(VALUE obj)
336
+ {
337
+ UNWRAP_OBJC(NSAttributedString);
338
+ }
339
+
340
+ VALUE
341
+ wrap_array_attributed_strings(CFArrayRef array)
342
+ {
343
+ WRAP_ARRAY(wrap_attributed_string);
344
+ }
345
+
346
+ VALUE wrap_array_nsattributed_strings(NSArray* ary)
347
+ {
348
+ CFArrayRef array = (CFArrayRef)ary;
349
+ WRAP_ARRAY(wrap_nsattributed_string);
350
+ }
351
+
352
+ static
353
+ VALUE
354
+ rb_astring_alloc(VALUE self)
355
+ {
356
+ return wrap_nsattributed_string([NSAttributedString alloc]);
357
+ }
358
+
359
+ static
360
+ VALUE
361
+ rb_astring_init_with_string(int argc, VALUE* argv, VALUE self)
362
+ {
363
+ if (!argc)
364
+ rb_raise(rb_eArgError, "wrong number of arguments (0 for 1+)");
365
+
366
+ NSString* nsstring = unwrap_nsstring(argv[0]);
367
+ NSAttributedString* old_astring = unwrap_nsattributed_string(self);
368
+ NSAttributedString* new_astring = [old_astring initWithString:nsstring];
369
+ [nsstring release];
370
+ if (old_astring == new_astring)
371
+ return self;
372
+ return wrap_nsattributed_string(new_astring);
373
+ }
374
+
375
+ static
376
+ VALUE
377
+ rb_astring_string(VALUE self)
378
+ {
379
+ NSString* string = [unwrap_nsattributed_string(self) string];
380
+ VALUE rb_str = wrap_nsstring(string);
381
+ return rb_str;
382
+ }
383
+
384
+ static
385
+ VALUE
386
+ rb_astring_length(VALUE self)
387
+ {
388
+ return ULONG2NUM([unwrap_nsattributed_string(self) length]);
389
+ }
390
+
391
+ static
392
+ VALUE
393
+ rb_astring_equality(VALUE self, VALUE other)
394
+ {
395
+ OBJC_EQUALITY(rb_cAttributedString, unwrap_nsattributed_string);
396
+ }
397
+
398
+
300
399
  #define WRAP_NUM(type, cookie, macro) do { \
301
400
  type value; \
302
401
  if (CFNumberGetValue(num, cookie, &value)) \
@@ -456,16 +555,21 @@ VALUE wrap_array_booleans(CFArrayRef array) { WRAP_ARRAY(wrap_boolean) }
456
555
  VALUE
457
556
  wrap_array(CFArrayRef array)
458
557
  {
459
- CFTypeRef obj = CFArrayGetValueAtIndex(array, 0);
460
- CFTypeID di = CFGetTypeID(obj);
461
- if (di == AXUIElementGetTypeID()) return wrap_array_refs(array);
462
- else if (di == AXValueGetTypeID()) return wrap_array_values(array);
463
- else if (di == CFStringGetTypeID()) return wrap_array_strings(array);
464
- else if (di == CFNumberGetTypeID()) return wrap_array_numbers(array);
465
- else if (di == CFBooleanGetTypeID()) return wrap_array_booleans(array);
466
- else if (di == CFURLGetTypeID()) return wrap_array_urls(array);
467
- else if (di == CFDateGetTypeID()) return wrap_array_dates(array);
468
- else return wrap_unknown(obj);
558
+ CFIndex length = CFArrayGetCount(array);
559
+ if (length) {
560
+ CFTypeRef obj = CFArrayGetValueAtIndex(array, 0);
561
+ CFTypeID di = CFGetTypeID(obj);
562
+ if (di == AXUIElementGetTypeID()) return wrap_array_refs(array);
563
+ else if (di == AXValueGetTypeID()) return wrap_array_values(array);
564
+ else if (di == CFStringGetTypeID()) return wrap_array_strings(array);
565
+ else if (di == CFNumberGetTypeID()) return wrap_array_numbers(array);
566
+ else if (di == CFBooleanGetTypeID()) return wrap_array_booleans(array);
567
+ else if (di == CFURLGetTypeID()) return wrap_array_urls(array);
568
+ else if (di == CFDateGetTypeID()) return wrap_array_dates(array);
569
+ else if (di == CFDictionaryGetTypeID()) return wrap_array_dictionaries(array);
570
+ else return wrap_unknown(obj);
571
+ }
572
+ return rb_ary_new();
469
573
  }
470
574
 
471
575
 
@@ -481,22 +585,25 @@ wrap_dictionary(NSDictionary* dict)
481
585
  return hash;
482
586
  }
483
587
 
588
+ VALUE wrap_array_dictionaries(CFArrayRef array) { WRAP_ARRAY(wrap_dictionary); }
484
589
 
485
590
 
486
591
  VALUE
487
592
  to_ruby(CFTypeRef obj)
488
593
  {
489
594
  CFTypeID di = CFGetTypeID(obj);
490
- if (di == CFArrayGetTypeID()) return wrap_array(obj);
491
- else if (di == AXUIElementGetTypeID()) return wrap_ref(obj);
492
- else if (di == AXValueGetTypeID()) return wrap_value(obj);
493
- else if (di == CFStringGetTypeID()) return wrap_string(obj);
494
- else if (di == CFNumberGetTypeID()) return wrap_number(obj);
495
- else if (di == CFBooleanGetTypeID()) return wrap_boolean(obj);
496
- else if (di == CFURLGetTypeID()) return wrap_url(obj);
497
- else if (di == CFDateGetTypeID()) return wrap_date(obj);
498
- else if (di == CFDictionaryGetTypeID()) return wrap_dictionary(obj);
499
- else return wrap_unknown(obj);
595
+ if (di == CFArrayGetTypeID()) return wrap_array(obj);
596
+ else if (di == AXUIElementGetTypeID()) return wrap_ref(obj);
597
+ else if (di == AXValueGetTypeID()) return wrap_value(obj);
598
+ else if (di == CFStringGetTypeID()) return wrap_string(obj);
599
+ else if (di == CFNumberGetTypeID()) return wrap_number(obj);
600
+ else if (di == CFBooleanGetTypeID()) return wrap_boolean(obj);
601
+ else if (di == CFURLGetTypeID()) return wrap_url(obj);
602
+ else if (di == CFDateGetTypeID()) return wrap_date(obj);
603
+ else if (di == CFDataGetTypeID()) return wrap_data(obj);
604
+ else if (di == CFAttributedStringGetTypeID()) return wrap_attributed_string(obj);
605
+ else if (di == CFDictionaryGetTypeID()) return wrap_dictionary(obj);
606
+ else return wrap_unknown(obj);
500
607
  }
501
608
 
502
609
  CFTypeRef
@@ -513,8 +620,9 @@ to_ax(VALUE obj)
513
620
  case T_FLOAT:
514
621
  return unwrap_number(obj);
515
622
  case T_TRUE:
623
+ return kCFBooleanTrue;
516
624
  case T_FALSE:
517
- return unwrap_boolean(obj);
625
+ return kCFBooleanFalse;
518
626
  }
519
627
 
520
628
  VALUE type = CLASS_OF(obj);
@@ -522,6 +630,10 @@ to_ax(VALUE obj)
522
630
  return unwrap_date(obj);
523
631
  else if (type == rb_cRange)
524
632
  return unwrap_value_range(obj);
633
+ else if (type == rb_cAttributedString)
634
+ return unwrap_attributed_string(obj);
635
+ else if (type == rb_cData)
636
+ return unwrap_data(obj);
525
637
 
526
638
  if (rb_obj_is_kind_of(obj, rb_cURI))
527
639
  return unwrap_url(obj);
@@ -531,8 +643,114 @@ to_ax(VALUE obj)
531
643
  }
532
644
 
533
645
 
646
+ VALUE
647
+ wrap_data(CFDataRef data)
648
+ {
649
+ return wrap_nsdata((NSData*)data);
650
+ }
651
+
652
+ VALUE
653
+ wrap_nsdata(NSData* obj)
654
+ {
655
+ WRAP_OBJC(rb_cData, objc_finalizer);
656
+ }
657
+
658
+ VALUE wrap_array_data(CFArrayRef array) { WRAP_ARRAY(wrap_data); }
659
+ VALUE
660
+ wrap_array_nsdata(NSArray* ary)
661
+ {
662
+ CFArrayRef array = (CFArrayRef)ary;
663
+ WRAP_ARRAY(wrap_data);
664
+ }
665
+
666
+ CFDataRef
667
+ unwrap_data(VALUE data)
668
+ {
669
+ return (CFDataRef)unwrap_nsdata(data);
670
+ }
671
+
672
+ NSData*
673
+ unwrap_nsdata(VALUE obj)
674
+ {
675
+ UNWRAP_OBJC(NSData);
676
+ }
677
+
678
+
679
+ static
680
+ VALUE
681
+ rb_data_data(VALUE self)
682
+ {
683
+ return wrap_nsdata([NSData data]);
684
+ }
685
+
686
+ static
687
+ VALUE
688
+ rb_data_with_contents_of_url(VALUE self, VALUE url)
689
+ {
690
+ NSData* data = [NSData dataWithContentsOfURL:unwrap_nsurl(url)];
691
+ if (data)
692
+ return wrap_nsdata(data);
693
+ return Qnil;
694
+ }
695
+
696
+ static
697
+ VALUE
698
+ rb_data_length(VALUE self)
699
+ {
700
+ return ULONG2NUM([unwrap_nsdata(self) length]);
701
+ }
702
+
703
+ static
704
+ VALUE
705
+ rb_data_equality(VALUE self, VALUE other)
706
+ {
707
+ OBJC_EQUALITY(rb_cData, unwrap_nsdata);
708
+ }
709
+
534
710
  static
535
711
  VALUE
712
+ rb_data_write_to_file(int argc, VALUE* argv, VALUE self)
713
+ {
714
+ if (argc < 2)
715
+ rb_raise(
716
+ rb_eArgError,
717
+ "wrong number of arguments, got %d, expected 2",
718
+ argc
719
+ );
720
+
721
+ NSString* path = unwrap_nsstring(argv[0]);
722
+ BOOL result = [unwrap_nsdata(self) writeToFile:path
723
+ atomically:(argv[1] == Qtrue)];
724
+
725
+ [path release];
726
+
727
+ return (result ? Qtrue : Qfalse);
728
+ }
729
+
730
+
731
+ static
732
+ VALUE
733
+ rb_data_to_str(VALUE self)
734
+ {
735
+ NSData* data = unwrap_nsdata(self);
736
+ const void* bytes = [data bytes];
737
+ NSUInteger length = [data length];
738
+ return rb_enc_str_new(bytes, length, rb_utf8_encoding());
739
+ }
740
+
741
+ static
742
+ VALUE
743
+ rb_str_to_data(VALUE self)
744
+ {
745
+ NSData* data = [NSData dataWithBytes:(void*)StringValuePtr(self)
746
+ length:RSTRING_LEN(self)];
747
+ if (data)
748
+ return wrap_nsdata(data);
749
+ return Qnil; // I don't think this is possible except in case of ENOMEM
750
+ }
751
+
752
+
753
+ static VALUE
536
754
  rb_spin(int argc, VALUE* argv, VALUE self)
537
755
  {
538
756
  if (argc == 0)
@@ -570,6 +788,67 @@ Init_bridge()
570
788
  rb_mURI = rb_const_get(rb_cObject, rb_intern("URI"));
571
789
  rb_cURI = rb_const_get(rb_mURI, rb_intern("Generic"));
572
790
 
791
+
792
+ /*
793
+ * Document-class: NSAttributedString
794
+ *
795
+ * A 90% drop-in replacement for Cocoa's `NSAttributedString` class. The most likely
796
+ * to use methods have been bridged. Remaining methods can be bridged upon request.
797
+ *
798
+ * See [Apple's Developer Reference](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSAttributedString_Class/Reference/Reference.html)
799
+ * for documentation on the methods available in this class.
800
+ */
801
+ rb_cAttributedString = rb_define_class("NSAttributedString", rb_cObject);
802
+
803
+ // LOL, but required to be a drop-in replacement
804
+ rb_define_singleton_method(rb_cAttributedString, "alloc", rb_astring_alloc, 0);
805
+
806
+ // TODO: all these methods :(
807
+ rb_define_method(rb_cAttributedString, "initWithString", rb_astring_init_with_string, -1);
808
+ /* rb_define_method(rb_cAttributedString, "initWithAttributedString", rb_astring_init_with_astring, 2); */
809
+ rb_define_method(rb_cAttributedString, "string", rb_astring_string, 0);
810
+ rb_define_method(rb_cAttributedString, "length", rb_astring_length, 0);
811
+ /* rb_define_method(rb_cAttributedString, "attributesAtIndex", rb_astring_attrs_at_index, -1); */
812
+ rb_define_method(rb_cAttributedString, "isEqualToAttributedString", rb_astring_equality, 1);
813
+ /* rb_define_method(rb_cAttributedString, "attributedSubstringFromRange", rb_astring_astring_from_range, 1); */
814
+
815
+ rb_define_alias(rb_cAttributedString, "to_s", "string");
816
+ rb_define_alias(rb_cAttributedString, "to_str", "string");
817
+ rb_define_alias(rb_cAttributedString, "==", "isEqualToAttributedString");
818
+
819
+
820
+ /*
821
+ * Document-class: NSData
822
+ *
823
+ * A 50% drop-in replacement for Cocoa's `NSData` class. Almost all
824
+ * non-deprecated methods have been bridged.
825
+ *
826
+ * See [Apple's Developer Reference](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/Reference/Reference.html)
827
+ * for documentation on the methods available in this class.
828
+ */
829
+ rb_cData = rb_define_class("NSData", rb_cObject);
830
+
831
+ // TODO: implement commented out methods
832
+ rb_define_singleton_method(rb_cData, "data", rb_data_data, 0);
833
+ //rb_define_singleton_method(rb_cData, "dataWithBytes", rb_data_with_bytes, 2);
834
+ //rb_define_singleton_method(rb_cData, "dataWithContentsOfFile", rb_data_with_contents_of_file, 1);
835
+ rb_define_singleton_method(rb_cData, "dataWithContentsOfURL", rb_data_with_contents_of_url, 1);
836
+ //rb_define_singleton_method(rb_cData, "dataWithData", rb_data_with_data, 1);
837
+
838
+ //rb_define_method(rb_cData, "bytes", rb_data_bytes, 0);
839
+ //rb_define_method(rb_cData, "description", rb_data_description, 0);
840
+ //rb_define_method(rb_cData, "subdataWithRange", rb_data_subrange, 1);
841
+ rb_define_method(rb_cData, "isEqualToData", rb_data_equality, 1);
842
+ rb_define_method(rb_cData, "length", rb_data_length, 0);
843
+ rb_define_method(rb_cData, "writeToFile", rb_data_write_to_file, -1);
844
+ //rb_define_method(rb_cData, "writeToURL", rb_data_write_to_url, -1);
845
+ rb_define_method(rb_cData, "to_str", rb_data_to_str, 0);
846
+
847
+ rb_define_alias(rb_cData, "==", "isEqualToData");
848
+
849
+
850
+ // misc freedom patches
851
+ rb_define_method(rb_cString, "to_data", rb_str_to_data, 0);
573
852
  rb_define_method(rb_cObject, "spin", rb_spin, -1); // semi-private method
574
853
  #endif
575
854
  }
@@ -11,6 +11,8 @@ void Init_bridge();
11
11
 
12
12
  #ifdef NOT_MACRUBY
13
13
 
14
+ extern VALUE rb_cData;
15
+ extern VALUE rb_cAttributedString;
14
16
  extern VALUE rb_mAccessibility;
15
17
  extern VALUE rb_cElement;
16
18
  extern VALUE rb_cCGPoint;
@@ -43,6 +45,13 @@ extern ID sel_parse;
43
45
  return unwrapped; \
44
46
  } while (false);
45
47
 
48
+ #define OBJC_EQUALITY(type, unwrapper) do { \
49
+ if (CLASS_OF(other) == type) \
50
+ if ([unwrapper(self) isEqual:unwrapper(other)]) \
51
+ return Qtrue; \
52
+ return Qfalse; \
53
+ } while (false);
54
+
46
55
  #define WRAP_ARRAY(wrapper) do { \
47
56
  CFIndex length = CFArrayGetCount(array); \
48
57
  VALUE ary = rb_ary_new2(length); \
@@ -129,11 +138,17 @@ VALUE wrap_boolean(CFBooleanRef bool_val);
129
138
  VALUE wrap_array_booleans(CFArrayRef array);
130
139
  CFBooleanRef unwrap_boolean(VALUE bool_val);
131
140
 
141
+ VALUE wrap_data(CFDataRef data);
142
+ VALUE wrap_nsdata(NSData* data);
143
+ CFDataRef unwrap_data(VALUE data);
144
+ NSData* unwrap_nsdata(VALUE data);
145
+
132
146
  // this function assumes that arrays are homogeneous;
133
147
  // which is usually the case coming from the CF world
134
148
  VALUE wrap_array(CFArrayRef array);
135
149
 
136
150
  VALUE wrap_dictionary(NSDictionary* dict);
151
+ VALUE wrap_array_dictionaries(CFArrayRef array);
137
152
 
138
153
  VALUE to_ruby(CFTypeRef obj);
139
154
  CFTypeRef to_ax(VALUE obj);
@@ -142,4 +157,18 @@ VALUE wrap_screen(NSScreen* screen);
142
157
  VALUE wrap_array_screens(CFArrayRef array);
143
158
  NSScreen* unwrap_screen(VALUE screen);
144
159
 
160
+ VALUE wrap_attributed_string(CFAttributedStringRef string);
161
+ VALUE wrap_nsattributed_string(NSAttributedString* string);
162
+ VALUE wrap_array_attributed_strings(CFArrayRef array);
163
+ VALUE wrap_array_nsattributed_strings(NSArray* ary);
164
+ CFAttributedStringRef unwrap_attributed_string(VALUE string);
165
+ NSAttributedString* unwrap_nsattributed_string(VALUE string);
166
+
167
+ VALUE wrap_data(CFDataRef data);
168
+ VALUE wrap_nsdata(NSData* data);
169
+ VALUE wrap_array_data(CFArrayRef array);
170
+ VALUE wrap_array_nsdata(NSArray* array);
171
+ CFDataRef unwrap_data(VALUE data);
172
+ NSData* unwrap_nsdata(VALUE data);
173
+
145
174
  #endif
@@ -444,6 +444,29 @@ rb_bundle_object_for_info_dict_key(VALUE self, VALUE key)
444
444
  }
445
445
 
446
446
 
447
+ static
448
+ VALUE
449
+ rb_load_plist(VALUE self, VALUE plist_data)
450
+ {
451
+ NSData* data = [NSData dataWithBytes:(void*)StringValueCStr(plist_data)
452
+ length:RSTRING_LEN(plist_data)];
453
+ NSError* err = nil;
454
+ id plist = [NSPropertyListSerialization propertyListWithData:data
455
+ options:0
456
+ format:nil
457
+ error:&err];
458
+ [data release];
459
+ if (plist) {
460
+ VALUE list = to_ruby(plist);
461
+ [plist release];
462
+ return list;
463
+ }
464
+
465
+ rb_raise(rb_eArgError, "error loading property list: '%s'",
466
+ [[err localizedDescription] UTF8String]);
467
+ return Qnil; // unreachable
468
+ }
469
+
447
470
  VALUE wrap_screen(NSScreen* obj) { WRAP_OBJC(rb_cScreen, NULL); }
448
471
  VALUE wrap_array_screens(CFArrayRef array) { WRAP_ARRAY(wrap_screen); }
449
472
  NSScreen* unwrap_screen(VALUE obj) { UNWRAP_OBJC(NSScreen); }
@@ -837,6 +860,9 @@ Init_extras()
837
860
  rb_define_singleton_method(rb_cBundle, "bundleWithURL", rb_bundle_with_url, 1);
838
861
  rb_define_method(rb_cBundle, "infoDictionary", rb_bundle_info_dict, 0);
839
862
  rb_define_method(rb_cBundle, "objectForInfoDictionaryKey", rb_bundle_object_for_info_dict_key, 1);
863
+
864
+
865
+ rb_define_method(rb_cObject, "load_plist", rb_load_plist, 1);
840
866
  #endif
841
867
 
842
868
 
@@ -106,6 +106,39 @@ class URI::Generic
106
106
  def to_url
107
107
  self
108
108
  end
109
+
110
+ ##
111
+ # Return the last component of the path of the URL
112
+ #
113
+ # This is intended to help make {URI::Generic} closer to being
114
+ # a drop-in replacement for {NSURL}.
115
+ #
116
+ # @example
117
+ #
118
+ # url = "https://macruby.macosforge.org/files/nightlies/macruby_nightly-latest.pkg"
119
+ # URI.parse(url).lastPathComponent # => "macruby_nightly-latest.pkg"
120
+ #
121
+ # @return [String]
122
+ def lastPathComponent
123
+ self.path.split(%r{/+}).last
124
+ end
125
+
126
+ ##
127
+ # Returns the path extension of a file URL
128
+ #
129
+ # This is intended to help make {URI::Generic} closer to being
130
+ # a drop-in replacement for {NSURL}.
131
+ #
132
+ # @example
133
+ #
134
+ # url = "https://macruby.macosforge.org/files/nightlies/macruby_nightly-latest.pkg"
135
+ # URI.parse(url).pathExtension # => "pkg"
136
+ #
137
+ # @return [String]
138
+ def pathExtension
139
+ split = self.path.split '.', -1
140
+ split.size > 1 ? split.last : ''
141
+ end
109
142
  end
110
143
 
111
144
  ##
@@ -137,6 +170,17 @@ class Object
137
170
  def NSContainsRect outer, inner
138
171
  outer.to_rect.contains? inner
139
172
  end
173
+
174
+ ##
175
+ # An alias for `Object#inspect`
176
+ #
177
+ # This exists to help make code more compatible between MacRuby
178
+ # and CRuby.
179
+ #
180
+ # @return [String]
181
+ def description
182
+ inspect
183
+ end
140
184
  end
141
185
 
142
186
  ##
@@ -6,6 +6,6 @@ module Accessibility
6
6
  # Namespace for `accessibility_core` specific classes
7
7
  module Core
8
8
  # return [String]
9
- VERSION = '0.3.5'
9
+ VERSION = '0.4.0'
10
10
  end
11
11
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: accessibility_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-27 00:00:00.000000000 Z
12
+ date: 2013-01-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: yard
@@ -107,7 +107,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
107
107
  version: '0'
108
108
  segments:
109
109
  - 0
110
- hash: 865923332438012461
110
+ hash: -989078667386493475
111
111
  required_rubygems_version: !ruby/object:Gem::Requirement
112
112
  none: false
113
113
  requirements:
@@ -116,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
116
  version: '0'
117
117
  segments:
118
118
  - 0
119
- hash: 865923332438012461
119
+ hash: -989078667386493475
120
120
  requirements: []
121
121
  rubyforge_project:
122
122
  rubygems_version: 1.8.24