rb-appscript 0.5.0 → 0.5.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.
Files changed (59) hide show
  1. data/CHANGES +19 -0
  2. data/LICENSE +1 -1
  3. data/README +5 -5
  4. data/TODO +3 -1
  5. data/doc/aem-manual/01_introduction.html +2 -2
  6. data/doc/aem-manual/02_apioverview.html +2 -2
  7. data/doc/aem-manual/03_packingandunpackingdata.html +2 -2
  8. data/doc/aem-manual/04_references.html +9 -21
  9. data/doc/aem-manual/05_targettingapplications.html +3 -3
  10. data/doc/aem-manual/06_buildingandsendingevents.html +2 -2
  11. data/doc/aem-manual/07_findapp.html +2 -2
  12. data/doc/aem-manual/08_examples.html +3 -3
  13. data/doc/aem-manual/index.html +2 -2
  14. data/doc/appscript-manual/01_introduction.html +2 -2
  15. data/doc/appscript-manual/02_aboutappscripting.html +2 -2
  16. data/doc/appscript-manual/03_quicktutorial.html +2 -2
  17. data/doc/appscript-manual/04_gettinghelp.html +2 -2
  18. data/doc/appscript-manual/05_keywordconversion.html +2 -2
  19. data/doc/appscript-manual/06_classesandenums.html +2 -2
  20. data/doc/appscript-manual/07_applicationobjects.html +2 -2
  21. data/doc/appscript-manual/08_realvsgenericreferences.html +2 -2
  22. data/doc/appscript-manual/09_referenceforms.html +3 -3
  23. data/doc/appscript-manual/10_referenceexamples.html +2 -2
  24. data/doc/appscript-manual/11_applicationcommands.html +2 -2
  25. data/doc/appscript-manual/12_commandexamples.html +2 -2
  26. data/doc/appscript-manual/13_performanceissues.html +2 -2
  27. data/doc/appscript-manual/14_notes.html +2 -2
  28. data/doc/appscript-manual/index.html +2 -2
  29. data/doc/{appscript-manual/full.css → full.css} +0 -0
  30. data/doc/index.html +2 -2
  31. data/doc/mactypes-manual/index.html +2 -2
  32. data/doc/osax-manual/index.html +6 -6
  33. data/extconf.rb +13 -3
  34. data/rb-appscript.gemspec +2 -1
  35. data/src/lib/_aem/aemreference.rb +22 -31
  36. data/src/lib/_aem/codecs.rb +21 -19
  37. data/src/lib/_aem/connect.rb +7 -3
  38. data/src/lib/_aem/findapp.rb +7 -3
  39. data/src/lib/_aem/mactypes.rb +22 -14
  40. data/src/lib/_aem/send.rb +7 -3
  41. data/src/lib/_aem/typewrappers.rb +7 -3
  42. data/src/lib/_appscript/defaultterminology.rb +7 -3
  43. data/src/lib/_appscript/referencerenderer.rb +7 -3
  44. data/src/lib/_appscript/reservedkeywords.rb +8 -3
  45. data/src/lib/_appscript/safeobject.rb +12 -2
  46. data/src/lib/_appscript/terminology.rb +31 -15
  47. data/src/lib/aem.rb +8 -3
  48. data/src/lib/appscript.rb +74 -46
  49. data/src/lib/osax.rb +7 -6
  50. data/src/rbae.c +46 -77
  51. data/test/test_aemreference.rb +10 -4
  52. data/test/test_appscriptcommands.rb +3 -1
  53. data/test/test_appscriptreference.rb +5 -3
  54. data/test/test_codecs.rb +3 -1
  55. data/test/test_findapp.rb +3 -1
  56. data/test/test_mactypes.rb +12 -6
  57. data/test/test_osax.rb +3 -6
  58. metadata +44 -38
  59. data/doc/aem-manual/full.css +0 -21
