rb-appscript 0.5.3 → 0.6.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 (79) hide show
  1. data/CHANGES +28 -0
  2. data/README +51 -31
  3. data/doc/aem-manual/01_introduction.html +0 -2
  4. data/doc/aem-manual/02_apioverview.html +13 -9
  5. data/doc/aem-manual/03_packingandunpackingdata.html +41 -9
  6. data/doc/aem-manual/04_references.html +42 -40
  7. data/doc/aem-manual/{05_targettingapplications.html → 05_targetingapplications.html} +4 -6
  8. data/doc/aem-manual/06_buildingandsendingevents.html +40 -12
  9. data/doc/aem-manual/07_findapp.html +0 -2
  10. data/doc/aem-manual/08_examples.html +0 -2
  11. data/doc/aem-manual/aemreferenceinheritance.gif +0 -0
  12. data/doc/aem-manual/index.html +1 -3
  13. data/doc/appscript-manual/01_introduction.html +0 -2
  14. data/doc/appscript-manual/02_aboutappscripting.html +4 -6
  15. data/doc/appscript-manual/03_quicktutorial.html +1 -3
  16. data/doc/appscript-manual/04_gettinghelp.html +20 -7
  17. data/doc/appscript-manual/05_keywordconversion.html +5 -3
  18. data/doc/appscript-manual/06_classesandenums.html +32 -8
  19. data/doc/appscript-manual/07_applicationobjects.html +30 -41
  20. data/doc/appscript-manual/08_realvsgenericreferences.html +0 -2
  21. data/doc/appscript-manual/09_referenceforms.html +0 -2
  22. data/doc/appscript-manual/10_referenceexamples.html +1 -3
  23. data/doc/appscript-manual/11_applicationcommands.html +29 -2
  24. data/doc/appscript-manual/12_commandexamples.html +0 -2
  25. data/doc/appscript-manual/13_performanceissues.html +0 -2
  26. data/doc/appscript-manual/14_notes.html +0 -19
  27. data/doc/appscript-manual/index.html +0 -2
  28. data/doc/index.html +1 -4
  29. data/doc/mactypes-manual/01_introduction.html +0 -2
  30. data/doc/mactypes-manual/02_aliasclass.html +0 -10
  31. data/doc/mactypes-manual/03_fileurlclass.html +1 -11
  32. data/doc/mactypes-manual/04_unitsclass.html +0 -2
  33. data/doc/mactypes-manual/index.html +0 -2
  34. data/doc/osax-manual/01_introduction.html +0 -2
  35. data/doc/osax-manual/02_interface.html +0 -2
  36. data/doc/osax-manual/03_examples.html +0 -2
  37. data/doc/osax-manual/04_notes.html +6 -25
  38. data/doc/osax-manual/index.html +0 -2
  39. data/rb-appscript.gemspec +2 -3
  40. data/sample/AB_export_vcard.rb +0 -0
  41. data/sample/AB_list_people_with_emails.rb +0 -0
  42. data/sample/Create_daily_iCal_todos.rb +0 -0
  43. data/sample/Export_Address_Book_phone_numbers.rb +0 -0
  44. data/sample/Hello_world.rb +0 -0
  45. data/sample/List_iTunes_playlist_names.rb +0 -0
  46. data/sample/Open_file_in_TextEdit.rb +0 -0
  47. data/sample/Organize_Mail_messages.rb +0 -0
  48. data/sample/TextEdit_demo.rb +0 -0
  49. data/sample/iTunes_top40_to_html.rb +0 -0
  50. data/src/SendThreadSafe.c +0 -0
  51. data/src/SendThreadSafe.h +0 -0
  52. data/src/lib/_aem/aemreference.rb +5 -7
  53. data/src/lib/_aem/codecs.rb +47 -24
  54. data/src/lib/_aem/connect.rb +29 -8
  55. data/src/lib/_aem/encodingsupport.rb +77 -0
  56. data/src/lib/_aem/findapp.rb +0 -2
  57. data/src/lib/_aem/mactypes.rb +0 -2
  58. data/src/lib/_aem/send.rb +6 -8
  59. data/src/lib/_aem/typewrappers.rb +0 -2
  60. data/src/lib/_appscript/defaultterminology.rb +0 -2
  61. data/src/lib/_appscript/referencerenderer.rb +1 -3
  62. data/src/lib/_appscript/reservedkeywords.rb +0 -2
  63. data/src/lib/_appscript/safeobject.rb +58 -9
  64. data/src/lib/_appscript/terminology.rb +63 -46
  65. data/src/lib/aem.rb +3 -4
  66. data/src/lib/appscript.rb +12 -13
  67. data/src/lib/osax.rb +436 -9
  68. data/src/rbae.c +126 -103
  69. data/test/test_aemreference.rb +0 -0
  70. data/test/test_appscriptcommands.rb +15 -1
  71. data/test/test_appscriptreference.rb +0 -0
  72. data/test/test_codecs.rb +10 -4
  73. data/test/test_findapp.rb +0 -0
  74. data/test/test_mactypes.rb +0 -0
  75. data/test/test_osax.rb +0 -0
  76. data/test/testall.sh +0 -0
  77. metadata +24 -24
  78. data/LICENSE +0 -70
  79. data/TODO +0 -19
