rb-appscript 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
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