@@ -1,6 +1,10 @@
1
- #!/usr/local/bin/ruby
2
- # Copyright (C) 2006 HAS.
3
- # Released under MIT License.
1
+ #
2
+ # rb-appscript
3
+ #
4
+ # send -- Event class represents a packed AppleEvent that's ready to send via AESendMessage
5
+ #
6
+ # Copyright (C) 2006-2008 HAS. Released under MIT License.
7
+ #
4
8
 
5
9
  module Send
6
10
 
@@ -1,6 +1,10 @@
1
- #!/usr/local/bin/ruby
2
- # Copyright (C) 2006 HAS.
3
- # Released under MIT License.
1
+ #
2
+ # rb-appscript
3
+ #
4
+ # typewrappers -- Ruby classes representing type, enumerator, property and keyword AEDescs
5
+ #
6
+ # Copyright (C) 2006-2008 HAS. Released under MIT License.
7
+ #
4
8
 
5
9
  module TypeWrappers
6
10
 
@@ -1,6 +1,10 @@
1
- #!/usr/local/bin/ruby
2
- # Copyright (C) 2006 HAS.
3
- # Released under MIT License.
1
+ #
2
+ # rb-appscript
3
+ #
4
+ # defaultterminology -- lookup tables for default type, enumerator and command definitions
5
+ #
6
+ # Copyright (C) 2006-2008 HAS. Released under MIT License.
7
+ #
4
8
 
5
9
  module DefaultTerminology
6
10
  # Defines built-in terminology available for any application. When constructing the terminology tables for a particular application, the Terminology module will duplicate these tables and then add application-specific terms to create the finished lookup tables.
@@ -1,6 +1,10 @@
1
- #!/usr/local/bin/ruby
2
- # Copyright (C) 2006 HAS.
3
- # Released under MIT License.
1
+ #
2
+ # rb-appscript
3
+ #
4
+ # referencerenderer -- obtain an appscript-style string representation of an aem reference
5
+ #
6
+ # Copyright (C) 2006-2008 HAS. Released under MIT License.
7
+ #
4
8
 
5
9
  require "_aem/aemreference"
6
10
 
@@ -1,6 +1,11 @@
1
- #!/usr/local/bin/ruby
2
- # Copyright (C) 2006 HAS.
3
- # Released under MIT License.
1
+ #
2
+ # rb-appscript
3
+ #
4
+ # reservedkeywords -- names of methods already used by Ruby's Object class
5
+ # and appscript's Reference class
6
+ #
7
+ # Copyright (C) 2006-2008 HAS. Released under MIT License.
8
+ #
4
9
 
5
10
  # This list is mirrored in ch.6 of the appscript manual and in py-appscript's osaterminology.makeidentifier module
6
11
 
@@ -1,4 +1,14 @@
1
- #!/usr/local/bin/ruby
1
+ #
2
+ # rb-appscript
3
+ #
4
+ # safeobject -- ensure Appscript::Reference#method_missing works reliably
5
+ #
6
+ # New code Copyright (C) 2006-2008 HAS
7
+ # Original code Copyright (C) 2005 Thomas Sawyer, Jim Weirich; see below for original copyright
8
+ #
9
+
10
+ # Notes:
11
+
2
12
  # A modified, updated version of basicobject (http://facets.rubyforge.org/), used to provide
3
13
  # Appscript::Reference and Appscript#GenericReference with stable superclasses.
4
14
 
@@ -143,7 +153,7 @@ class AS_SafeObject
143
153
  ]
144
154
 
145
155
  def self.hide(name)
146
- case name
156
+ case name.to_s # Ruby1.9 returns method names as symbols, not strings as in 1.8
147
157
  when *EXCLUDE
148
158
  else
149
159
  undef_method(name) rescue nil
@@ -1,6 +1,10 @@
1
- #!/usr/local/bin/ruby
2
- # Copyright (C) 2006 HAS.
3
- # Released under MIT License.
1
+ #
2
+ # rb-appscript
3
+ #
4
+ # terminology -- retrieve and convert an application's terminology into lookup tables
5
+ #
6
+ # Copyright (C) 2006-2008 HAS. Released under MIT License.
7
+ #
4
8
 