@@ -3,8 +3,6 @@
3
3
  #
4
4
  # connect -- launch applications and create AEAddressDescs
5
5
  #
6
- # Copyright (C) 2006-2009 HAS. Released under MIT License.
7
- #
8
6
 
9
7
  module Connect
10
8
  # Creates Apple event descriptor records of typeProcessSerialNumber, typeKernelProcessID and typeApplicationURL, used to specify the target application in Send::Event constructor.
@@ -13,10 +11,28 @@ module Connect
13
11
  require "kae"
14
12
  require "_aem/codecs"
15
13
  require "_aem/send"
16
-
17
- LaunchContinue = 0x4000
18
- LaunchNoFileFlags = 0x0800
19
- LaunchDontSwitch = 0x0200
14
+ require "_aem/encodingsupport"
15
+
16
+ @@encoding_support = AEMEncodingSupport.encoding_support
17
+
18
+ LSLaunchDefaults = 0x00000001
19
+ LSLaunchAndPrint = 0x00000002
20
+ LSLaunchReserved2 = 0x00000004
21
+ LSLaunchReserved3 = 0x00000008
22
+ LSLaunchReserved4 = 0x00000010
23
+ LSLaunchReserved5 = 0x00000020
24
+ LSLaunchAndDisplayErrors = 0x00000040
25
+ LSLaunchInhibitBGOnly = 0x00000080
26
+ LSLaunchDontAddToRecents = 0x00000100
27
+ LSLaunchDontSwitch = 0x00000200
28
+ LSLaunchNoParams = 0x00000800
29
+ LSLaunchAsync = 0x00010000
30
+ LSLaunchStartClassic = 0x00020000
31
+ LSLaunchInClassic = 0x00040000
32
+ LSLaunchNewInstance = 0x00080000
33
+ LSLaunchAndHide = 0x00100000
34
+ LSLaunchAndHideOthers = 0x00200000
35
+ LSLaunchHasUntrustedContents = 0x00400000
20
36
 
21
37
  KNoProcess = 0
22
38
  KCurrentProcess = 2
@@ -65,9 +81,10 @@ module Connect
65
81
  ##
66
82
 
67
83
  def Connect.launch_application(path, event)
84
+ path = @@encoding_support.to_utf8_string(path)
68
85
  begin
69
86
  return AE.launch_application(path, event,
70
- LaunchContinue + LaunchNoFileFlags + LaunchDontSwitch)
87
+ LSLaunchNoParams | LSLaunchStartClassic | LSLaunchDontSwitch)
71
88
  rescue AE::MacOSError => err
72
89
  raise CantLaunchApplicationError, err.to_i
73
90
  end
@@ -75,6 +92,7 @@ module Connect
75
92
 
76
93
  def Connect.launch_app_with_launch_event(path)
77
94
  # Send a 'launch' event to an application. If application is not already running, it will be launched in background first.
