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