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.
- data/CHANGES +37 -0
- data/LICENSE +6 -2
- data/README +7 -4
- data/TODO +6 -2
- data/doc/aem-manual/01_introduction.html +1 -1
- data/doc/aem-manual/02_apioverview.html +1 -1
- data/doc/aem-manual/03_packingandunpackingdata.html +3 -3
- data/doc/aem-manual/04_references.html +18 -13
- data/doc/aem-manual/05_targettingapplications.html +33 -13
- data/doc/aem-manual/06_buildingandsendingevents.html +1 -1
- data/doc/aem-manual/07_findapp.html +1 -1
- data/doc/aem-manual/08_examples.html +1 -1
- data/doc/aem-manual/index.html +1 -1
- data/doc/appscript-manual/01_introduction.html +1 -1
- data/doc/appscript-manual/02_aboutappscripting.html +4 -4
- data/doc/appscript-manual/03_quicktutorial.html +1 -1
- data/doc/appscript-manual/04_gettinghelp.html +13 -42
- data/doc/appscript-manual/05_keywordconversion.html +1 -1
- data/doc/appscript-manual/06_classesandenums.html +1 -1
- data/doc/appscript-manual/07_applicationobjects.html +19 -1
- data/doc/appscript-manual/08_realvsgenericreferences.html +1 -1
- data/doc/appscript-manual/09_referenceforms.html +1 -1
- data/doc/appscript-manual/10_referenceexamples.html +1 -1
- data/doc/appscript-manual/11_applicationcommands.html +1 -1
- data/doc/appscript-manual/12_commandexamples.html +1 -1
- data/doc/appscript-manual/13_performanceissues.html +1 -1
- data/doc/appscript-manual/14_notes.html +1 -1
- data/doc/appscript-manual/index.html +1 -1
- data/doc/index.html +1 -1
- data/doc/mactypes-manual/index.html +13 -1
- data/doc/osax-manual/index.html +37 -6
- data/extconf.rb +2 -2
- data/rb-appscript.gemspec +1 -1
- data/sample/AB_export_vcard.rb +31 -0
- data/sample/Add_iCal_event.rb +4 -4
- data/src/lib/_aem/connect.rb +88 -8
- data/src/lib/_aem/mactypes.rb +27 -21
- data/src/lib/_appscript/reservedkeywords.rb +1 -0
- data/src/lib/aem.rb +40 -5
- data/src/lib/appscript.rb +104 -30
- data/src/lib/kae.rb +1 -0
- data/src/lib/osax.rb +35 -19
- data/src/rbae.c +115 -1
- data/test/README +3 -1
- data/test/test_appscriptcommands.rb +5 -4
- data/test/test_codecs.rb +7 -1
- data/test/testall.sh +1 -1
- metadata +24 -23
data/src/lib/_aem/mactypes.rb
CHANGED
@@ -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,
|
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(
|
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
|
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(
|
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,
|
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 =
|
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
|
data/src/lib/aem.rb
CHANGED
@@ -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.
|
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.
|
109
|
-
#
|
110
|
-
|
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.
|
data/src/lib/appscript.rb
CHANGED
@@ -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
|
-
|
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
|
81
|
+
def _init_help_agent
|
79
82
|
begin
|
80
|
-
|
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
|
84
|
-
|
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
|
103
|
+
$stderr.puts(@_help_agent.event('AppSHelp', {
|
91
104
|
'Cons' => Constructors[@constructor],
|
92
|
-
'Iden' => @
|
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
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
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.
|
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
|
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
|
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
|
-
|
588
|
-
|
589
|
-
|
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
|
-
|
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
|
data/src/lib/kae.rb
CHANGED
data/src/lib/osax.rb
CHANGED
@@ -23,18 +23,22 @@ module OSAX
|
|
23
23
|
OSAXCache = {}
|
24
24
|
OSAXNames = []
|
25
25
|
|
26
|
-
se =
|
27
|
-
[
|
28
|
-
osaxen =
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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,
|
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
|
139
|
+
if not terms
|
132
140
|
osax_name = name.downcase.sub(/(?i)\.osax$/, '')
|
133
|
-
path,
|
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
|
138
|
-
|
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
|
-
|
141
|
-
OSAXCache[osax_name][1] =
|
152
|
+
terminology_tables = Terminology.tables_for_aetes(aetes)
|
153
|
+
OSAXCache[osax_name][1] = terminology_tables
|
142
154
|
end
|
143
|
-
@_terms =
|
144
|
-
|
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(
|
162
|
+
super(terms, AEM.app)
|
147
163
|
end
|
148
164
|
|
149
165
|
def to_s
|