95
+ path = @@encoding_support.to_utf8_string(path)
78
96
  begin
79
97
  # If app is already running, calling AE.launch_application will send a 'reopen' event, so need to check for this first:
80
98
  psn = AE.psn_for_application_path(path)
@@ -93,6 +111,7 @@ module Connect
93
111
  ##
94
112
 
95
113
  def Connect.process_exists_for_path?(path)
114
+ path = @@encoding_support.to_utf8_string(path)
96
115
  # Does a local process launched from the specified application file exist?
97
116
  # Note: if path is invalid, an AE::MacOSError is raised.
98
117
  begin
@@ -138,7 +157,7 @@ module Connect
138
157
  # AESendMessage may return a timeout error (this should be -1712, but
139
158
  # -609 is often returned instead for some reason).
140
159
  Send::Event.new(desc, 'ascrnoop').send
141
- rescue Send::CommandError => err
160
+ rescue Send::EventError => err
142
161
  return (not [-600, -905].include?(err.to_i)) # not running/no network access
143
162
  end
144
163
  return true
@@ -154,6 +173,7 @@ module Connect
154
173
  # Result : AEAddressDesc
155
174
  #
156
175
  # Always creates AEAddressDesc by process serial number; that way there's no confusion if multiple versions of the same app are running.
176
+ path = @@encoding_support.to_utf8_string(path)
157
177
  begin
158
178
  psn = AE.psn_for_application_path(path)
159
179
  rescue AE::MacOSError => err
@@ -175,6 +195,7 @@ module Connect
175
195
  end
176
196
 
177
197
  def Connect.remote_app(url)
198
+ url = @@encoding_support.to_utf8_string(url)
178
199
  # Make an AEAddressDesc identifying a running application on another machine.
179
200
  # url : string -- URL for remote application, e.g. 'eppc://user:password@0.0.0.1/TextEdit'
180
201
  # Result : AEAddressDesc
@@ -0,0 +1,77 @@
1
+ #
2
+ # rb-appscript
3
+ #
4
+ # encodingsupport -- support string encodings in Ruby 1.9+
5
+ #
6
+
7
+
8
+ module AEMEncodingSupport
9
+
10
+ module EnableStringEncodings
11
+ # AE extension methods consume and return Strings containing UTF-8 encoded data, ignoring
12
+ # any attached encoding information. This module provides wrappers for AE interactions that
13
+ # take care of any encoding issues in Ruby 1.9+.
14
+
15
+ def EnableStringEncodings.to_utf8_string(s)
16
+ # Call before passing a string to an AE method that expects it to contain UTF-8 encoded data.
17
+ return s if [Encoding::ASCII_8BIT, Encoding::UTF_8].include?(s.encoding)
18
+ return s.encode('UTF-8')
19
+ end
20
+
21
+ def EnableStringEncodings.pack_string(s, as_type)
22
+ begin
23
+ return AE::AEDesc.new(KAE::TypeUTF8Text, EnableStringEncodings.to_utf8_string(s)).coerce(as_type)
24
+ rescue AE::MacOSError => e
25
+ if e.to_i == -1700 # couldn't coerce to TypeUnicodeText
26
+ raise TypeError, "Not valid UTF8 data or couldn't coerce to type %{as_type}: #{s.inspect}"
27
+ else
28
+ raise
29
+ end
30
+ end
31
+ end
32
+
33
+ def EnableStringEncodings.unpack_string(desc)
34
+ # String instances returned by AE methods contain UTF-8 data and ASCII-8BIT encoding,
35
+ # so change the encoding to match the data
36
+ return desc.coerce(KAE::TypeUTF8Text).data.force_encoding('UTF-8')
37
+ end
38
+ end
39
+
40
+
41
+ module DisableStringEncodings
42
+ # Support for Ruby 1.8 Strings, which do not contain encoding information. User is responsible
43
+ # for ensuring String instances passed to AE APIs contain UTF-8 encoded data; String instances
44
+ # returned by unpack_string will always contain contain UTF-8 encoded data.
45
+
46
+ def DisableStringEncodings.to_utf8_string(s)
47
+ return s
48
+ end
49
+
50
+ def DisableStringEncodings.pack_string(s, as_type)
51
+ begin
52
+ # Note: while the BOM is optional in typeUnicodeText, it's not included by AS
53
+ # and some apps, e.g. iTunes 7, will handle it incorrectly, so it's omitted here.)
54
+ return AE::AEDesc.new(KAE::TypeUTF8Text, s).coerce(as_type)
55
+ rescue AE::MacOSError => e
56
+ if e.to_i == -1700 # couldn't coerce to TypeUnicodeText
57
+ raise TypeError, "Not valid UTF8 data or couldn't coerce to type %{as_type}: #{s.inspect}"
58
+ else
59
+ raise
60
+ end
61
+ end
62
+ end
63
+
64
+ def DisableStringEncodings.unpack_string(desc)
65
+ return desc.coerce(KAE::TypeUTF8Text).data
66
+ end
67
+
68
+ end
69
+
70
+
71
+ def AEMEncodingSupport.encoding_support
72
+ # get the appropriate module for the Ruby version used
73
+ version, sub_version = RUBY_VERSION.split('.').collect {|n| n.to_i} [0, 2]
74
+ return (version >= 1 and sub_version >= 9) ? AEMEncodingSupport::EnableStringEncodings : AEMEncodingSupport::DisableStringEncodings
75
+ end
76
+
77
+ end
@@ -3,8 +3,6 @@
3
3
  #