5
9
  ######################################################################
6
10
  # TERMINOLOGY PARSER
@@ -51,9 +55,21 @@ module TerminologyParser
51
55
  return @_str[@_ptr - 4, 4] # big-endian
52
56
  end
53
57
 
58
+ # Ruby 1.9 has changed the way that a character ordinal is obtained
59
+ maj, min, rev = RUBY_VERSION.split('.')
60
+ if (maj == '1' and min.to_i < 9) # is Ruby 1.8
61
+ def _length
62
+ return @_str[@_ptr]
63
+ end
64
+ else
65
+ def _length
66
+ return @_str[@_ptr].ord
67
+ end
68
+ end
69
+
54
70
  def _name
55
71
  # Read a MacRoman-encoded Pascal keyword string.
56
- count = @_str[@_ptr]
72
+ count = _length
57
73
  @_ptr += 1 + count
58
74
  s = @_str[@_ptr - count, count]
59
75
  if not @@_name_cache.has_key?(s)
@@ -89,17 +105,17 @@ module TerminologyParser
89
105
 
90
106
  def parse_command
91
107
  name = _name
92
- @_ptr += 1 + @_str[@_ptr] # description string
108
+ @_ptr += 1 + _length # description string
93
109
  @_ptr += @_ptr & 1 # align
94
110
  code = _word + _word # event class + event id
95
111
  # skip result
96
112
  @_ptr += 4 # datatype word
97
- @_ptr += 1 + @_str[@_ptr] # description string
113
+ @_ptr += 1 + _length # description string
98
114
  @_ptr += @_ptr & 1 # align
99
115
  @_ptr += 2 # flags integer
100
116
  # skip direct parameter
101
117
  @_ptr += 4 # datatype word
102
- @_ptr += 1 + @_str[@_ptr] # description string
118
+ @_ptr += 1 + _length # description string
103
119
  @_ptr += @_ptr & 1 # align
104
120
  @_ptr += 2 # flags integer
105
121
  #
@@ -117,7 +133,7 @@ module TerminologyParser
117
133
  @_ptr += @_ptr & 1 # align
118
134
  parameter_code = _word
119
135
  @_ptr += 4 # datatype word
120
- @_ptr += 1 + @_str[@_ptr] # description string
136
+ @_ptr += 1 + _length # description string
121
137
  @_ptr += @_ptr & 1 # align
122
138
  @_ptr += 2 # flags integer
123
139
  current_command_args.push([parameter_name, parameter_code])
@@ -128,7 +144,7 @@ module TerminologyParser
128
144
  name = _name
129
145
  @_ptr += @_ptr & 1 # align
130
146
  code = _word
131
- @_ptr += 1 + @_str[@_ptr] # description string
147
+ @_ptr += 1 + _length # description string
132
148
  @_ptr += @_ptr & 1 # align
133
149
  is_plural = false
134
150
  _integer.times do # properties
@@ -136,7 +152,7 @@ module TerminologyParser
136
152
  @_ptr += @_ptr & 1 # align
137
153
  propcode = _word
138
154
  @_ptr += 4 # datatype word
139
- @_ptr += 1 + @_str[@_ptr] # description string
155
+ @_ptr += 1 + _length # description string
140
156
  @_ptr += @_ptr & 1 # align
141
157
  flags = _integer
142
158
  if propcode != 'c@#^' # not a superclass definition (see kAEInheritedProperties)
@@ -170,10 +186,10 @@ module TerminologyParser
170
186
  end
171
187
 
172
188
  def parse_comparison # comparison info isn't used
173
- @_ptr += 1 + @_str[@_ptr] # name string
189
+ @_ptr += 1 + _length # name string
174
190
  @_ptr += @_ptr & 1 # align
175
191
  @_ptr += 4 # code word
176
- @_ptr += 1 + @_str[@_ptr] # description string
192
+ @_ptr += 1 + _length # description string
177
193
  @_ptr += @_ptr & 1 # align
178
194
  end
179
195
 
@@ -183,7 +199,7 @@ module TerminologyParser
183
199
  name = _name
