rb-appscript 0.4.0 → 0.5.0

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 (48) hide show
  1. data/CHANGES +37 -0
  2. data/LICENSE +6 -2
  3. data/README +7 -4
  4. data/TODO +6 -2
  5. data/doc/aem-manual/01_introduction.html +1 -1
  6. data/doc/aem-manual/02_apioverview.html +1 -1
  7. data/doc/aem-manual/03_packingandunpackingdata.html +3 -3
  8. data/doc/aem-manual/04_references.html +18 -13
  9. data/doc/aem-manual/05_targettingapplications.html +33 -13
  10. data/doc/aem-manual/06_buildingandsendingevents.html +1 -1
  11. data/doc/aem-manual/07_findapp.html +1 -1
  12. data/doc/aem-manual/08_examples.html +1 -1
  13. data/doc/aem-manual/index.html +1 -1
  14. data/doc/appscript-manual/01_introduction.html +1 -1
  15. data/doc/appscript-manual/02_aboutappscripting.html +4 -4
  16. data/doc/appscript-manual/03_quicktutorial.html +1 -1
  17. data/doc/appscript-manual/04_gettinghelp.html +13 -42
  18. data/doc/appscript-manual/05_keywordconversion.html +1 -1
  19. data/doc/appscript-manual/06_classesandenums.html +1 -1
  20. data/doc/appscript-manual/07_applicationobjects.html +19 -1
  21. data/doc/appscript-manual/08_realvsgenericreferences.html +1 -1
  22. data/doc/appscript-manual/09_referenceforms.html +1 -1
  23. data/doc/appscript-manual/10_referenceexamples.html +1 -1
  24. data/doc/appscript-manual/11_applicationcommands.html +1 -1
  25. data/doc/appscript-manual/12_commandexamples.html +1 -1
  26. data/doc/appscript-manual/13_performanceissues.html +1 -1
  27. data/doc/appscript-manual/14_notes.html +1 -1
  28. data/doc/appscript-manual/index.html +1 -1
  29. data/doc/index.html +1 -1
  30. data/doc/mactypes-manual/index.html +13 -1
  31. data/doc/osax-manual/index.html +37 -6
  32. data/extconf.rb +2 -2
  33. data/rb-appscript.gemspec +1 -1
  34. data/sample/AB_export_vcard.rb +31 -0
  35. data/sample/Add_iCal_event.rb +4 -4
  36. data/src/lib/_aem/connect.rb +88 -8
  37. data/src/lib/_aem/mactypes.rb +27 -21
  38. data/src/lib/_appscript/reservedkeywords.rb +1 -0
  39. data/src/lib/aem.rb +40 -5
  40. data/src/lib/appscript.rb +104 -30
  41. data/src/lib/kae.rb +1 -0
  42. data/src/lib/osax.rb +35 -19
  43. data/src/rbae.c +115 -1
  44. data/test/README +3 -1
  45. data/test/test_appscriptcommands.rb +5 -4
  46. data/test/test_codecs.rb +7 -1
  47. data/test/testall.sh +1 -1
  48. metadata +24 -23
@@ -11,21 +11,6 @@ module MacTypes
11
11
  require "kae"
12
12
 
13
13
  class FileBase
14
-
15
- URLPrefix = 'file://localhost'
16
- URLPatt = Regexp.new('file://.*?(/.*)', Regexp::IGNORECASE)
17
-
18
- def FileBase._path_to_url(path)
19
- return URLPrefix + path.gsub(/[^a-zA-Z0-9_.-\/]/) { |c| "%%%02x" % c[0] }
20
- end
21
-
22
- def FileBase._url_to_path(url)
23
- match = url.match(URLPatt)
24
- if not match
25
- raise ArgumentError, "Not a file:// URL."
26
- end
27
- return match[1].gsub(/%../) { |s| "%c" % s[1,2].hex }
28
- end
29
14
 
30
15
  def FileBase._coerce(desc, type, path=nil)
31
16
  begin
@@ -72,13 +57,20 @@ module MacTypes
72
57
  def Alias.path(path)
73
58
  # Make Alias object from POSIX path.
74
59
  return new(FileBase._coerce(
75
- AE::AEDesc.new(KAE::TypeFileURL, FileBase._path_to_url(path)),
60
+ AE::AEDesc.new(KAE::TypeFileURL, AE.convert_posix_path_to_url(path)),
61
+ KAE::TypeAlias, path))
62
+ end
63
+
64
+ def Alias.hfs_path(path)
65
+ # Make Alias object from HFS path.
66
+ return new(FileBase._coerce(
67
+ AE::AEDesc.new(KAE::TypeFileURL, AE.convert_hfs_path_to_url(path)),
76
68
  KAE::TypeAlias, path))