4
4
  # findapp -- locate an application by name, bundle ID or creator code
5
5
  #
6
- # Copyright (C) 2006-2009 HAS. Released under MIT License.
7
- #
8
6
 
9
7
  module FindApp
10
8
  # Support module for obtaining the full path to a local application given its name, bundle id or creator type. If application isn't found, an ApplicationNotFoundError exception is raised.
@@ -3,8 +3,6 @@
3
3
  #
4
4
  # mactypes -- Ruby classes representing Alias, FileURL and unit type AEDescs
5
5
  #
6
- # Copyright (C) 2006-2009 HAS. Released under MIT License.
7
- #
8
6
 
9
7
  module MacTypes
10
8
  # Defines wrapper classes for Mac OS datatypes that don't have a suitable Ruby equivalent.
@@ -3,13 +3,11 @@
3
3
  #
4
4
  # send -- Event class represents a packed AppleEvent that's ready to send via AESendMessage
5
5
  #
6
- # Copyright (C) 2006-2009 HAS. Released under MIT License.
7
- #
8
6
 
9
7
  module Send
10
8
 
11
9
  # Defines the Event class, which represents an Apple event that's packed and ready to send,
12
- # and the CommandError class, which contains error information for a failed event.
10
+ # and the EventError class, which contains error information for a failed event.
13
11
 
14
12
  require "ae"
15
13
  require "kae"
@@ -73,7 +71,7 @@ module Send
73
71
  reply_event = _send_apple_event(flags, timeout)
74
72
  rescue AE::MacOSError => err # The Apple Event Manager raised an error.
75
73
  if not(@_event_code == 'aevtquit' and err.to_i == -609) # Ignore invalid connection errors (-609) when quitting
76
- raise CommandError.new(err.to_i)
74
+ raise EventError.new(err.to_i)
77
75
  end
78
76
  else # Decode application's reply, if any. May be a return value, error number (and optional message), or nothing.
79
77
  if reply_event.type != KAE::TypeNull
@@ -86,7 +84,7 @@ module Send
86
84
  # Error info is unpacked using default codecs for reliability.
87
85
  e_num = DefaultCodecs.unpack(event_result[KAE::KeyErrorNumber])
88
86
  if e_num != 0 # Some apps (e.g. Finder) may return error code 0 to indicate a successful operation, so ignore this.
89
- raise CommandError.new(e_num, event_result)
87
+ raise EventError.new(e_num, event_result)
90
88
  end
91
89
  end
92
90
  if event_result.has_key?(KAE::KeyAEResult)
@@ -101,7 +99,7 @@ module Send
101
99
  end
102
100
 
103
101
 