184
200
  @_ptr += @_ptr & 1 # align
185
201
  code = _word
186
- @_ptr += 1 + @_str[@_ptr] # description string
202
+ @_ptr += 1 + _length # description string
187
203
  @_ptr += @_ptr & 1 # align
188
204
  if not @_found_enumerators.has_key?(name + code)
189
205
  @enumerators.push([name, code])
@@ -193,8 +209,8 @@ module TerminologyParser
193
209
  end
194
210
 
195
211
  def parse_suite
196
- @_ptr += 1 + @_str[@_ptr] # name string
197
- @_ptr += 1 + @_str[@_ptr] # description string
212
+ @_ptr += 1 + _length # name string
213
+ @_ptr += 1 + _length # description string
198
214
  @_ptr += @_ptr & 1 # align
199
215
  @_ptr += 4 # code word
200
216
  @_ptr += 4 # level, version integers
@@ -1,6 +1,11 @@
1
- #!/usr/local/bin/ruby
2
- # Copyright (C) 2006 HAS.
3
- # Released under MIT License.
1
+ #
2
+ # rb-appscript
3
+ #
4
+ # aem -- a mid-level object-oriented API for creating and sending Apple events
5
+ # using raw AE codes; may be used directly or via high-level appscript wrapper
6
+ #
7
+ # Copyright (C) 2006-2008 HAS. Released under MIT License.
8
+ #
4
9
 
5
10
  require "ae"
6
11
  require "kae"
@@ -1,6 +1,11 @@
1
- #!/usr/local/bin/ruby
2
- # Copyright (C) 2006 HAS.
3
- # Released under MIT License.
1
+ #
2
+ # rb-appscript
3
+ #
4
+ # appscript -- syntactically sugared wrapper around the mid-level aem API;
5
+ # provides a high-level, easy-to-use API for creating and sending Apple events
6
+ #
7
+ # Copyright (C) 2006-2008 HAS. Released under MIT License.
8
+ #
4
9
 
5
10
  require "_aem/mactypes"
6
11
 
@@ -187,15 +192,15 @@ module Appscript
187
192
  # if hash contains a 'class' property containing a class name, coerce the AEDesc to that class
188
193
  new_val = Hash[val]
189
194
  if new_val.has_key?(:class_)
190
- value = new_val.delete(:class_)
195
+ val2 = new_val.delete(:class_)
191
196
  else
192
- value = new_val.delete(ClassType)
197
+ val2 = new_val.delete(ClassType)
193
198
  end
194
- if value.is_a?(Symbol) # get the corresponding AEType (assuming there is one)
195
- value = @type_by_name.fetch(value, value)
199
+ if val2.is_a?(Symbol) # get the corresponding AEType (assuming there is one)
200
+ val2 = @type_by_name.fetch(val2, val2)
196
201
  end
197
- if value.is_a?(AEM::AEType) # coerce the record to the desired type
198
- record = record.coerce(value.code)
202
+ if val2.is_a?(AEM::AEType) # coerce the record to the desired type
203
+ record = record.coerce(val2.code)
199
204
  val = new_val
200
205
  end # else value wasn't a class name, so it'll be packed as a normal record property instead
201
206
  end
@@ -241,8 +246,8 @@ module Appscript
241
246
  key, value = desc.get_item(i + 1, KAE::TypeWildCard)
242
247
  if key == KAE::KeyASUserRecordFields
243
248
  lst = unpack_aelist(value)
244
- (lst.length / 2).times do |i|
245
- dct[lst[i * 2]] = lst[i * 2 + 1]
249
+ (lst.length / 2).times do |j|
250
+ dct[lst[j * 2]] = lst[j * 2 + 1]
246
251
  end
247
252
  else
248
253
  dct[@type_by_code.fetch(key) { AEM::AEType.new(key) }] = unpack(value)
@@ -259,7 +264,7 @@ module Appscript
259
264
  return Reference.new(self, @reference_codecs.unpack(desc))
260
265
  end
261
266
 
