rb-appscript 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/CHANGES +30 -0
  2. data/LICENSE +1 -1
  3. data/README +7 -3
  4. data/TODO +7 -1
  5. data/doc/aem-manual/01_introduction.html +23 -9
  6. data/doc/aem-manual/02_apioverview.html +25 -11
  7. data/doc/aem-manual/03_packingandunpackingdata.html +22 -17
  8. data/doc/aem-manual/04_references.html +49 -36
  9. data/doc/aem-manual/05_targettingapplications.html +25 -14
  10. data/doc/aem-manual/06_buildingandsendingevents.html +47 -21
  11. data/doc/aem-manual/07_findapp.html +22 -11
  12. data/doc/aem-manual/08_examples.html +21 -10
  13. data/doc/aem-manual/index.html +28 -12
  14. data/doc/appscript-manual/01_introduction.html +40 -27
  15. data/doc/appscript-manual/02_aboutappscripting.html +28 -15
  16. data/doc/appscript-manual/03_quicktutorial.html +29 -16
  17. data/doc/appscript-manual/04_gettinghelp.html +31 -16
  18. data/doc/appscript-manual/05_keywordconversion.html +23 -10
  19. data/doc/appscript-manual/06_classesandenums.html +32 -19
  20. data/doc/appscript-manual/07_applicationobjects.html +31 -18
  21. data/doc/appscript-manual/08_realvsgenericreferences.html +23 -11
  22. data/doc/appscript-manual/09_referenceforms.html +33 -20
  23. data/doc/appscript-manual/10_referenceexamples.html +30 -17
  24. data/doc/appscript-manual/11_applicationcommands.html +25 -13
  25. data/doc/appscript-manual/12_commandexamples.html +26 -15
  26. data/doc/appscript-manual/13_performanceissues.html +46 -20
  27. data/doc/appscript-manual/14_notes.html +29 -19
  28. data/doc/appscript-manual/index.html +27 -11
  29. data/doc/full.css +95 -9
  30. data/doc/index.html +27 -10
  31. data/doc/mactypes-manual/01_introduction.html +56 -0
  32. data/doc/mactypes-manual/02_aliasclass.html +134 -0
  33. data/doc/mactypes-manual/03_fileurlclass.html +136 -0
  34. data/doc/mactypes-manual/04_unitsclass.html +102 -0
  35. data/doc/mactypes-manual/index.html +26 -227
  36. data/doc/osax-manual/01_introduction.html +69 -0
  37. data/doc/osax-manual/02_interface.html +149 -0
  38. data/doc/osax-manual/03_examples.html +75 -0
  39. data/doc/osax-manual/04_notes.html +80 -0
  40. data/doc/osax-manual/index.html +26 -195
  41. data/doc/rb-appscript-logo.png +0 -0
  42. data/rb-appscript.gemspec +2 -2
  43. data/sample/TextEdit_demo.rb +1 -1
  44. data/src/lib/_aem/aemreference.rb +1 -1
  45. data/src/lib/_aem/codecs.rb +42 -8
  46. data/src/lib/_aem/connect.rb +3 -1
  47. data/src/lib/_aem/findapp.rb +1 -1
  48. data/src/lib/_aem/mactypes.rb +1 -1
  49. data/src/lib/_aem/send.rb +162 -142
  50. data/src/lib/_aem/typewrappers.rb +2 -2
  51. data/src/lib/_appscript/defaultterminology.rb +76 -46
  52. data/src/lib/_appscript/referencerenderer.rb +1 -1
  53. data/src/lib/_appscript/reservedkeywords.rb +2 -2
  54. data/src/lib/_appscript/safeobject.rb +1 -1
  55. data/src/lib/_appscript/terminology.rb +30 -19
  56. data/src/lib/aem.rb +1 -6
  57. data/src/lib/appscript.rb +65 -20
  58. data/src/lib/osax.rb +21 -18
  59. data/src/rbae.c +1 -1
  60. data/test/test_appscriptcommands.rb +1 -1
  61. metadata +12 -3
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # typewrappers -- Ruby classes representing type, enumerator, property and keyword AEDescs
5
5
  #