104
- class CommandError < RuntimeError
102
+ class EventError < RuntimeError
105
103
  # Represents an error raised by the Apple Event Manager or target application when a command fails.
106
104
  #
107
105
  # Methods:
@@ -255,9 +253,9 @@ module Send
255
253
 
256
254
  def to_s
257
255
  if message != ''
258
- return "CommandError\n\t\tOSERROR: #{number}\n\t\tMESSAGE: #{message}"
256
+ return "EventError\n\t\tOSERROR: #{number}\n\t\tMESSAGE: #{message}"
259
257
  else
260
- return "CommandError\n\t\tOSERROR: #{number}"
258
+ return "EventError\n\t\tOSERROR: #{number}"
261
259
  end
262
260
  end
263
261
 
@@ -3,8 +3,6 @@
3
3
  #
4
4
  # typewrappers -- Ruby classes representing type, enumerator, property and keyword AEDescs
5
5
  #
6
- # Copyright (C) 2006-2009 HAS. Released under MIT License.
7
- #
8
6
 
9
7
  module TypeWrappers
10
8
 
@@ -3,8 +3,6 @@
3
3
  #
4
4
  # defaultterminology -- lookup tables for default type, enumerator and command definitions
5
5
  #
6
- # Copyright (C) 2006-2009 HAS. Released under MIT License.
7
- #
8
6
 
9
7
  module DefaultTerminology
10
8
  # 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.
@@ -3,8 +3,6 @@
3
3
  #
4
4
  # referencerenderer -- obtain an appscript-style string representation of an aem reference
5
5
  #
6
- # Copyright (C) 2006-2009 HAS. Released under MIT License.
7
- #
8
6
 
9
7
  require "_aem/aemreference"
10
8
 
@@ -21,7 +19,7 @@ class ReferenceRenderer
21
19
  end
22
20
 
23
21
  def _format(val)
24
- if val.is_a?(AEMReference::Base)
22
+ if val.is_a?(AEMReference::Query)
25
23
  return ReferenceRenderer.render(@_app_data, val)
26
24
  else
27
25
  return val.inspect
@@ -4,8 +4,6 @@
4
4
  # reservedkeywords -- names of methods already used by Ruby's Object class
5
5
  # and appscript's Reference class
6
6
  #
7
- # Copyright (C) 2006-2009 HAS. Released under MIT License.
8
- #
9
7
 
10
8
  # This list is mirrored in ch.6 of the appscript manual and in py-osaterminology's makeidentifier module
11
9
 
@@ -3,7 +3,6 @@
3
3
  #
4
4
  # safeobject -- ensure Appscript::Reference#method_missing works reliably
5
5
  #
6
- # New code Copyright (C) 2006-2009 HAS
7
6
  # Original code Copyright (C) 2005 Thomas Sawyer, Jim Weirich; see below for original copyright
8
7
  #
9
8
 
@@ -60,14 +59,64 @@
60
59
  #
61
60
  # == Copyright (c) 2005 Thomas Sawyer, Jim Weirich
62
61
  #