77
69
  end
78
70
 
79
71
  def Alias.url(url)
80
72
  # Make Alias object from file URL. Note: only the path portion of the URL is used; the domain will always be localhost.
81
- return Alias.path(_url_to_path(url))
73
+ return Alias.path(AE.convert_url_to_posix_path(url))
82
74
  end
83
75
 
84
76
  def Alias.desc(desc)
@@ -97,7 +89,12 @@ module MacTypes
97
89
 
98
90
  def path
99
91
  # Get as POSIX path.
100
- return FileBase._url_to_path(FileBase._coerce(@desc, KAE::TypeFileURL).data)
92
+ return AE.convert_url_to_posix_path(FileBase._coerce(@desc, KAE::TypeFileURL).data)
93
+ end
94
+
95
+ def hfs_path
96
+ # Get as HFS path.
97
+ return AE.convert_url_to_hfs_path(FileBase._coerce(@desc, KAE::TypeFileURL).data)
101
98
  end
102
99
 
103
100
  alias_method :to_s, :path
@@ -136,9 +133,14 @@ module MacTypes
136
133
  return new(path, nil)
137
134
  end
138
135
 
136
+ def FileURL.hfs_path(path)
137
+ # Make FileURL object from HFS path.
138
+ return new(AE.convert_url_to_posix_path(AE.convert_hfs_path_to_url(path)), nil)
139
+ end
140
+
139
141
  def FileURL.url(url)
140
142
  # Make FileURL object from file URL. Note: only the path portion of the URL is used; the domain will always be localhost.
141
- return FileURL.path(_url_to_path(url))
143
+ return FileURL.path(AE.convert_url_to_posix_path(url))
142
144
  end
143
145
 
144
146
  def FileURL.desc(desc)
@@ -151,7 +153,7 @@ module MacTypes
151
153
  def desc
152
154
  # Get as AEDesc. If constructed from Ruby, descriptor's type is always typeFileURL; if returned by aem, its type mat be typeFSS, typeFSRef or typeFileURL.
153
155
  if not @desc
154
- @desc = AE::AEDesc.new(KAE::TypeFileURL, FileBase._path_to_url(@path))
156
+ @desc = AE::AEDesc.new(KAE::TypeFileURL, AE.convert_posix_path_to_url(@path))
155
157
  end
156
158
  return @desc
157
159
  end
@@ -164,11 +166,15 @@ module MacTypes
164
166
  def path
165
167
  # Get as POSIX path.
166
168
  if not @path
167
- @path = FileBase._url_to_path(FileBase._coerce(@desc, KAE::TypeFileURL).data)
169
+ @path = AE.convert_url_to_posix_path(FileBase._coerce(@desc, KAE::TypeFileURL).data)
168
170
  end
169
171
  return @path
170
172
  end
171
173
 
174
+ def hfs_path
175
+ return AE.convert_url_to_hfs_path(AE.convert_posix_path_to_url(path))
176
+ end
177
+
172
178
  alias_method :to_s, :path
173
179
 
174
180
  def inspect