6
- # Copyright (C) 2006-2008 HAS. Released under MIT License.
6
+ # Copyright (C) 2006-2009 HAS. Released under MIT License.
7
7
  #
8
8
 
9
9
  module TypeWrappers
@@ -13,7 +13,7 @@ module TypeWrappers
13
13
  attr_reader :code
14
14
 
15
15
  def initialize(code)
16
- if not (code.is_a?(String) and code.length == 4)
16
+ if not(code.is_a?(String) and code.length == 4)
17
17
  raise ArgumentError, "Code must be a four-character string: #{code.inspect}"
18
18
  end
19
19
  @code = code
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # defaultterminology -- lookup tables for default type, enumerator and command definitions
5
5
  #
6
- # Copyright (C) 2006-2008 HAS. Released under MIT License.
6
+ # Copyright (C) 2006-2009 HAS. Released under MIT License.
7
7
  #
8
8
 
9
9
  module DefaultTerminology
@@ -64,7 +64,7 @@ module DefaultTerminology
64
64
  'ldt ' => :date,
65
65
  'list' => :list,
66
66
  'reco' => :record,
67
- 'rdat' => :data,
67
+ 'tdta' => :data,
68
68
  'scpt' => :script,
69
69
 
70
70
  'insl' => :location_reference,
@@ -114,7 +114,7 @@ module DefaultTerminology
114
114
 
115
115
  'msng' => :missing_value,
116
116
 
117
- 'pcls' => :class_,
117
+ 'cobj' => :item,
118
118
 
119
119
  'null' => :null,
120
120
 
@@ -190,60 +190,90 @@ module DefaultTerminology
190
190
  'sat ' => :Saturday,
191
191
  }
192
192
 
193
- #######
194
- # TypeByCode and TypeByName tables are used to convert Ruby Symbols to and from AEDescs of typeType, typeEnum and typeProperty.
195
-
196
- TypeByCode = Types.clone.update(Enums)
197
-
198
- TypeByName = {}
199
- Types.each { |code, name| TypeByName[name] = AEM::AEType.new(code) }
200
- Enums.each { |code, name| TypeByName[name] = AEM::AEEnum.new(code) }
201
-
202
- #######
203
- # ReferenceByCode tables is used by ReferenceRenderer module to convert property and element four-char codes to human readable names
204
- #
205
- # ReferenceByName table is used to convert appscript-style references and commands to their aem equivalents
193
+ Properties = {
194
+ 'pcls' => :class_,
195
+ 'pAll' => :properties_,
196
+ 'ID ' => :id_,
197
+ }
206
198
 