63
- # Ruby License
64
- #
65
- # This module is free software. You may use, modify, and/or redistribute this
66
- # software under the same terms as Ruby.
67
- #
68
- # This program is distributed in the hope that it will be useful, but WITHOUT
69
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
70
- # FOR A PARTICULAR PURPOSE.
62
+ # THE RUBY LICENSE
63
+ # (http://www.ruby-lang.org/en/LICENSE.txt)
64
+ #
65
+ # You may redistribute this software and/or modify it under either the terms of
66
+ # the GPL (see below), or the conditions below:
67
+ #
68
+ # 1. You may make and give away verbatim copies of the source form of the
69
+ # software without restriction, provided that you duplicate all of the
70
+ # original copyright notices and associated disclaimers.
71
+ #
72
+ # 2. You may modify your copy of the software in any way, provided that
73
+ # you do at least ONE of the following:
74
+ #
75
+ # a) place your modifications in the Public Domain or otherwise
76
+ # make them Freely Available, such as by posting said
77
+ # modifications to Usenet or an equivalent medium, or by allowing
78
+ # the author to include your modifications in the software.
79
+ #
80
+ # b) use the modified software only within your corporation or
81
+ # organization.
82
+ #
83
+ # c) rename any non-standard executables so the names do not conflict
84
+ # with standard executables, which must also be provided.
85
+ #
86
+ # d) make other distribution arrangements with the author.
87
+ #
88
+ # 3. You may distribute the software in object code or executable
89
+ # form, provided that you do at least ONE of the following:
90
+ #
91
+ # a) distribute the executables and library files of the software,
92
+ # together with instructions (in the manual page or equivalent)
93
+ # on where to get the original distribution.
94
+ #
95
+ # b) accompany the distribution with the machine-readable source of
96
+ # the software.
97
+ #
98
+ # c) give non-standard executables non-standard names, with
99
+ # instructions on where to get the original software distribution.
100
+ #
101
+ # d) make other distribution arrangements with the author.
102
+ #
103
+ # 4. You may modify and include the part of the software into any other
104
+ # software (possibly commercial). But some files in the distribution
105
+ # are not written by the author, so that they are not under these terms.
106
+ #
107
+ # For the list of those files and their copying conditions, see the
108
+ # file LEGAL.
109
+ #
110
+ # 5. The scripts and library files supplied as input to or produced as
111
+ # output from the software do not automatically fall under the
112
+ # copyright of the software, but belong to whomever generated them,
113
+ # and may be sold commercially, and may be aggregated with this
114
+ # software.
115
+ #
116
+ # 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
117
+ # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
118
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
119
+ # PURPOSE.
71
120
 
72
121
  ######################################################################
73
122
  # PUBLIC
@@ -3,8 +3,6 @@
3
3
  #
4
4
  # terminology -- retrieve and convert an application's terminology into lookup tables
5
5
  #
6
- # Copyright (C) 2006-2009 HAS. Released under MIT License.
7
- #
8
6
 
9
7
  ######################################################################
10
8
  # TERMINOLOGY PARSER
@@ -339,6 +337,38 @@ module Terminology
339
337
  return reference_by_code, reference_by_name
340
338
  end
341
339
 
340
+ def Terminology.dump_tables(tables, module_name, source_path, out_path)
341
+ # Parse aete(s) into intermediate tables, suitable for use by Terminology#tables_for_module
342
+ if not(/^[A-Z][A-Za-z0-9_]*$/ === module_name)
343
+ raise RuntimeError, "Invalid module name."
344
+ end
345
+ # Write module
346
+ File.open(out_path, "w") do |f|
347
+ f.puts "module #{module_name}"
348
+ f.puts "\tVersion = 1.1"
349
+ f.puts "\tPath = #{source_path.inspect}"
350
+ f.puts
351
+ (["Classes", "Enumerators", "Properties", "Elements"].zip(tables[0,4])).each do |name, table|
352
+ f.puts "\t#{name} = ["
353
+ table.sort.each do |item|
354
+ f.puts "\t\t#{item.inspect},"
355
+ end
356
+ f.puts "\t]"
357
+ f.puts
358
+ end
359
+ f.puts "\tCommands = ["
360
+ tables[4].sort.each do |name, code, params|
361
+ f.puts "\t\t[#{name.inspect}, #{code.inspect}, ["
362
+ params.each do |item|
363
+ f.puts "\t\t\t#{item.inspect},"
364
+ end
365
+ f.puts "\t\t]],"
366
+ end
367
+ f.puts "\t]"
368
+ f.puts "end"
369
+ end
370
+ end
371
+
342
372
  #######
343
373
  # public
344
374
 
@@ -367,11 +397,18 @@ module Terminology
367
397
  + _make_reference_table(terms::Properties, terms::Elements, terms::Commands)
368
398
  end
369
399
 
400
+ def Terminology.tables_for_parsed_sdef(terms)
401
+ # Build terminology tables from an SdefParser instance.
402
+ # Result : list of hash -- [typebycode, typebyname, referencebycode, referencebyname]
403
+ return _make_type_table(terms.classes, terms.enumerators, terms.properties) \
404
+ + _make_reference_table(terms.properties, terms.elements, terms.commands)
405
+ end
406
+
370
407
  def Terminology.aetes_for_app(aem_app)