@@ -74,6 +74,7 @@ ReservedKeywords = [
74
74
  "is_a?",
75
75
  "is_in",
76
76
  "is_not_in",
77
+ "is_running?",
77
78
  "its",
78
79
  "keywords",
79
80
  "kind_of?",
@@ -23,6 +23,8 @@ module AEM
23
23
  Codecs = Codecs
24
24
  DefaultCodecs = DefaultCodecs
25
25
  MacOSError = AE::MacOSError
26
+ CantLaunchApplicationError = Connect::CantLaunchApplicationError
27
+
26
28
 
27
29
  AEDesc = AE::AEDesc
28
30
 
@@ -56,7 +58,7 @@ module AEM
56
58
  #######
57
59
  # Application class
58
60
 
59
- class Application
61
+ class Application < AEMReference::Base
60
62
  # Identifies an application and provides an #event method for constructing Apple events targetted at it.
61
63
 
62
64
  require "weakref"
@@ -102,12 +104,37 @@ module AEM
102
104
 
103
105
  def Application.launch(path)
104
106
  # Launches a local application without sending it the usual 'run' event (aevtoapp).
105
- Connect.launch_app(path)
107
+ Connect.launch_app_with_launch_event(path)
108
+ end
109
+
110
+ def Application.is_running?(path) # TO DO: delete
111
+ $stderr.puts('Warning! AEM::Application.is_running? is deprecated; use process_exists_for_path? instead.')
112
+ return Connect.process_exists_for_path?(path)
113
+ end
114
+
115
+ def Application.process_exists_for_path?(path)
116
+ # Does a local process launched from the specified application file exist?
117
+ # Note: if path is invalid, an AE::MacOSError is raised.
118
+ return Connect.process_exists_for_path?(path)
119
+ end
120
+
121
+ def Application.process_exists_for_pid?(pid)
122
+ # Is there a local application process with the given unix process id?
123
+ return Connect.process_exists_for_pid?(pid)
106
124
  end
107
125
 
108
- def Application.is_running?(path)
109
- # Checks if a local application is running.
110
- return Connect.is_running?(path)
126
+ def Application.process_exists_for_url?(url)
127
+ # Does an application process specified by the given eppc:// URL exist?
128
+ # Returns false if process doesn't exist or if access to it isn't allowed.
129
+ # (Implementation note: this method sends an Apple event to the specified process and checks for errors.)
130
+ return Connect.process_exists_for_url?(url)
131
+ end
132
+
133
+ def Application.process_exists_for_desc?(desc)
134
+ # Does an application process specified by the given AEAddressDesc exist?
135
+ # Returns false if process doesn't exist or if access to it isn't allowed.
136
+ # (Implementation note: this method sends an Apple event to the specified process and checks for errors.)
137
+ return Connect.process_exists_for_desc?(desc)
111
138
  end
112
139
 
113
140
  #######
@@ -161,6 +188,14 @@ module AEM
161
188
 
162
189
  # (hash method is provided by attr_reader :hash)
163
190
 
191
+ def AEM_comparable
192
+ return ['AEMApplication', @identity]
193
+ end
194
+
195
+ def AEM_pack_self(codecs)
196
+ return @address_desc
197
+ end
198
+
164
199
  def reconnect
165
200
  # If application has quit since this Application object was created, its AEAddressDesc
166
201
  # is no longer valid so this Application object will not work even when application is restarted.
@@ -5,8 +5,11 @@
5
5
  require "_aem/mactypes"
6
6
 
7
7
  module Appscript
8
+
9
+ Version = '0.5.0'
10
+
8
11
  # The following methods and classes are of interest to end users:
9
- # app, con, its, CommandError, ApplicationNotFoundError
12
+ # app, con, its, CommandError, ApplicationNotFoundError, CantLaunchApplicationError
10
13
  # Other classes are only of interest to implementors who need to hook in their own code.
11
14
 
12
15
  require "kae"
@@ -26,7 +29,7 @@ module Appscript
26
29
 
27
30
  class AppData < AEM::Codecs
28
31
 
29
- HelpAgentID = 'net.sourceforge.appscript.appscripthelpagent'
32
+ ASDictionaryBundleID = 'net.sourceforge.appscript.asdictionary'
30
33
 
31
34
  attr_reader :constructor, :identifier, :reference_codecs
32
35
  attr_writer :reference_codecs
@@ -75,25 +78,35 @@ module Appscript
75
78
  :current => 'current',
76
79
  }
77
80
 
78
- def _make_help_agent
81
+ def _init_help_agent
79
82
  begin
80
- @_help_agent = AEM::Application.by_path(FindApp.by_id(HelpAgentID))
83
+ apppath = FindApp.by_id(ASDictionaryBundleID)
84
+ asdictionary_is_running = AEM::Application.process_exists_for_path?(apppath)
85
+ @_help_agent = AEM::Application.by_path(apppath)
86
+ if not asdictionary_is_running # hide ASDictionary after launching it # TO DO: something less kludgy
87
+ AEM::Application.by_path(FindApp.by_id('com.apple.systemevents')).event('coresetd', {
88
+ '----' => AEM.app.elements('prcs').by_name('ASDictionary').property('pvis'),
89
+ 'data' => false}).send
90
+ sleep(1) # KLUDGE: need a short delay here to workaround ASDictionary 0.9.0's event handling glitches # TO DO: delete after ASDictionary is fixed
91
+ end
81
92
  return true