207
- ReferenceByCode = {
208
- 'ppcls' => 'class_',
209
- 'pID ' => 'id_',
199
+ Elements = {
200
+ 'cobj' => :items,
210
201
  }
211
202
 
212
- ReferenceByName = {
213
- :quit => [:command, ['aevtquit', {
203
+ Commands = {
204
+ :quit => ['aevtquit', {
214
205
  :saving => 'savo',
215
- }]],
216
- :activate => [:command, ['miscactv', {
217
- }]],
218
- :run => [:command, ['aevtoapp', {
219
- }]],
220
- :launch => [:command, ['ascrnoop', {
221
- }]],
222
- :open => [:command, ['aevtodoc', {
223
- }]],
224
- :get => [:command, ['coregetd', {
225
- }]],
226
- :print => [:command, ['aevtpdoc', {
227
- }]],
228
- :class_ => [:property, 'pcls'],
229
- :set => [:command, ['coresetd', {
206
+ }],
207
+ :activate => ['miscactv', {
208
+ }],
209
+ :run => ['aevtoapp', {
210
+ }],
211
+ :launch => ['ascrnoop', {
212
+ }],
213
+ :open => ['aevtodoc', {
214
+ }],
215
+ :get => ['coregetd', {
216
+ }],
217
+ :print => ['aevtpdoc', {
218
+ }],
219
+ :set => ['coresetd', {
230
220
  :to => 'data',
231
- }]],
232
- :reopen => [:command, ['aevtrapp', {
233
- }]],
234
- :id_ => [:property, 'ID '],
235
- :open_location => [:command, ['GURLGURL', {
221
+ }],
222
+ :reopen => ['aevtrapp', {
223
+ }],
224
+ :open_location => ['GURLGURL', {
236
225
  :window => 'WIND',
237
- }]],
226
+ }],
238
227
  }
239
-
228
+
229
+ #######
230
+ # TypeByCode and TypeByName tables are used to convert Ruby Symbols to and from AEDescs of typeType, typeEnum and typeProperty.
231
+
232
+ TypeByCode = {} # used to decode class (typeType) and enumerator (typeEnum) descriptors
233
+ TypeByName = {} # used to encode class and enumerator keywords
234
+ TypeCodeByName = {} # used to check for name collisions
235
+
236
+ Enums.each do |code, name|
237
+ TypeByCode[code] = name
238
+ TypeByName[name] = AEM::AEEnum.new(code)
239
+ TypeCodeByName[name.to_s] = code
240
+ end
241
+
242
+ [Types, Properties].each do |table|
243
+ table.each do |code, name|
244
+ TypeByCode[code] = name
245
+ TypeByName[name] = AEM::AEType.new(code)
246
+ TypeCodeByName[name.to_s] = code
247
+ end
248
+ end
249
+
250
+ #######
251
+ # ReferenceByCode and ReferenceByName tables are used to convert between appscript- and aem-style references
252
+
253
+ ReferenceByCode = {} # used by ReferenceRenderer module to convert property and element four-char codes to human readable names
254
+ ReferenceByName = {} # used to convert appscript-style references and commands to their aem equivalents
255
+
256
+ Properties.each do |code, name|
257
+ ReferenceByCode['p' + code] = name.to_s
258
+ ReferenceByName[name] = [:property, code]
259
+ end
260
+
261
+ Elements.each do |code, name|
262
+ ReferenceByCode['e' + code] = name.to_s
263
+ ReferenceByName[name] = [:element, code]
264
+ end
265
+
266
+ Commands.each do |name, info|
267
+ ReferenceByName[name] = [:command, info]
268
+ end
269
+
240
270
  #######
241
- # DefaultCommands; used by Terminology._make_reference_table to check for any collisions between standard and application-defined commands where the command names are the same but the codes are different
271
+ # CommandCodeByName; used by Terminology._make_reference_table to check for any collisions between standard and application-defined commands where the command names are the same but the codes are different
242
272
 
243
- DefaultCommands = {} # {'quit' => 'aevtquit', 'activate' => 'miscactv',...}
273
+ CommandCodeByName = {} # {'quit' => 'aevtquit', 'activate' => 'miscactv',...}
244
274
  ReferenceByName.each do |name, info|
245
275
  if info[0] == :command
246
- DefaultCommands[name.to_s] = info[1][0]
276
+ CommandCodeByName[name.to_s] = info[1][0]
247
277
  end
248
278
  end
249
279
  end
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # referencerenderer -- obtain an appscript-style string representation of an aem reference
5
5
  #
6
- # Copyright (C) 2006-2008 HAS. Released under MIT License.
6
+ # Copyright (C) 2006-2009 HAS. Released under MIT License.
7
7
  #
8
8
 
9
9
  require "_aem/aemreference"
@@ -4,10 +4,10 @@
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-2008 HAS. Released under MIT License.
7
+ # Copyright (C) 2006-2009 HAS. Released under MIT License.
8
8
  #
9
9
 
10
- # This list is mirrored in ch.6 of the appscript manual and in py-appscript's osaterminology.makeidentifier module
10
+ # This list is mirrored in ch.6 of the appscript manual and in py-osaterminology's makeidentifier module
11
11
 
12
12
  ReservedKeywords = [
13
13
  "==",
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # safeobject -- ensure Appscript::Reference#method_missing works reliably
5
5
  #
6
- # New code Copyright (C) 2006-2008 HAS
6
+ # New code Copyright (C) 2006-2009 HAS
7
7
  # Original code Copyright (C) 2005 Thomas Sawyer, Jim Weirich; see below for original copyright
8
8
  #
9
9
 
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # terminology -- retrieve and convert an application's terminology into lookup tables
5
5
  #
6
- # Copyright (C) 2006-2008 HAS. Released under MIT License.
6
+ # Copyright (C) 2006-2009 HAS. Released under MIT License.
7
7
  #
8
8
 
9
9
  ######################################################################
@@ -283,17 +283,17 @@ module Terminology
283
283
  table.each_with_index do |item, i|
284
284
  name, code = item
285
285
  # If an application-defined name overlaps an existing type name but has a different code, append '_' to avoid collision:
286
- if DefaultTerminology::TypeByName.has_key?(name) and \
287
- DefaultTerminology::TypeByName[name].code != code
288
- name += '_'
286
+ name += '_' if DefaultTerminology::TypeCodeByName.fetch(name, code) != code
287
+ begin
288
+ type_by_code[code] = name.intern # to handle synonyms, if same code appears more than once then use name from last definition in list
289
+ rescue ArgumentError # ignore #intern error if name is empty string
289
290
  end
290
- type_by_code[code] = name.intern # to handle synonyms, if same code appears more than once then use name from last definition in list
291
291
  name, code = table[-i - 1]
292
- if DefaultTerminology::TypeByName.has_key?(name) and \
293
- DefaultTerminology::TypeByName[name].code != code
294
- name += '_'
292
+ name += '_' if DefaultTerminology::TypeCodeByName.fetch(name, code) != code
293
+ begin
294
+ type_by_name[name.intern] = klass.new(code) # to handle synonyms, if same name appears more than once then use code from first definition in list
295
+ rescue ArgumentError # ignore #intern error if name is empty string
295
296
  end
296
- type_by_name[name.intern] = klass.new(code) # to handle synonyms, if same name appears more than once then use code from first definition in list
297
297
  end
298
298
  end
299
299
  return [type_by_code, type_by_name]
@@ -307,9 +307,15 @@ module Terminology
307
307
  # note: if property and element names are same (e.g. 'file' in BBEdit), will pack as property specifier unless it's a special case (i.e. see :text below). Note that there is currently no way to override this, i.e. to force appscript to pack it as an all-elements specifier instead (in AS, this would be done by prepending the 'every' keyword), so clients would need to use aem for that (but could add an 'all' method to Reference class if there was demand for a built-in workaround)
308
308
  table.each_with_index do |item, i|
309
309
  name, code = item
310
+ # If an application-defined name overlaps an existing type name but has a different code, append '_' to avoid collision:
311
+ name += '_' if DefaultTerminology::TypeCodeByName.fetch(name, code) != code
310
312
  reference_by_code[prefix + code] = name # to handle synonyms, if same code appears more than once then use name from last definition in list
311
313
  name, code = table[-i - 1]
312
- reference_by_name[name.intern] = [kind, code] # to handle synonyms, if same name appears more than once then use code from first definition in list
314
+ name += '_' if DefaultTerminology::TypeCodeByName.fetch(name, code) != code
315
+ begin
316
+ reference_by_name[name.intern] = [kind, code] # to handle synonyms, if same name appears more than once then use code from first definition in list
317
+ rescue ArgumentError # ignore #intern error if name is empty string
318
+ end
313
319
  end
314
320
  end
315
321
  if reference_by_name.has_key?(:text) # special case: AppleScript always packs 'text of...' as all-elements specifier
@@ -317,13 +323,18 @@ module Terminology
317
323
  end
318
324
  commands.reverse.each do |name, code, args| # to handle synonyms, if two commands have same name but different codes, only the first definition should be used (iterating over the commands list in reverse ensures this)
319
325
  # Avoid collisions between default commands and application-defined commands with same name but different code (e.g. 'get' and 'set' in InDesign CS2):
320
- if DefaultTerminology::DefaultCommands.has_key?(name) and \
321
- code != DefaultTerminology::DefaultCommands[name]
322
- name += '_'
323
- end
326
+ name += '_' if DefaultTerminology::CommandCodeByName.fetch(name, code) != code
324
327
  dct = {}
325
- args.each { |arg_name, arg_code| dct[arg_name.intern] = arg_code }
326
- reference_by_name[name.intern] = [:command, [code, dct]]
328
+ args.each do |arg_name, arg_code|
329
+ begin
330
+ dct[arg_name.intern] = arg_code
331
+ rescue ArgumentError # ignore #intern error if name is empty string
332
+ end
333
+ end
334
+ begin
335
+ reference_by_name[name.intern] = [:command, [code, dct]]
336
+ rescue ArgumentError # ignore #intern error if name is empty string
337
+ end
327
338
  end
328
339
  return reference_by_code, reference_by_name
329
340
  end
@@ -339,7 +350,7 @@ module Terminology
339
350
  def Terminology.tables_for_aetes(aetes)
340
351
  # Build terminology tables from a list of unpacked aete byte strings.
341
352
  # Result : list of hash -- [typebycode, typebyname, referencebycode, referencebyname]
342
- aetes = aetes.reject { |aete| not (aete.is_a?(AE::AEDesc) and aete.type == KAE::TypeAETE and aete.data != '') }
353
+ aetes = aetes.reject { |aete| not(aete.is_a?(AE::AEDesc) and aete.type == KAE::TypeAETE and aete.data != '') }
343
354
  classes, enums, properties, elements, commands = TerminologyParser.build_tables_for_aetes(aetes)
344
355
  return _make_type_table(classes, enums, properties) + _make_reference_table(properties, elements, commands)
345
356
  end
@@ -393,7 +404,7 @@ module Terminology
393
404
  # module_name : string -- name of generated module (must be a valid Ruby constant)
394
405
  # out_path : string -- module file to write
395
406
  app_path = FindApp.by_name(app_name)
396
- if not /^[A-Z][A-Za-z0-9_]*$/ === module_name
407
+ if not(/^[A-Z][A-Za-z0-9_]*$/ === module_name)
397
408
  raise RuntimeError, "Invalid module name."
398
409
  end
399
410
  # Get aete(s)
@@ -410,7 +421,7 @@ module Terminology
410
421
  raise
411
422
  end
412
423
  end
413
- aetes.delete_if { |aete| not (aete.is_a?(AE::AEDesc) and aete.type == KAE::TypeAETE) }
424
+ aetes.delete_if { |aete| not(aete.is_a?(AE::AEDesc) and aete.type == KAE::TypeAETE) }
414
425
  # Parse aete(s) into intermediate tables, suitable for use by Terminology#tables_for_module
415
426
  tables = TerminologyParser.build_tables_for_aetes(aetes)
416
427
  # Write module
@@ -4,7 +4,7 @@
4
4
  # aem -- a mid-level object-oriented API for creating and sending Apple events
5
5
  # using raw AE codes; may be used directly or via high-level appscript wrapper
6
6
  #
7
- # Copyright (C) 2006-2008 HAS. Released under MIT License.
7
+ # Copyright (C) 2006-2009 HAS. Released under MIT License.
8
8
  #
9
9
 
10
10
  require "ae"
@@ -112,11 +112,6 @@ module AEM
112
112
  Connect.launch_app_with_launch_event(path)
113
113
  end
114
114
 
115
- def Application.is_running?(path) # TO DO: delete
116
- $stderr.puts('Warning! AEM::Application.is_running? is deprecated; use process_exists_for_path? instead.')
117
- return Connect.process_exists_for_path?(path)
118
- end
119
-
120
115
  def Application.process_exists_for_path?(path)
121
116
  # Does a local process launched from the specified application file exist?
122
117
  # Note: if path is invalid, an AE::MacOSError is raised.
@@ -4,14 +4,14 @@
4
4
  # appscript -- syntactically sugared wrapper around the mid-level aem API;
5
5
  # provides a high-level, easy-to-use API for creating and sending Apple events
6
6
  #
7
- # Copyright (C) 2006-2008 HAS. Released under MIT License.
7
+ # Copyright (C) 2006-2009 HAS. Released under MIT License.
8
8
  #
9
9
 
10
10
  require "_aem/mactypes"
11
11
 
12
12
  module Appscript
13
13
 
14
- Version = '0.5.0'
14
+ Version = '0.5.2'
15
15
 
16
16
  # The following methods and classes are of interest to end users:
17
17
  # app, con, its, CommandError, ApplicationNotFoundError, CantLaunchApplicationError
@@ -75,6 +75,12 @@ module Appscript
75
75
 
76
76
  #######
77
77
 
78
+ def dont_cache_unpacked_specifiers
79
+ @reference_codecs.dont_cache_unpacked_specifiers
80
+ end
81
+
82
+ #######
83
+
78
84
  Constructors = {
79
85
  :by_path => 'path',
80
86
  :by_pid => 'pid',
@@ -88,11 +94,10 @@ module Appscript
88
94
  apppath = FindApp.by_id(ASDictionaryBundleID)
89
95
  asdictionary_is_running = AEM::Application.process_exists_for_path?(apppath)
90
96
  @_help_agent = AEM::Application.by_path(apppath)
91
- if not asdictionary_is_running # hide ASDictionary after launching it # TO DO: something less kludgy
97
+ if not asdictionary_is_running # hide ASDictionary after launching it
92
98
  AEM::Application.by_path(FindApp.by_id('com.apple.systemevents')).event('coresetd', {
93
99
  '----' => AEM.app.elements('prcs').by_name('ASDictionary').property('pvis'),
94
100
  'data' => false}).send
95
- 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
96
101
  end
97
102
  return true
98
103
  rescue FindApp::ApplicationNotFoundError => e
@@ -128,13 +133,7 @@ module Appscript
128
133
  return ref if not _init_help_agent
129
134
  e = _display_help(flags, ref)
130
135
  end
131
- if e
132
- if e.number == -1708 # event wasn't handled, presumably because available ASDictionary is too old
133
- $stderr.puts("No help available: ASDictionary 0.9.0 or later required.")
134
- else
135
- $stderr.puts("No help available: ASDictionary raised an error: #{e}.")
136
- end
137
- end
136
+ $stderr.puts("No help available: ASDictionary raised an error: #{e}.") if e
138
137
  rescue => err
139
138
  $stderr.puts("No help available: unknown error: #{err}")
140
139
  end
@@ -527,7 +526,7 @@ module Appscript
527
526
  if code == 'ascrnoop'
528
527
  AEM::Application.launch(@AS_app_data.identifier)
529
528
  elsif code != 'aevtoapp'
530
- raise CommandError.new(self, name, args, e)
529
+ raise CommandError.new(self, name, args, e, @AS_app_data)
531
530
  end
532
531
  end
533
532
  # update AEMApplication object's AEAddressDesc
@@ -537,11 +536,11 @@ module Appscript
537
536
  return @AS_app_data.target.event(code, params, atts,
538
537
  KAE::KAutoGenerateReturnID, @AS_app_data).send(timeout, send_flags)
539
538
  rescue AEM::CommandError => e
540
- raise CommandError.new(self, name, args, e)
539
+ raise CommandError.new(self, name, args, e, @AS_app_data)
541
540
  end
542
541
  end
543
542
  end
544
- raise CommandError.new(self, name, args, e)
543
+ raise CommandError.new(self, name, args, e, @AS_app_data)
545
544
  end
546
545
 
547
546
 
@@ -635,8 +634,10 @@ module Appscript
635
634
  selector_type, code = @AS_app_data.reference_by_name[name]
636
635
  case selector_type # check if name is a property/element/command name, and if it is handle accordingly
637
636
  when :property
637
+ raise ArgumentError, "wrong number of arguments for '#{name}' property (1 for 0)" if args != []
638
638
  return Reference.new(@AS_app_data, @AS_aem_reference.property(code))
639
639
  when :element
640
+ raise ArgumentError, "wrong number of arguments for '#{name}' elements (1 for 0)" if args != []
640
641
  return Reference.new(@AS_app_data, @AS_aem_reference.elements(code))
641
642
  when :command
642
643
  return _send_command(args, name, code[0], code[1])
@@ -692,7 +693,12 @@ module Appscript
692
693
  when Appscript::GenericReference, Appscript::Reference, AEMReference::Test
693
694
  case selector
694
695
  when Appscript::GenericReference
695
- test_clause = selector.AS_resolve(@AS_app_data).AS_aem_reference
696
+ test_clause = selector.AS_resolve(@AS_app_data)
697
+ begin
698
+ test_clause = test_clause.AS_aem_reference
699
+ rescue NoMethodError
700
+ raise ArgumentError, "Not a valid its-based test: #{selector}"
701
+ end
696
702
  when Appscript::Reference
697
703
  test_clause = selector.AS_aem_reference
698
704
  else
@@ -1008,12 +1014,31 @@ module Appscript
1008
1014
 
1009
1015
  attr_reader :reference, :name, :parameters, :real_error
1010
1016
 
1011
- def initialize(reference, command_name, parameters, real_error)
1012
- @reference, @command_name, @parameters, @real_error = reference, command_name, parameters, real_error
1017
+ def initialize(reference, command_name, parameters, real_error, codecs)
1018
+ @reference, @command_name, @parameters = reference, command_name, parameters
1019
+ @real_error, @codecs = real_error, codecs
1013
1020
  super()
1014
1021
  end
1015
1022
 
1016
- def to_i
1023
+ def to_s
1024
+ if @real_error.is_a?(AEM::CommandError)
1025
+ err = "CommandError\n\t\tOSERROR: #{error_number}"
1026
+ err += "\n\t\tMESSAGE: #{error_message}" if error_message != ''
1027
+ [
1028
+ ["\n\t\tOFFENDING OBJECT", KAE::KOSAErrorOffendingObject],
1029
+ ["\n\t\tEXPECTED TYPE", KAE::KOSAErrorExpectedType],
1030
+ ["\n\t\tPARTIAL RESULT", KAE::KOSAErrorPartialResult],
1031
+ ].each do |label, key|
1032
+ desc = @real_error.raw[key]
1033
+ err += "#{label}: #{@codecs.unpack(desc).inspect}" if desc
1034
+ end
1035
+ else
1036
+ err = @real_error
1037
+ end
1038
+ return "#{err}\n\t\tCOMMAND: #{@reference}.#{@command_name}(#{(@parameters.collect { |item| item.inspect }).join(', ')})\n"
1039
+ end
1040
+
1041
+ def error_number
1017
1042
  if @real_error.is_a?(AE::MacOSError) or @real_error.is_a?(AEM::CommandError)
1018
1043
  return @real_error.to_i
1019
1044
  else
@@ -1021,8 +1046,28 @@ module Appscript
1021
1046
  end
1022
1047
  end
1023
1048
 
1024
- def to_s
1025
- return "#{@real_error}\n\t\tCOMMAND: #{@reference}.#{@command_name}(#{(@parameters.collect { |item| item.inspect }).join(', ')})\n"
1049
+ alias_method :to_i, :error_number
1050
+
1051
+ def error_message
1052
+ return @real_error.message
1053
+ end
1054
+
1055
+ def offending_object
1056
+ return nil if not @real_error.is_a?(AEM::CommandError)
1057
+ desc = @real_error.raw[KAE::KOSAErrorOffendingObject]
1058
+ return desc ? @codecs.unpack(desc) : nil
1059
+ end
1060
+
1061
+ def expected_type
1062
+ return nil if not @real_error.is_a?(AEM::CommandError)
1063
+ desc = @real_error.raw[KAE::KOSAErrorExpectedType]
1064
+ return desc ? @codecs.unpack(desc) : nil
1065
+ end
1066
+
1067
+ def partial_result
1068
+ return nil if not @real_error.is_a?(AEM::CommandError)
1069
+ desc = @real_error.raw[KAE::KOSAErrorPartialResult]
1070
+ return desc ? @codecs.unpack(desc) : nil
1026
1071
  end
1027
1072
  end
1028
1073