371
408
  begin
372
409
  begin
373
410
  aetes = aem_app.event('ascrgdte', {'----' => 0}).send(120 * 60)
374
- rescue AEM::CommandError => e
411
+ rescue AEM::EventError => e
375
412
  if e.number == -192 # aete resource not found
376
413
  aetes = []
377
414
  else
@@ -397,58 +434,38 @@ module Terminology
397
434
  end
398
435
 
399
436
  #######
437
+ # public
400
438
 
401
439
  def Terminology.dump(app_name, module_name, out_path)
402
- # Export terminology tables as a Ruby module
440
+ # Export application terminology tables as a Ruby module
403
441
  # app_path : string -- name or path of application
404
442
  # module_name : string -- name of generated module (must be a valid Ruby constant)
405
443
  # out_path : string -- module file to write
444
+ #
445
+ # Generates a Ruby module containing an application's basic terminology
446
+ # (names and codes) as used by appscript.
447
+ #
448
+ # Call the #dump method to dump faulty aetes to Ruby module, e.g.:
449
+ #
450
+ # Terminology.dump('MyApp', 'MyAppGlue', '/path/to/ruby/modules/myappglue.rb')
451
+ #
452
+ # Patch any errors by hand, then import the patched module into your script
453
+ # and pass it to appscript's app() constructor via its 'terms' argument, e.g.:
454
+ #
455
+ # require 'appscript'; include Appscript
456
+ # require 'myappglue'
457
+ #
458
+ # myapp = app('MyApp', terms => MyAppGlue)
459
+ #
460
+ # Note that dumped terminologies aren't used by appscript's built-in help system.
461
+ #
406
462
  app_path = FindApp.by_name(app_name)
407
- if not(/^[A-Z][A-Za-z0-9_]*$/ === module_name)
408
- raise RuntimeError, "Invalid module name."
409
- end
410
463
  # Get aete(s)
411
- begin
412
- begin
413
- aetes = AEM::Codecs.new.unpack(AE.get_app_terminology(app_path).coerce(KAE::TypeAEList))
414
- rescue NotImplementedError # get_app_terminology is unavailable on 64-bit Leopard
415
- aetes = Terminology.aetes_for_app(AEM::Application.by_path(app_path))
416
- end
417
- rescue AE::MacOSError => e
418
- if e.to_i == -192 # aete resource not found
419
- raise RuntimeError, "No terminology found."
420
- else
421
- raise
422
- end
423
- end
464
+ aetes = Terminology.aetes_for_app(Application.by_path(app_path))
424
465
  aetes.delete_if { |aete| not(aete.is_a?(AE::AEDesc) and aete.type == KAE::TypeAETE) }
425
- # Parse aete(s) into intermediate tables, suitable for use by Terminology#tables_for_module
426
466
  tables = TerminologyParser.build_tables_for_aetes(aetes)
427
- # Write module
428
- File.open(out_path, "w") do |f|
429
- f.puts "module #{module_name}"
430
- f.puts "\tVersion = 1.1"
431
- f.puts "\tPath = #{app_path.inspect}"
432
- f.puts
433
- (["Classes", "Enumerators", "Properties", "Elements"].zip(tables[0,4])).each do |name, table|
434
- f.puts "\t#{name} = ["
435
- table.sort.each do |item|
436
- f.puts "\t\t#{item.inspect},"
437
- end
438
- f.puts "\t]"
439
- f.puts
440
- end
441
- f.puts "\tCommands = ["
442
- tables[4].sort.each do |name, code, params|
443
- f.puts "\t\t[#{name.inspect}, #{code.inspect}, ["
444
- params.each do |item|
445
- f.puts "\t\t\t#{item.inspect},"
446
- end
447
- f.puts "\t\t]],"
448
- end
449
- f.puts "\t]"
450
- f.puts "end"
451
- end
467
+ Terminology.dump_tables(tables, module_name, app_path, out_path)
452
468
  end
469
+
453
470
  end
454
471