82
- rescue FindApp::ApplicationNotFoundError
83
- puts "No help available: AppscriptHelpAgent.app not found."
84
- return false
93
+ rescue FindApp::ApplicationNotFoundError => e
94
+ $stderr.puts("No help available: ASDictionary application not found (#{e}).")
95
+ rescue AEM::CantLaunchApplicationError => e
96
+ $stderr.puts("No help available: can't launch ASDictionary application (#{e}).")
85
97
  end
98
+ return false
86
99
  end
87
100
 
88
101
  def _display_help(flags, ref)
89
102
  begin
90
- puts @_help_agent.event('ASHAHelp', {
103
+ $stderr.puts(@_help_agent.event('AppSHelp', {
91
104
  'Cons' => Constructors[@constructor],
92
- 'Iden' => @constructor == :by_aem_app ? @identifier.address_desc : @identifier,
105
+ 'Iden' => @identifier,
93
106
  'Styl' => 'rb-appscript',
94
107
  'Flag' => flags,
95
108
  'aRef' => pack(ref),
96
- }).send
109
+ }).send)
97
110
  return nil
98
111
  rescue AEM::CommandError => e
99
112
  return e
@@ -101,15 +114,25 @@ module Appscript
101
114
  end
102
115
 
103
116
  def help(flags, ref)
104
- if not @_help_agent
105
- return ref if not _make_help_agent
106
- end
107
- e = _display_help(flags, ref)
108
- if e and [-600, -609].include?(e.number) # not running
109
- return ref if not _make_help_agent
117
+ begin
118
+ if not @_help_agent
119
+ return ref if not _init_help_agent
120
+ end
110
121
  e = _display_help(flags, ref)
122
+ if e and [-600, -609].include?(e.number) # not running
123
+ return ref if not _init_help_agent
124
+ e = _display_help(flags, ref)
125
+ end
126
+ if e
127
+ if e.number == -1708 # event wasn't handled, presumably because available ASDictionary is too old
128
+ $stderr.puts("No help available: ASDictionary 0.9.0 or later required.")
129
+ else
130
+ $stderr.puts("No help available: ASDictionary raised an error: #{e}.")
131
+ end
132
+ end
133
+ rescue => err
134
+ $stderr.puts("No help available: unknown error: #{err}")
111
135
  end
112
- puts "No help available: AppscriptHelpAgent raised an error: #{e}." if e
113
136
  return ref
114
137
  end
115
138
 
@@ -298,9 +321,9 @@ module Appscript
298
321
  s= @_call[0]
299
322
  @_call[1, @_call.length].each do |name, args| if name == :[]
300
323
  if args.length == 1
301
- s += "[#{args[0]}]"
324
+ s += "[#{args[0].inspect}]"
302
325
  else
303
- s += "[#{args[0]}, #{args[1]}]"
326
+ s += "[#{args[0].inspect}, #{args[1].inspect}]"
304
327
  end
305
328
  else
306
329
  if args.length > 0
@@ -485,7 +508,7 @@ module Appscript
485
508
  rescue => e
486
509
  if e.is_a?(AEM::CommandError)
487
510
  if [-600, -609].include?(e.number) and @AS_app_data.constructor == :by_path
488
- if not AEM::Application.is_running?(@AS_app_data.identifier)
511
+ if not AEM::Application.process_exists_for_path?(@AS_app_data.identifier)
489
512
  if code == 'ascrnoop'
490
513
  AEM::Application.launch(@AS_app_data.identifier)
491
514
  elsif code != 'aevtoapp'
@@ -510,8 +533,8 @@ module Appscript
510
533
  #######
511
534
  # introspection
512
535
 
513
- def respond_to?(name)
514
- if super
536
+ def respond_to?(name, includePriv=false)
537
+ if Object.respond_to?(name)
515
538
  return true
516
539
  else
517
540
  return @AS_app_data.reference_by_name.has_key?(name.is_a?(String) ? name.intern : name)
@@ -519,7 +542,7 @@ module Appscript
519
542
  end
520
543
 
521
544
  def methods
522
- return super + @AS_app_data.reference_by_name.keys.collect { |name| name.to_s }
545
+ return (Object.instance_methods + @AS_app_data.reference_by_name.keys.collect { |name| name.to_s }).uniq
523
546
  end
524
547
 
525
548
  def commands
@@ -571,24 +594,73 @@ module Appscript
571
594
 
572
595
  alias_method :inspect, :to_s
573
596
 