262
- def unpack_contains_comp_descriptor(op1, op2) # TO DO: is this needed?
267
+ def unpack_contains_comp_descriptor(op1, op2)
263
268
  if op1.is_a?(Appscript::Reference) and op1.AS_aem_reference.AEM_root == AEMReference::Its
264
269
  return op1.contains(op2)
265
270
  else
@@ -300,6 +305,7 @@ module Appscript
300
305
  protected :_call
301
306
 
302
307
  def initialize(call)
308
+ super()
303
309
  @_call = call
304
310
  end
305
311
 
@@ -363,22 +369,18 @@ module Appscript
363
369
  attr_writer :AS_aem_reference, :AS_app_data
364
370
 
365
371
  def initialize(app_data, aem_reference)
372
+ super()
366
373
  @AS_app_data = app_data
367
374
  @AS_aem_reference = aem_reference
368
375
  end
369
376
 
370
- def _resolve_range_boundary(selector, value_if_none)
371
- if selector == nil
372
- selector = value_if_none
373
- end
377
+ def _resolve_range_boundary(selector)
374
378
  if selector.is_a?(Appscript::GenericReference)
375
379
  return selector.AS_resolve(@AS_app_data).AS_aem_reference
376
380
  elsif selector.is_a?(Reference)
377
381
  return selector.AS_aem_reference
378
- elsif selector.is_a?(String)
379
- return AEM.con.elements(@AS_aem_reference.AEM_want).by_name(selector)
380
382
  else
381
- return AEM.con.elements(@AS_aem_reference.AEM_want).by_index(selector)
383
+ return selector
382
384
  end
383
385
  end
384
386
 
@@ -505,28 +507,41 @@ module Appscript
505
507
  begin
506
508
  return @AS_app_data.target.event(code, params, atts,
507
509
  KAE::KAutoGenerateReturnID, @AS_app_data).send(timeout, send_flags)
508
- rescue => e
509
- if e.is_a?(AEM::CommandError)
510
- if [-600, -609].include?(e.number) and @AS_app_data.constructor == :by_path
511
- if not AEM::Application.process_exists_for_path?(@AS_app_data.identifier)
512
- if code == 'ascrnoop'
513
- AEM::Application.launch(@AS_app_data.identifier)
514
- elsif code != 'aevtoapp'
515
- raise CommandError.new(self, name, args, e)
516
- end
517
- end
518
- @AS_app_data.target.reconnect
519
- begin
520
- return @AS_app_data.target.event(code, params, atts,
521
- KAE::KAutoGenerateReturnID, @AS_app_data).send(timeout, send_flags)
522
- rescue
510
+ rescue AEM::CommandError => e
511
+ if e.number == -1708 and code == 'ascrnoop'
512
+ return # 'launch' events always return 'not handled' errors; just ignore these
513
+ elsif [-600, -609].include?(e.number) and @AS_app_data.constructor == :by_path
514
+ #
515
+ # Event was sent to a local app for which we no longer have a valid address
516
+ # (i.e. the application has quit since this AEM::Application object was made).
517
+ #
518
+ # - If application is running under a new process id, we just update the
519
+ # AEM::Application object and resend the event.
520
+ #
521
+ # - If application isn't running, then we see if the event being sent is one of
522
+ # those allowed to relaunch the application (i.e. 'run' or 'launch'). If it is, the
523
+ # application is relaunched, the process id updated and the event resent;
524
+ # if not, the error is rethrown.
525
+ #
526
+ if not AEM::Application.process_exists_for_path?(@AS_app_data.identifier)
527
+ if code == 'ascrnoop'
528
+ AEM::Application.launch(@AS_app_data.identifier)
529
+ elsif code != 'aevtoapp'
530
+ raise CommandError.new(self, name, args, e)
523
531
  end