597
+ #######
598
+ # Utility methods
599
+
600
+ def is_running?
601
+ identifier = @AS_app_data.identifier
602
+ case @AS_app_data.constructor
603
+ when :by_path
604
+ return AEM::Application.process_exists_for_path?(identifier)
605
+ when :by_pid
606
+ return AEM::Application.process_exists_for_pid?(identifier)
607
+ when :by_url
608
+ return AEM::Application.process_exists_for_url?(identifier)
609
+ when :by_aem_app
610
+ return AEM::Application.process_exists_for_desc?(identifier.address_desc)
611
+ else # when :current
612
+ return true
613
+ end
614
+ end
615
+
574
616
  #######
575
617
  # Public properties and methods; these are called by end-user and other clients (e.g. generic references)
576
618
 
577
619
  def method_missing(name, *args)
578
620
  selector_type, code = @AS_app_data.reference_by_name[name]
579
- case selector_type
621
+ case selector_type # check if name is a property/element/command name, and if it is handle accordingly
580
622
  when :property
581
623
  return Reference.new(@AS_app_data, @AS_aem_reference.property(code))
582
624
  when :element
583
625
  return Reference.new(@AS_app_data, @AS_aem_reference.elements(code))
584
626
  when :command
585
627
  return _send_command(args, name, code[0], code[1])
586
- else
587
- msg = "Unknown property, element or command: '#{name}'"
588
- if @AS_app_data.reference_by_name.has_key?("#{name}_".intern)
589
- msg += " (Did you mean '#{name}_'?)"
628
+ else
629
+ # 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
631
+ begin
632
+ # Notes:
633
+ # rb-appscript has to prevent arbitrary methods that are added to Ruby's base Object class
634
+ # by client code from automatically appearing in Appscript::Reference as well, as these new
635
+ # methods may inadvertently mask property/element/command names, causing appscript to
636
+ # behave incorrectly. However, once it is confirmed that a given method will not mask an existing
637
+ # property/element/command name, it can be added retrospectively to the Reference instance
638
+ # upon which it was called, which is what happens here.
639
+ #
640
+ # This means that methods such as #pretty_print and #pretty_inspect, which are
641
+ # injected into Object when the 'pp' module is loaded, will still be available in appscript
642
+ # references, even though they are not on AS_SafeObject's official list of permitted methods,
643
+ # *as long as* properties/elements/commands of the same name do not already exist for that
644
+ # reference.
645
+ #
646
+ # Where properties/elements/commands of the same name do already exist, appscript
647
+ # will still defer to those, of course, and this may cause problems for the caller if
648
+ # they were wanting the other behaviour. (But, that's the risk one runs with any sort
649
+ # of subclassing exercise when the contents of the superclass are not known for certain
650
+ # beforehand.) Clients that require access to these methods will need to add their names
651
+ # to the ReservedKeywords list (see _appscript/reservedkeywords.rb) at runtime, thereby
652
+ # forcing appscript to append underscores to the conflicting property/element/command
653
+ # names in order to disambiguate them, and modifying any code that refers to those
654
+ # properties/elements/commands accordingly.
655
+ meth = Object.instance_method(name)
656
+ rescue NameError # message not handled
657
+ msg = "Unknown property, element or command: '#{name}'"
658
+ if @AS_app_data.reference_by_name.has_key?("#{name}_".intern)
659
+ msg += " (Did you mean '#{name}_'?)"
660
+ end
661
+ raise RuntimeError, msg
590
662
  end
591
- raise RuntimeError, msg
663
+ return meth.bind(self).call(*args)
592
664
  end
593
665
  end
594
666
 
@@ -785,6 +857,8 @@ module Appscript
785
857
  return ref.AS_resolve(@AS_app_data)
786
858
  elsif ref.is_a?(AEMReference::Base)
787
859
  return Reference.new(@AS_app_data, ref)
860
+ elsif ref == nil
861
+ return Reference.new(@AS_app_data, AEM.app)
788
862
  else
789
863
  return Reference.new(@AS_app_data, AEM.custom_root(ref))
790
864
  end
@@ -924,6 +998,6 @@ module Appscript
924
998
  end
925
999
  end
926
1000
 
927
-
928
1001
  ApplicationNotFoundError = FindApp::ApplicationNotFoundError
1002
+ CantLaunchApplicationError = Connect::CantLaunchApplicationError
929
1003
  end
@@ -1485,4 +1485,5 @@ module KAE
1485
1485
  # new in 10.5
1486
1486
  TypeUInt16 = 'ushr'
1487
1487
  TypeUInt64 = 'ucom'
1488
+ TypeCFAbsoluteTime = 'cfat'
1488
1489
  end
@@ -23,18 +23,22 @@ module OSAX
23
23
  OSAXCache = {}
24
24
  OSAXNames = []
25
25
 
26
- se = Appscript.app.by_id('com.apple.systemevents')
27
- [se.system_domain, se.local_domain, se.user_domain].each do |domain|
28
- osaxen = domain.scripting_additions_folder.files[
29
- Appscript.its.file_type.eq('osax').or(Appscript.its.name_extension.eq('osax'))]
30
- osaxen.name.get.zip(osaxen.POSIX_path.get).each do |name, path|
31
- name = name.sub(/(?i)\.osax$/, '') # remove name extension, if any
32
- OSAXNames.push(name)
33
- OSAXCache[name.downcase] = [path, nil]
26
+ se = AEM::Application.by_path(FindApp.by_id('com.apple.systemevents'))
27
+ ['flds', 'fldl', 'fldu'].each do |domain_code|
28
+ osaxen = AEM.app.property(domain_code).property('$scr').elements('file').by_filter(
29
+ AEM.its.property('asty').eq('osax').or(AEM.its.property('extn').eq('osax')))
30
+ if se.event('coredoex', {'----' => osaxen.property('pnam')}).send # domain has ScriptingAdditions folder
31
+ names = se.event('coregetd', {'----' => osaxen.property('pnam')}).send
32
+ paths = se.event('coregetd', {'----' => osaxen.property('posx')}).send
33
+ names.zip(paths).each do |name, path|
34
+ name = name.sub(/(?i)\.osax$/, '') # remove name extension, if any
35
+ OSAXNames.push(name)
36
+ OSAXCache[name.downcase] = [path, nil]
37
+ end
34
38
  end
35
39
  end
36
40
  OSAXNames.sort!.uniq!
37
-
41
+
38
42
  #######
39
43
  # modified AppData class
40
44
 
@@ -122,28 +126,40 @@ module OSAX
122
126
  class ScriptingAddition < Appscript::Reference
123
127
  # Represents a single scripting addition.
124
128
 
125
- def initialize(name, osax_data=nil)
129
+ def initialize(name, terms=nil)
126
130
  # name: string -- a scripting addition's name, e.g. "StandardAdditions";
127
131
  # basically its filename minus the '.osax' suffix
128
132
  #
133
+ # terms : module or nil -- an optional terminology glue module,
134
+ # as exported by Terminology.dump; if given, ScriptingAddition
135
+ # will use this instead of retrieving the terminology dynamically
136
+ #
129
137
  # Note that name is case-insensitive and an '.osax' suffix is ignored if given.
130
138
  @_osax_name = name
131
- if not osax_data
139
+ if not terms
132
140
  osax_name = name.downcase.sub(/(?i)\.osax$/, '')
133
- path, terms = OSAXCache[osax_name]
141
+ path, terminology_tables = OSAXCache[osax_name]
134
142
  if not path
135
143
  raise ArgumentError, "Scripting addition not found: #{name.inspect}"
136
144
  end
137
- if not terms
138
- aetes_desc = AE.get_app_terminology(path) # will raise NotImplementedError in 64-bit processes
145
+ if not terminology_tables
146
+ begin
147
+ aetes_desc = AE.get_app_terminology(path) # will raise NotImplementedError in 64-bit processes
148
+ rescue NotImplementedError
149
+ raise RuntimeError, "OSAX::ScriptingAddition can't dynamically retrieve scripting addition terminology within a 64-bit process."
150
+ end
139
151
  aetes = DefaultCodecs.unpack(aetes_desc.coerce(KAE::TypeAEList))
140
- terms = Terminology.tables_for_aetes(aetes)
141
- OSAXCache[osax_name][1] = terms
152
+ terminology_tables = Terminology.tables_for_aetes(aetes)
153
+ OSAXCache[osax_name][1] = terminology_tables
142
154
  end
143
- @_terms = terms
144
- osax_data = OSAXData.new(:current, nil, @_terms)
155
+ @_terms = terminology_tables
156
+ terms = OSAXData.new(:current, nil, @_terms)
157
+ elsif not terms.is_a?(OSAX::OSAXData) # assume it's a glue module
158
+ terminology_tables = Terminology.tables_for_module(terms)
159
+ @_terms = terminology_tables
160
+ terms = OSAXData.new(:current, nil, @_terms)
145
161
  end
146
- super(osax_data, AEM.app)
162
+ super(terms, AEM.app)
147
163
  end
148
164
 
149
165
  def to_s