524
- elsif e.number == -1708 and code == 'ascrnoop'
525
- return
532
+ end
533
+ # update AEMApplication object's AEAddressDesc
534
+ @AS_app_data.target.reconnect
535
+ # re-send command
536
+ begin
537
+ return @AS_app_data.target.event(code, params, atts,
538
+ KAE::KAutoGenerateReturnID, @AS_app_data).send(timeout, send_flags)
539
+ rescue AEM::CommandError => e
540
+ raise CommandError.new(self, name, args, e)
526
541
  end
527
542
  end
528
- raise CommandError.new(self, name, args, e)
529
543
  end
544
+ raise CommandError.new(self, name, args, e)
530
545
  end
531
546
 
532
547
 
@@ -627,7 +642,7 @@ module Appscript
627
642
  return _send_command(args, name, code[0], code[1])
628
643
  else
629
644
  # see if it's a method that has been added to Object class [presumably] at runtime, but excluded
630
- # by AE_SafeObject to avoid potential conflicts with property/element/command names
645
+ # by AS_SafeObject to avoid potential conflicts with property/element/command names
631
646
  begin
632
647
  # Notes:
633
648
  # rb-appscript has to prevent arbitrary methods that are added to Ruby's base Object class
@@ -665,19 +680,28 @@ module Appscript
665
680
  end
666
681
 
667
682
  def [](selector, end_range_selector=nil)
683
+ raise TypeError, "Bad selector: nil not allowed." if selector == nil
668
684
  if end_range_selector != nil
669
685
  new_ref = @AS_aem_reference.by_range(
670
- self._resolve_range_boundary(selector, 1),
671
- self._resolve_range_boundary(end_range_selector, -1))
686
+ self._resolve_range_boundary(selector),
687
+ self._resolve_range_boundary(end_range_selector))
672
688
  else
673
689
  case selector
674
690
  when String
675
691
  new_ref = @AS_aem_reference.by_name(selector)
676
- when Appscript::GenericReference
677
- new_ref = @AS_aem_reference.by_filter(
678
- selector.AS_resolve(@AS_app_data).AS_aem_reference)
679
- when Appscript::Reference, AEMReference::Test
680
- new_ref = @AS_aem_reference.by_filter(selector)
692
+ when Appscript::GenericReference, Appscript::Reference, AEMReference::Test
693
+ case selector
694
+ when Appscript::GenericReference
695
+ test_clause = selector.AS_resolve(@AS_app_data).AS_aem_reference
696
+ when Appscript::Reference
697
+ test_clause = selector.AS_aem_reference
698
+ else
699
+ test_clause = selector
700
+ end
701
+ if not test_clause.is_a?(AEMReference::Test)
702
+ raise TypeError, "Not an its-based test: #{selector}"
703
+ end
704
+ new_ref = @AS_aem_reference.by_filter(test_clause)
681
705
  else
682
706
  new_ref = @AS_aem_reference.by_index(selector)
683
707
  end
@@ -881,7 +905,11 @@ module Appscript
881
905
  AEM::Application.launch(@AS_app_data.identifier)
882
906
  @AS_app_data.target.reconnect
883
907
  else
884
- @AS_app_data.target.event('ascrnoop').send # will send launch event to app if already running; else will error
908
+ begin
909
+ @AS_app_data.target.event('ascrnoop').send # will send launch event to app if already running; else will error
910
+ rescue AEM::CommandError => e
911
+ raise if e.to_i != -1708
912
+ end
885
913
  end
886
914
  end
887
915
  end
@@ -1,13 +1,14 @@
1
- #!/usr/local/bin/ruby
1
+ #
2
+ # rb-appscript
3
+ #
4
+ # osax -- invoke scripting addition (OSAX) commands from Ruby
5
+ #
6
+ # Copyright (C) 2006-2008 HAS. Released under MIT License.
7
+ #
2
8
 
3
9
  require "appscript"
4
10
 
5
11
  module OSAX
6
-
7
- # Allows scripting additions (a.k.a. OSAXen) to be called from Ruby.
8
- #
9
- # Note: currently 32-bit only; attempting to create a new ScriptingAddition instance
10
- # in a 64-bit process will result in a NotImplementedError.
11
12
 
12
13
  ######################################################################
13
14
  # PRIVATE