rubyosa 0.2.0 → 0.3.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/AUTHORS +4 -0
- data/COPYRIGHT +2 -2
- data/README +7 -0
- data/bin/rdoc-osa +47 -18
- data/extconf.rb +8 -2
- data/sample/AddressBook/inspect.rb +31 -0
- data/sample/{BBEdit_unix_script.rb → BBEdit/unix_script.rb} +0 -0
- data/sample/{Finder_show_desktop.rb → Finder/show_desktop.rb} +0 -0
- data/sample/Mail/get_selected_mail.rb +14 -0
- data/sample/{QT_playall.rb → QuickTime/play_all.rb} +0 -0
- data/sample/{TextEdit_hello_world.rb → TextEdit/hello_world.rb} +1 -1
- data/sample/{iChat_image.rb → iChat/image.rb} +0 -0
- data/sample/{iChat_uptime.rb → iChat/uptime.rb} +0 -0
- data/sample/{iTunes_artwork.rb → iTunes/artwork.rb} +0 -0
- data/sample/{iTunes_control.rb → iTunes/control.rb} +0 -0
- data/sample/{iTunes_fade_volume.rb → iTunes/fade_volume.rb} +0 -0
- data/sample/{iTunes_inspect.rb → iTunes/inspect.rb} +0 -0
- data/sample/iTunes/tag_genre_lastfm.rb +20 -0
- data/sample/{sdef.rb → misc/sdef.rb} +6 -6
- data/src/lib/rbosa.rb +334 -178
- data/src/lib/rbosa_properties.rb +136 -0
- data/src/rbosa.c +97 -43
- data/src/rbosa.h +7 -3
- data/src/rbosa_conv.c +2 -2
- data/src/rbosa_err.c +105 -0
- data/src/rbosa_sdef.c +311 -20
- metadata +19 -14
data/AUTHORS
CHANGED
@@ -5,5 +5,9 @@ Contributors:
|
|
5
5
|
Aaron Patterson <aaron.patterson@gmail.com>
|
6
6
|
James MacAulay <jmacaulay@gmail.com>
|
7
7
|
Michael Pruett <michael@68k.org>
|
8
|
+
Michail Pishchagin <mblsha@gmail.com>
|
8
9
|
Sebastian Delmont <sd@notso.net>
|
10
|
+
Stefan Saasen <s@juretta.com>
|
11
|
+
Terry Donoghue <donoghue@apple.com>
|
9
12
|
Vincent Isambart <vincent.isambart@gmail.com>
|
13
|
+
Wes Rogers <wesrog@gmail.com>
|
data/COPYRIGHT
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2006, Apple
|
1
|
+
Copyright (c) 2006-2007, Apple Inc. All rights reserved.
|
2
2
|
|
3
3
|
Redistribution and use in source and binary forms, with or without
|
4
4
|
modification, are permitted provided that the following conditions
|
@@ -8,7 +8,7 @@ are met:
|
|
8
8
|
2. Redistributions in binary form must reproduce the above copyright
|
9
9
|
notice, this list of conditions and the following disclaimer in the
|
10
10
|
documentation and/or other materials provided with the distribution.
|
11
|
-
3. Neither the name of Apple
|
11
|
+
3. Neither the name of Apple Inc. ("Apple") nor the names of
|
12
12
|
its contributors may be used to endorse or promote products derived
|
13
13
|
from this software without specific prior written permission.
|
14
14
|
|
data/README
CHANGED
@@ -24,9 +24,16 @@ libxml-ruby 0.3.8 or greater
|
|
24
24
|
$ ruby extconf.rb
|
25
25
|
$ make
|
26
26
|
$ sudo make install
|
27
|
+
$ sudo make install-extras
|
28
|
+
|
29
|
+
`make install' will only install the core of the bridge, while
|
30
|
+
`make install-extras' will install some additional tools such as the rdoc-osa
|
31
|
+
utility.
|
27
32
|
|
28
33
|
== Support ==
|
29
34
|
|
35
|
+
A tutorial is available online at http://rubyosa.rubyforge.org/tutorial.html.
|
36
|
+
|
30
37
|
Sample code is available in the `sample' sub-directory.
|
31
38
|
|
32
39
|
The rdoc-osa tool can be used to generate API reference documentation
|
data/bin/rdoc-osa
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# RDoc frontend for RubyOSA. Generate API
|
2
|
+
# RDoc frontend for RubyOSA. Generate API reference documentation for the
|
3
3
|
# given application, based on the descriptions in the sdef(5).
|
4
4
|
#
|
5
|
-
# Copyright (c) 2006, Apple
|
5
|
+
# Copyright (c) 2006-2007, Apple Inc. All rights reserved.
|
6
6
|
#
|
7
7
|
# Redistribution and use in source and binary forms, with or without
|
8
8
|
# modification, are permitted provided that the following conditions
|
@@ -12,7 +12,7 @@
|
|
12
12
|
# 2. Redistributions in binary form must reproduce the above copyright
|
13
13
|
# notice, this list of conditions and the following disclaimer in the
|
14
14
|
# documentation and/or other materials provided with the distribution.
|
15
|
-
# 3. Neither the name of Apple
|
15
|
+
# 3. Neither the name of Apple Inc. ("Apple") nor the names of
|
16
16
|
# its contributors may be used to endorse or promote products derived
|
17
17
|
# from this software without specific prior written permission.
|
18
18
|
#
|
@@ -30,6 +30,7 @@
|
|
30
30
|
|
31
31
|
require 'rbosa'
|
32
32
|
require 'tmpdir'
|
33
|
+
require 'rbconfig'
|
33
34
|
|
34
35
|
def usage
|
35
36
|
STDERR.puts <<-EOS
|
@@ -55,20 +56,22 @@ end
|
|
55
56
|
|
56
57
|
usage unless ARGV.length >= 2
|
57
58
|
|
58
|
-
|
59
|
+
key = case ARGV.first
|
59
60
|
when '--name'
|
60
|
-
:
|
61
|
+
:name
|
61
62
|
when '--path'
|
62
|
-
:
|
63
|
+
:path
|
63
64
|
when '--bundle_id'
|
64
|
-
:
|
65
|
+
:bundle_id
|
65
66
|
when '--signature'
|
66
|
-
:
|
67
|
+
:signature
|
67
68
|
else
|
68
69
|
usage
|
69
70
|
end
|
70
71
|
|
71
|
-
|
72
|
+
DOC_NOT_AVAILABLE = 'Documentation not available.'
|
73
|
+
|
74
|
+
app = OSA.app(key => ARGV[1])
|
72
75
|
mod = OSA.const_get(app.class.name.scan(/^OSA::(.+)::Application$/).to_s)
|
73
76
|
fake_ruby_src = mod.constants.map do |const_name|
|
74
77
|
obj = mod.const_get(const_name)
|
@@ -76,20 +79,37 @@ fake_ruby_src = mod.constants.map do |const_name|
|
|
76
79
|
when Class
|
77
80
|
# Class.
|
78
81
|
methods_desc = obj.const_get('METHODS_DESCRIPTION').map do |method|
|
79
|
-
args_doc, args_def = '', ''
|
82
|
+
args_doc, args_def, args_def_opt = '', '', ''
|
80
83
|
if method.args and !method.args.empty?
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
84
|
+
args_doc_ary, args_def_ary, args_def_opt_ary = [], [], []
|
85
|
+
method.args.each do |x|
|
86
|
+
arg = x.name
|
87
|
+
desc = x.description
|
88
|
+
desc = DOC_NOT_AVAILABLE if desc.empty?
|
89
|
+
args_doc_ary << " # #{arg}::\n # #{desc}" + (x.optional? ? ' Optional. Can be passed as a Hash key/value.' : '')
|
90
|
+
if x.optional?
|
91
|
+
args_def_ary << x.name + '=nil'
|
92
|
+
args_def_opt_ary << ':' + x.name + ' => nil'
|
93
|
+
else
|
94
|
+
args_def_ary << x.name
|
95
|
+
args_def_opt_ary << x.name
|
96
|
+
end
|
97
|
+
end
|
98
|
+
args_doc = args_doc_ary.join("\n")
|
99
|
+
args_def = '(' + args_def_ary.join(', ') + ')'
|
100
|
+
args_def_opt = '(' + args_def_opt_ary.join(', ') + ')'
|
87
101
|
end
|
88
102
|
if method.result
|
89
103
|
args_doc << "\n" unless args_doc.empty?
|
90
|
-
|
104
|
+
desc = method.result.description
|
105
|
+
desc = DOC_NOT_AVAILABLE if desc.empty?
|
106
|
+
args_doc << " # Returns::\n # #{desc}\n"
|
91
107
|
end
|
92
108
|
<<EOS
|
109
|
+
# call-seq:
|
110
|
+
# #{method.name + args_def}
|
111
|
+
# #{args_def_opt != args_def ? method.name + args_def_opt : ''}
|
112
|
+
#
|
93
113
|
# #{method.description}
|
94
114
|
#{args_doc}
|
95
115
|
def #{method.name}#{args_def}; end
|
@@ -134,9 +154,18 @@ module OSA; end
|
|
134
154
|
module #{mod.name}; end
|
135
155
|
EOS
|
136
156
|
|
157
|
+
rdoc_flags = ''
|
158
|
+
template = File.join(Config.datadir('rubyosa'), 'rdoc_html.rb')
|
159
|
+
if File.exists?(template)
|
160
|
+
rdoc_flags << " --template '#{template}' "
|
161
|
+
end
|
162
|
+
rdoc_flags << " --title '#{app.name} RubyOSA API' "
|
163
|
+
rdoc_flags << ' --main OSA '
|
164
|
+
rdoc_flags << ARGV[2..-1].join(' ')
|
165
|
+
|
137
166
|
path = unique_tmp_path(app.name, '.rb')
|
138
167
|
File.open(path, 'w') { |io| io.puts fake_ruby_src }
|
139
|
-
line = "rdoc #{
|
168
|
+
line = "rdoc #{rdoc_flags} \"#{path}\""
|
140
169
|
unless system(line)
|
141
170
|
STDERR.puts "Error when executing `#{line}' : #{$?}"
|
142
171
|
exit 1
|
data/extconf.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2006, Apple
|
1
|
+
# Copyright (c) 2006-2007, Apple Inc. All rights reserved.
|
2
2
|
#
|
3
3
|
# Redistribution and use in source and binary forms, with or without
|
4
4
|
# modification, are permitted provided that the following conditions
|
@@ -8,7 +8,7 @@
|
|
8
8
|
# 2. Redistributions in binary form must reproduce the above copyright
|
9
9
|
# notice, this list of conditions and the following disclaimer in the
|
10
10
|
# documentation and/or other materials provided with the distribution.
|
11
|
-
# 3. Neither the name of Apple
|
11
|
+
# 3. Neither the name of Apple Inc. ("Apple") nor the names of
|
12
12
|
# its contributors may be used to endorse or promote products derived
|
13
13
|
# from this software without specific prior written permission.
|
14
14
|
#
|
@@ -50,4 +50,10 @@ new_filename_prefix = 'osx_'
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
+
# Generate the Makefile
|
53
54
|
create_makefile('osa', 'src')
|
55
|
+
|
56
|
+
# Tweak the Makefile to add an extra install task.
|
57
|
+
text = File.read('Makefile')
|
58
|
+
text << "\n\ninstall-extras: post-install.rb\n\t@$(RUBY) post-install.rb\n\n"
|
59
|
+
File.open('Makefile', 'w') { |io| io.write(text) }
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Print all the contacts your Address Book contains.
|
2
|
+
# Thanks to Stefan Saasen.
|
3
|
+
|
4
|
+
begin require 'rubygems'; rescue LoadError; end
|
5
|
+
require 'rbosa'
|
6
|
+
|
7
|
+
OSA.utf8_strings = true
|
8
|
+
|
9
|
+
def print_person(pe)
|
10
|
+
puts pe.name
|
11
|
+
unless pe.emails.size < 1
|
12
|
+
puts "\tE-Mail: " + pe.emails.map { |email|
|
13
|
+
email.value
|
14
|
+
}.join(', ')
|
15
|
+
end
|
16
|
+
formatted_addresses = pe.addresses.map { |a|
|
17
|
+
# Some malformed addresses can't be formatted and the address book
|
18
|
+
# will therefore return an application-level error, that we handle there.
|
19
|
+
('(' + a.label + ') ' + a.formatted_address rescue nil)
|
20
|
+
}.compact.map { |a|
|
21
|
+
"\t\t" + a.gsub(/\n/, ' ').strip.squeeze(' ')
|
22
|
+
}
|
23
|
+
unless formatted_addresses.size < 1
|
24
|
+
puts "\tAddresses:\n" + formatted_addresses.join("\n")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
ab = OSA.app('Address Book')
|
29
|
+
ab.people.each do |pe|
|
30
|
+
print_person pe
|
31
|
+
end
|
File without changes
|
File without changes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Retrieve and show every selected message content in Mail into new TextEdit documents.
|
2
|
+
|
3
|
+
begin require 'rubygems'; rescue LoadError; end
|
4
|
+
require 'rbosa'
|
5
|
+
|
6
|
+
OSA.utf8_strings = true
|
7
|
+
textedit = OSA.app('TextEdit')
|
8
|
+
mailApp = OSA.app('Mail')
|
9
|
+
viewers = mailApp.message_viewers
|
10
|
+
viewers.each do |viewer|
|
11
|
+
viewer.selected_messages.each do |message|
|
12
|
+
textedit.make(OSA::TextEdit::Document).text = message.content
|
13
|
+
end
|
14
|
+
end
|
File without changes
|
@@ -6,7 +6,7 @@ require 'rbosa'
|
|
6
6
|
textedit = OSA.app('TextEdit')
|
7
7
|
|
8
8
|
# Complex way.
|
9
|
-
textedit.make(OSA::TextEdit::Document,
|
9
|
+
textedit.make(OSA::TextEdit::Document, :with_properties => {:text => 'Hello World #1'})
|
10
10
|
|
11
11
|
# Easier way.
|
12
12
|
textedit.make(OSA::TextEdit::Document).text = 'Hello World #2'
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# For each selected track in iTunes, retrieve the genre from Last.fm and accordingly tag the track.
|
2
|
+
|
3
|
+
begin require 'rubygems'; rescue LoadError; end
|
4
|
+
require 'rbosa'
|
5
|
+
require 'net/http'
|
6
|
+
require 'cgi'
|
7
|
+
require 'rexml/document'
|
8
|
+
include REXML
|
9
|
+
|
10
|
+
itunes = OSA.app('iTunes')
|
11
|
+
selection = itunes.selection.get
|
12
|
+
if selection.empty?
|
13
|
+
$stderr.puts "Please select some tracks."
|
14
|
+
exit 1
|
15
|
+
end
|
16
|
+
selection.each do |track|
|
17
|
+
feed = "http://ws.audioscrobbler.com/1.0/artist/#{CGI::escape(track.artist)}/toptags.xml"
|
18
|
+
doc = Document.new(Net::HTTP.get(URI(feed)))
|
19
|
+
track.genre = doc.root[1][1].text
|
20
|
+
end
|
@@ -18,20 +18,20 @@ end
|
|
18
18
|
|
19
19
|
usage unless ARGV.length == 2
|
20
20
|
|
21
|
-
|
21
|
+
key = case ARGV.first
|
22
22
|
when '--name'
|
23
|
-
:
|
23
|
+
:name
|
24
24
|
when '--path'
|
25
|
-
:
|
25
|
+
:path
|
26
26
|
when '--bundle_id'
|
27
|
-
:
|
27
|
+
:bundle_id
|
28
28
|
when '--signature'
|
29
|
-
:
|
29
|
+
:signature
|
30
30
|
else
|
31
31
|
usage
|
32
32
|
end
|
33
33
|
|
34
|
-
app = OSA.
|
34
|
+
app = OSA.app(key => ARGV.last)
|
35
35
|
doc = REXML::Document.new(app.sdef)
|
36
36
|
doc.write(STDOUT, 0)
|
37
37
|
puts ""
|
data/src/lib/rbosa.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2006, Apple
|
1
|
+
# Copyright (c) 2006-2007, Apple Inc. All rights reserved.
|
2
2
|
#
|
3
3
|
# Redistribution and use in source and binary forms, with or without
|
4
4
|
# modification, are permitted provided that the following conditions
|
@@ -8,7 +8,7 @@
|
|
8
8
|
# 2. Redistributions in binary form must reproduce the above copyright
|
9
9
|
# notice, this list of conditions and the following disclaimer in the
|
10
10
|
# documentation and/or other materials provided with the distribution.
|
11
|
-
# 3. Neither the name of Apple
|
11
|
+
# 3. Neither the name of Apple Inc. ("Apple") nor the names of
|
12
12
|
# its contributors may be used to endorse or promote products derived
|
13
13
|
# from this software without specific prior written permission.
|
14
14
|
#
|
@@ -116,8 +116,8 @@ class OSA::Element
|
|
116
116
|
end
|
117
117
|
|
118
118
|
def self.from_rbobj(requested_type, value, enum_group_codes)
|
119
|
-
|
120
|
-
|
119
|
+
obj = OSA.convert_to_osa(requested_type, value, enum_group_codes)
|
120
|
+
obj.is_a?(OSA::Element) ? obj : self.__new__(*obj)
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
@@ -129,16 +129,37 @@ class OSA::ElementList
|
|
129
129
|
end
|
130
130
|
|
131
131
|
class OSA::ElementRecord
|
132
|
+
def self.from_hash(hash)
|
133
|
+
value = {}
|
134
|
+
hash.each do |code, val|
|
135
|
+
key = OSA.sym_to_code(code)
|
136
|
+
if key.nil?
|
137
|
+
raise ArgumentError, "invalid key `#{code}'" if code.to_s.length != 4
|
138
|
+
key = code
|
139
|
+
end
|
140
|
+
value[key] = OSA::Element.from_rbobj(nil, val, nil)
|
141
|
+
end
|
142
|
+
OSA::ElementRecord.__new__(value)
|
143
|
+
end
|
144
|
+
|
132
145
|
def to_hash
|
133
146
|
h = {}
|
134
|
-
self.to_a.each
|
147
|
+
self.to_a.each do |code, val|
|
148
|
+
key = (OSA.code_to_sym(code) or code)
|
149
|
+
h[key] = val.to_rbobj
|
150
|
+
end
|
135
151
|
return h
|
136
152
|
end
|
137
153
|
end
|
138
154
|
|
139
155
|
module OSA::ObjectSpecifier
|
140
156
|
def get
|
141
|
-
@app.__send_event__('core', 'getd', [['----', self]], true).to_rbobj
|
157
|
+
new_obj = @app.__send_event__('core', 'getd', [['----', self]], true).to_rbobj
|
158
|
+
if !new_obj.is_a?(self.class) and new_obj.is_a?(OSA::Element) and self.respond_to?(:properties) and (klass = self.properties[:class])
|
159
|
+
klass.__duplicate__(new_obj)
|
160
|
+
else
|
161
|
+
new_obj
|
162
|
+
end
|
142
163
|
end
|
143
164
|
end
|
144
165
|
|
@@ -150,7 +171,7 @@ class OSA::ObjectSpecifierList
|
|
150
171
|
end
|
151
172
|
|
152
173
|
def length
|
153
|
-
@
|
174
|
+
@app.__send_event__(
|
154
175
|
'core', 'cnte',
|
155
176
|
[['----', @container], ['kocl', OSA::Element.__new__('type', @desired_class::CODE.to_4cc)]],
|
156
177
|
true).to_rbobj
|
@@ -186,6 +207,10 @@ class OSA::ObjectSpecifierList
|
|
186
207
|
and (0..other.length).all? { |i| other[i] == self[i] }
|
187
208
|
end
|
188
209
|
|
210
|
+
def inspect
|
211
|
+
super.scan(/^([^ ]+)/).to_s << " desired_class=#{@desired_class}>"
|
212
|
+
end
|
213
|
+
|
189
214
|
#######
|
190
215
|
private
|
191
216
|
#######
|
@@ -196,25 +221,87 @@ class OSA::ObjectSpecifierList
|
|
196
221
|
end
|
197
222
|
end
|
198
223
|
|
224
|
+
module OSA::EventDispatcher
|
225
|
+
|
226
|
+
SCRIPTING_ADDITIONS_DIR = [
|
227
|
+
'/System/Library/ScriptingAdditions',
|
228
|
+
'/Library/ScriptingAdditions'
|
229
|
+
]
|
230
|
+
if home = ENV['HOME']
|
231
|
+
SCRIPTING_ADDITIONS_DIR << File.join(home, '/Library/ScriptingAdditions')
|
232
|
+
end
|
233
|
+
|
234
|
+
def merge(args)
|
235
|
+
args = { :name => args } if args.is_a?(String)
|
236
|
+
by_name = args[:name]
|
237
|
+
begin
|
238
|
+
name, target, sdef = OSA.__scripting_info__(args)
|
239
|
+
rescue RuntimeError => excp
|
240
|
+
# If an sdef bundle can't be find by name, let's be clever and look in the ScriptingAdditions locations.
|
241
|
+
if by_name
|
242
|
+
args = SCRIPTING_ADDITIONS_DIR.each do |dir|
|
243
|
+
path = ['.app', '.osax'].map { |e| File.join(dir, by_name + e) }.find { |p| File.exists?(p) }
|
244
|
+
if path
|
245
|
+
break { :path => path }
|
246
|
+
end
|
247
|
+
end
|
248
|
+
if args.is_a?(Hash)
|
249
|
+
by_name = nil
|
250
|
+
retry
|
251
|
+
end
|
252
|
+
end
|
253
|
+
raise excp
|
254
|
+
end
|
255
|
+
app_module_name = self.class.name.scan(/^OSA::(.+)::.+$/).flatten.first
|
256
|
+
app_module = OSA.const_get(app_module_name)
|
257
|
+
OSA.__load_sdef__(sdef, target, app_module, true, self.class)
|
258
|
+
(self.__send_event__('ascr', 'gdut', [], true) rescue nil) # Don't ask me why...
|
259
|
+
return self
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
199
263
|
module OSA
|
200
264
|
def self.app_with_name(name)
|
201
|
-
|
265
|
+
STDERR.puts "OSA.app_with_name() has been deprecated and its usage is now discouraged. Please use OSA.app('name') instead."
|
266
|
+
self.__app__(*OSA.__scripting_info__(:name => name))
|
202
267
|
end
|
203
268
|
|
204
269
|
def self.app_with_path(path)
|
205
|
-
|
270
|
+
STDERR.puts "OSA.app_by_path() has been deprecated and its usage is now discouraged. Please use OSA.app(:path => 'path') instead."
|
271
|
+
self.__app__(*OSA.__scripting_info__(:path => path))
|
206
272
|
end
|
207
273
|
|
208
|
-
def self.
|
209
|
-
|
274
|
+
def self.app_by_bundle_id(bundle_id)
|
275
|
+
STDERR.puts "OSA.app_by_bundle_id() has been deprecated and its usage is now discouraged. Please use OSA.app(:bundle_id => 'bundle_id') instead."
|
276
|
+
self.__app__(*OSA.__scripting_info__(:bundle_id => bundle_id))
|
210
277
|
end
|
211
278
|
|
212
|
-
def self.
|
213
|
-
|
279
|
+
def self.app_by_signature(signature)
|
280
|
+
STDERR.puts "OSA.app_by_signature() has been deprecated and its usage is now discouraged. Please use OSA.app(:signature => 'signature') instead."
|
281
|
+
self.__app__(*OSA.__scripting_info__(:signature => signature))
|
214
282
|
end
|
215
283
|
|
216
|
-
def self.app(
|
217
|
-
|
284
|
+
def self.app(*args)
|
285
|
+
if args.size == 2
|
286
|
+
if args.first.is_a?(String) and args.last.is_a?(Hash)
|
287
|
+
hash = args.last
|
288
|
+
if hash.has_key?(:name)
|
289
|
+
warn "Given Hash argument already has a :name key, ignoring the first String argument `#{args.first}'"
|
290
|
+
else
|
291
|
+
hash[:name] = args.first
|
292
|
+
end
|
293
|
+
args = hash
|
294
|
+
else
|
295
|
+
raise ArgumentError, "when called with 2 arguments, the first is supposed to be a String and the second a Hash"
|
296
|
+
end
|
297
|
+
else
|
298
|
+
if args.size != 1
|
299
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for at least 1)"
|
300
|
+
end
|
301
|
+
args = args.first
|
302
|
+
end
|
303
|
+
args = { :name => args } if args.is_a?(String)
|
304
|
+
self.__app__(*OSA.__scripting_info__(args))
|
218
305
|
end
|
219
306
|
|
220
307
|
@conversions_to_ruby = {}
|
@@ -253,47 +340,49 @@ module OSA
|
|
253
340
|
end
|
254
341
|
end
|
255
342
|
|
256
|
-
def self.
|
257
|
-
if
|
258
|
-
case value
|
259
|
-
when OSA::Element
|
260
|
-
return value
|
261
|
-
when String
|
262
|
-
requested_type = 'text'
|
263
|
-
when Array
|
264
|
-
requested_type = 'list'
|
265
|
-
when Hash
|
266
|
-
requested_type = 'record'
|
267
|
-
when Integer
|
268
|
-
requested_type = 'integer'
|
269
|
-
else
|
270
|
-
STDERR.puts "can't determine OSA type for #{value}" if $VERBOSE
|
271
|
-
['null', nil]
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
343
|
+
def self.__convert_to_osa__(requested_type, value, enum_group_codes=nil)
|
344
|
+
return value if value.is_a?(OSA::Element)
|
275
345
|
if conversion = @conversions_to_osa[requested_type]
|
276
346
|
args = [value, requested_type]
|
277
347
|
conversion.call(*args[0..(conversion.arity - 1)])
|
278
348
|
elsif enum_group_codes and enum_group_codes.include?(requested_type)
|
279
349
|
['enum', value.code.to_4cc]
|
280
350
|
elsif md = /^list_of_(.+)$/.match(requested_type)
|
281
|
-
ary = value.to_a.map
|
351
|
+
ary = value.to_a.map do |elem|
|
352
|
+
obj = convert_to_osa(md[1], elem, enum_group_codes)
|
353
|
+
obj.is_a?(OSA::Element) ? obj : OSA::Element.__new__(*obj)
|
354
|
+
end
|
282
355
|
ElementList.__new__(ary)
|
283
356
|
else
|
284
357
|
STDERR.puts "unrecognized type #{requested_type}" if $VERBOSE
|
285
358
|
['null', nil]
|
286
359
|
end
|
287
360
|
end
|
361
|
+
|
362
|
+
def self.convert_to_osa(requested_type, value, enum_group_codes=nil)
|
363
|
+
ary = __convert_to_osa__(requested_type, value, enum_group_codes)
|
364
|
+
if ary == ['null', nil]
|
365
|
+
new_type = case value
|
366
|
+
when String then 'text'
|
367
|
+
when Array then 'list'
|
368
|
+
when Hash then 'record'
|
369
|
+
when Integer then 'integer'
|
370
|
+
end
|
371
|
+
if new_type
|
372
|
+
ary = __convert_to_osa__(new_type, value, enum_group_codes)
|
373
|
+
end
|
374
|
+
end
|
375
|
+
ary
|
376
|
+
end
|
288
377
|
|
289
378
|
def self.set_params(hash)
|
290
379
|
previous_values = {}
|
291
380
|
hash.each do |key, val|
|
292
|
-
|
293
|
-
previous_val = self.instance_variable_get(ivar_key)
|
294
|
-
if previous_val.nil?
|
381
|
+
unless OSA.respond_to?(key)
|
295
382
|
raise ArgumentError, "Invalid key value (no parameter named #{key} was found)"
|
296
383
|
end
|
384
|
+
ivar_key = '@' + key.to_s
|
385
|
+
previous_val = self.instance_variable_get(ivar_key)
|
297
386
|
previous_values[ivar_key] = previous_val;
|
298
387
|
self.instance_variable_set(ivar_key, hash[key])
|
299
388
|
end
|
@@ -310,9 +399,13 @@ module OSA
|
|
310
399
|
|
311
400
|
class DocItem
|
312
401
|
attr_reader :name, :description
|
313
|
-
def initialize(name, description)
|
402
|
+
def initialize(name, description, optional=false)
|
314
403
|
@name = name
|
315
404
|
@description = description
|
405
|
+
@optional = optional
|
406
|
+
end
|
407
|
+
def optional?
|
408
|
+
@optional
|
316
409
|
end
|
317
410
|
end
|
318
411
|
|
@@ -328,10 +421,20 @@ module OSA
|
|
328
421
|
end
|
329
422
|
end
|
330
423
|
|
331
|
-
def self.__app__(name,
|
424
|
+
def self.__app__(name, target, sdef)
|
332
425
|
@apps ||= {}
|
333
|
-
app = @apps[
|
426
|
+
app = @apps[target]
|
334
427
|
return app if app
|
428
|
+
|
429
|
+
# Creates a module for this app, we will define the scripting interface within it.
|
430
|
+
app_module = Module.new
|
431
|
+
self.const_set(rubyfy_constant_string(name), app_module)
|
432
|
+
|
433
|
+
@apps[target] = __load_sdef__(sdef, target, app_module)
|
434
|
+
end
|
435
|
+
|
436
|
+
def self.__load_sdef__(sdef, target, app_module, merge_only=false, app_class=nil)
|
437
|
+
# Load the sdef.
|
335
438
|
doc = if USE_LIBXML
|
336
439
|
parser = XML::Parser.new
|
337
440
|
parser.string = sdef
|
@@ -340,10 +443,6 @@ module OSA
|
|
340
443
|
REXML::Document.new(sdef)
|
341
444
|
end
|
342
445
|
|
343
|
-
# Creates a module for this app, we will define the scripting interface within it.
|
344
|
-
app_module = Module.new
|
345
|
-
self.const_set(rubyfy_constant_string(name), app_module)
|
346
|
-
|
347
446
|
# Retrieves and creates enumerations.
|
348
447
|
enum_group_codes = {}
|
349
448
|
doc.find('/dictionary/suite/enumeration').each do |element|
|
@@ -367,14 +466,15 @@ module OSA
|
|
367
466
|
documentation << DocItem.new(enum_name, englishify_sentence(element['description']))
|
368
467
|
end
|
369
468
|
|
370
|
-
app_module.const_set(enum_module_name, enum_module)
|
469
|
+
app_module.const_set(enum_module_name, enum_module) unless app_module.const_defined?(enum_module_name)
|
371
470
|
end
|
372
471
|
|
373
472
|
# Retrieves and creates classes.
|
374
473
|
classes = {}
|
375
474
|
class_elements = {}
|
376
475
|
doc.find('/dictionary/suite/class').each do |element|
|
377
|
-
(
|
476
|
+
key = (element['id'] or element['name'])
|
477
|
+
(class_elements[key] ||= []) << element
|
378
478
|
end
|
379
479
|
class_elements.values.flatten.each do |element|
|
380
480
|
klass = add_class_from_xml_element(element, class_elements, classes, app_module)
|
@@ -396,7 +496,7 @@ module OSA
|
|
396
496
|
# Add basic properties that might be missing to the Item class (if any).
|
397
497
|
props = {}
|
398
498
|
element.find('property').each do |x|
|
399
|
-
props[x['name']] = [x['code'], x
|
499
|
+
props[x['name']] = [x['code'], type_of_parameter(x), x['access'], x['description']]
|
400
500
|
end
|
401
501
|
if klass.name[-6..-1] == '::Item'
|
402
502
|
unless props.has_key?('id')
|
@@ -422,60 +522,54 @@ module OSA
|
|
422
522
|
# Implicit 'get' if the property class is primitive (not defined in the sdef),
|
423
523
|
# otherwise just return an object specifier.
|
424
524
|
method_name = rubyfy_method(name, klass, type)
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
end
|
433
|
-
EOC
|
525
|
+
method_proc = if pklass.nil?
|
526
|
+
proc do
|
527
|
+
@app.__send_event__('core', 'getd',
|
528
|
+
[['----', Element.__new_object_specifier__('prop', @app == self ? Element.__new__('null', nil) : self,
|
529
|
+
'prop', Element.__new__('type', code.to_4cc))]],
|
530
|
+
true).to_rbobj
|
531
|
+
end
|
434
532
|
else
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
end
|
446
|
-
EOC
|
533
|
+
proc do
|
534
|
+
o = pklass.__new_object_specifier__('prop', @app == self ? Element.__new__('null', nil) : self,
|
535
|
+
'prop', Element.__new__('type', code.to_4cc))
|
536
|
+
unless OSA.lazy_events?
|
537
|
+
@app.__send_event__('core', 'getd', [['----', o]], true).to_rbobj
|
538
|
+
else
|
539
|
+
o.instance_variable_set(:@app, @app)
|
540
|
+
o.extend(OSA::ObjectSpecifier)
|
541
|
+
end
|
542
|
+
end
|
447
543
|
end
|
448
544
|
|
449
|
-
klass.class_eval(
|
545
|
+
klass.class_eval { define_method(method_name, method_proc) }
|
450
546
|
ptypedoc = if pklass.nil?
|
451
|
-
|
452
|
-
"a #{mod} enumeration"
|
453
|
-
else
|
454
|
-
type
|
455
|
-
end
|
547
|
+
type_doc(type, enum_group_codes, app_module)
|
456
548
|
else
|
457
549
|
"a #{pklass} object"
|
458
550
|
end
|
459
|
-
|
460
|
-
|
551
|
+
if description
|
552
|
+
description[0] = description[0].chr.downcase
|
553
|
+
description = '-- ' << description
|
554
|
+
end
|
555
|
+
methods_doc << DocMethod.new(method_name, englishify_sentence("Gets the #{name} property #{description}"), DocItem.new('result', englishify_sentence("the property value, as #{ptypedoc}")), nil)
|
461
556
|
|
462
557
|
# For the setter, always send an event.
|
463
558
|
if setter
|
464
559
|
method_name = rubyfy_method(name, klass, type, true)
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
klass.class_eval(method_code)
|
477
|
-
methods_doc << DocMethod.new(method_name, englishify_sentence("Sets the #{name} property -- #{description}"), nil, [DocItem.new('val', englishify_sentence("the value to be set, as #{ptypedoc}"))])
|
560
|
+
method_proc = proc do |val|
|
561
|
+
@app.__send_event__('core', 'setd',
|
562
|
+
[['----', Element.__new_object_specifier__('prop', @app == self ? Element.__new__('null', nil) : self,
|
563
|
+
'prop', Element.__new__('type', code.to_4cc))],
|
564
|
+
['data', val.is_a?(OSA::Element) ? val : Element.from_rbobj(type, val, enum_group_codes.keys)]],
|
565
|
+
true)
|
566
|
+
return nil
|
567
|
+
end
|
568
|
+
klass.class_eval { define_method(method_name, method_proc) }
|
569
|
+
methods_doc << DocMethod.new(method_name, englishify_sentence("Sets the #{name} property #{description}"), nil, [DocItem.new('val', englishify_sentence("the value to be set, as #{ptypedoc}"))])
|
478
570
|
end
|
571
|
+
|
572
|
+
OSA.add_property(name.intern, code)
|
479
573
|
end
|
480
574
|
|
481
575
|
# Creates elements.
|
@@ -496,39 +590,49 @@ EOC
|
|
496
590
|
end
|
497
591
|
|
498
592
|
method_name = rubyfy_method(eklass::PLURAL, klass)
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
EOC
|
512
|
-
|
513
|
-
klass.class_eval(method_code)
|
593
|
+
method_proc = proc do
|
594
|
+
unless OSA.lazy_events?
|
595
|
+
@app.__send_event__('core', 'getd',
|
596
|
+
[['----', Element.__new_object_specifier__(
|
597
|
+
eklass::CODE.to_4cc, @app == self ? Element.__new__('null', nil) : self,
|
598
|
+
'indx', Element.__new__('abso', 'all '.to_4cc))]],
|
599
|
+
true).to_rbobj
|
600
|
+
else
|
601
|
+
ObjectSpecifierList.new(@app, eklass, @app == self ? Element.__new__('null', nil) : self)
|
602
|
+
end
|
603
|
+
end
|
604
|
+
klass.class_eval { define_method(method_name, method_proc) }
|
514
605
|
methods_doc << DocMethod.new(method_name, englishify_sentence("Gets the #{eklass::PLURAL} associated with this object"), DocItem.new('result', englishify_sentence("an Array of #{eklass} objects")), nil)
|
515
606
|
end
|
516
607
|
end
|
517
608
|
|
518
|
-
|
519
|
-
|
520
|
-
|
609
|
+
unless merge_only
|
610
|
+
# Having an 'application' class is required.
|
611
|
+
app_class = classes['application']
|
612
|
+
raise "No application class defined." if app_class.nil?
|
613
|
+
all_classes_but_app = classes.values.reject { |x| x.ancestors.include?(OSA::EventDispatcher) }
|
614
|
+
else
|
615
|
+
all_classes_but_app = classes.values
|
616
|
+
end
|
521
617
|
|
522
618
|
# Maps commands to the right classes.
|
523
|
-
all_classes_but_app = classes.values.reject { |x| x.ancestors.include?(OSA::EventDispatcher) }
|
524
619
|
doc.find('/dictionary/suite/command').each do |element|
|
525
620
|
name = element['name']
|
526
621
|
next if /NOT AVAILABLE/.match(name) # Finder's sdef (Tiger) names some commands with this 'tag'.
|
527
622
|
description = element['description']
|
528
|
-
code = element['code']
|
529
623
|
direct_parameter = element.find_first('direct-parameter')
|
530
624
|
result = element.find_first('result')
|
625
|
+
has_result = result != nil
|
531
626
|
|
627
|
+
code = element['code']
|
628
|
+
begin
|
629
|
+
code = Iconv.iconv('MACROMAN', 'UTF-8', code).to_s
|
630
|
+
rescue Iconv::IllegalSequence
|
631
|
+
# We can't do more...
|
632
|
+
STDERR.puts "unrecognized command code encoding '#{code}', skipping..." if $DEBUG
|
633
|
+
next
|
634
|
+
end
|
635
|
+
|
532
636
|
classes_to_define = []
|
533
637
|
forget_direct_parameter = true
|
534
638
|
direct_parameter_optional = false
|
@@ -567,53 +671,79 @@ EOC
|
|
567
671
|
end
|
568
672
|
|
569
673
|
params = []
|
674
|
+
params_doc = []
|
570
675
|
unless direct_parameter.nil?
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
676
|
+
pdesc = direct_parameter['description']
|
677
|
+
params << [
|
678
|
+
'direct',
|
679
|
+
'----',
|
680
|
+
direct_parameter_optional,
|
681
|
+
type_of_parameter(direct_parameter)
|
682
|
+
]
|
683
|
+
unless forget_direct_parameter
|
684
|
+
params_doc << DocItem.new('direct', englishify_sentence(pdesc))
|
685
|
+
end
|
576
686
|
end
|
577
687
|
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
688
|
+
element.find('parameter').to_a.each do |element|
|
689
|
+
poptional = parameter_optional?(element)
|
690
|
+
params << [
|
691
|
+
rubyfy_string(element['name']),
|
692
|
+
element['code'],
|
693
|
+
poptional,
|
694
|
+
type_of_parameter(element)
|
695
|
+
]
|
696
|
+
params_doc << DocItem.new(rubyfy_string(element['name'], true), englishify_sentence(element['description']), poptional)
|
697
|
+
end
|
698
|
+
|
699
|
+
method_proc = proc do |*args_ary|
|
700
|
+
args = []
|
701
|
+
min_argc = i = 0
|
702
|
+
already_has_optional_args = false # Once an argument is optional, all following arguments should be optional.
|
703
|
+
optional_hash = nil
|
704
|
+
params.each do |pname, pcode, optional, ptype|
|
705
|
+
self_direct = (pcode == '----' and forget_direct_parameter)
|
706
|
+
if already_has_optional_args or (optional and !self_direct)
|
707
|
+
already_has_optional_args = true
|
708
|
+
else
|
709
|
+
if args_ary.size < i
|
710
|
+
raise ArgumentError, "wrong number of arguments (#{args_ary.size} for #{i})"
|
711
|
+
end
|
712
|
+
end
|
713
|
+
val = if self_direct
|
714
|
+
self.is_a?(OSA::EventDispatcher) ? [] : ['----', self]
|
715
|
+
else
|
716
|
+
arg = args_ary[i]
|
717
|
+
min_argc += 1 unless already_has_optional_args
|
718
|
+
i += 1
|
719
|
+
if arg.is_a?(Hash) and already_has_optional_args and i >= args_ary.size and min_argc + 1 == i
|
720
|
+
optional_hash = arg
|
721
|
+
end
|
722
|
+
if optional_hash
|
723
|
+
arg = optional_hash.delete(pname.intern)
|
724
|
+
end
|
725
|
+
if arg.nil?
|
726
|
+
if already_has_optional_args
|
727
|
+
[]
|
728
|
+
end
|
729
|
+
else
|
730
|
+
[pcode, arg.is_a?(OSA::Element) ? arg : OSA::Element.from_rbobj(ptype, arg, enum_group_codes.keys)]
|
731
|
+
end
|
732
|
+
end
|
733
|
+
args << val
|
595
734
|
end
|
596
|
-
if
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
unless self_direct
|
602
|
-
p_dec << decl
|
603
|
-
p_args_doc << DocItem.new(decl, englishify_sentence(pdesc))
|
735
|
+
if args_ary.size > params.size or args_ary.size < min_argc
|
736
|
+
raise ArgumentError, "wrong number of arguments (#{args_ary.size} for #{min_argc})"
|
737
|
+
end
|
738
|
+
if optional_hash and !optional_hash.empty?
|
739
|
+
raise ArgumentError, "inappropriate optional argument(s): #{optional_hash.keys.join(', ')}"
|
604
740
|
end
|
605
|
-
|
741
|
+
wait_reply = (OSA.wait_reply != nil ? OSA.wait_reply : (has_result or @app.remote?))
|
742
|
+
ret = @app.__send_event__(code[0..3], code[4..-1], args, wait_reply)
|
743
|
+
wait_reply ? ret.to_rbobj : ret
|
606
744
|
end
|
607
745
|
|
608
|
-
|
609
|
-
|
610
|
-
method_code = <<EOC
|
611
|
-
def %METHOD_NAME%(#{p_dec.join(', ')})
|
612
|
-
@app.__send_event__('#{code[0..3]}', '#{code[4..-1]}', [#{p_def.join(', ')}], #{result != nil})#{result != nil ? '.to_rbobj' : ''}
|
613
|
-
end
|
614
|
-
EOC
|
615
|
-
|
616
|
-
if result.nil?
|
746
|
+
unless has_result
|
617
747
|
result_type = result_doc = nil
|
618
748
|
else
|
619
749
|
result_type = type_of_parameter(result)
|
@@ -623,22 +753,27 @@ EOC
|
|
623
753
|
|
624
754
|
classes_to_define.each do |klass|
|
625
755
|
method_name = rubyfy_method(name, klass, result_type)
|
626
|
-
|
627
|
-
klass.class_eval(code)
|
756
|
+
klass.class_eval { define_method(method_name, method_proc) }
|
628
757
|
methods_doc = klass.const_get(:METHODS_DESCRIPTION)
|
629
|
-
methods_doc << DocMethod.new(method_name, englishify_sentence(description), result_doc,
|
758
|
+
methods_doc << DocMethod.new(method_name, englishify_sentence(description), result_doc, params_doc)
|
630
759
|
end
|
631
760
|
end
|
632
761
|
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
762
|
+
unless merge_only
|
763
|
+
# Returns an application instance, that's all folks!
|
764
|
+
hash = {}
|
765
|
+
classes.each_value { |klass| hash[klass::CODE] = klass }
|
766
|
+
app_class.class_eval do
|
767
|
+
attr_reader :sdef
|
768
|
+
define_method(:remote?) { @is_remote == true }
|
769
|
+
end
|
770
|
+
is_remote = target.length > 4
|
771
|
+
app = is_remote ? app_class.__new__('aprl', target) : app_class.__new__('sign', target.to_4cc)
|
772
|
+
app.instance_variable_set(:@is_remote, is_remote)
|
773
|
+
app.instance_variable_set(:@sdef, sdef)
|
774
|
+
app.instance_variable_set(:@classes, hash)
|
775
|
+
app.extend OSA::EventDispatcher
|
776
|
+
end
|
642
777
|
end
|
643
778
|
|
644
779
|
def self.parameter_optional?(element)
|
@@ -647,7 +782,8 @@ EOC
|
|
647
782
|
|
648
783
|
def self.add_class_from_xml_element(element, class_elements, repository, app_module)
|
649
784
|
real_name = element['name']
|
650
|
-
|
785
|
+
key = (element['id'] or real_name)
|
786
|
+
klass = repository[key]
|
651
787
|
if klass.nil?
|
652
788
|
code = element['code']
|
653
789
|
inherits = element['inherits']
|
@@ -674,7 +810,7 @@ EOC
|
|
674
810
|
end
|
675
811
|
end
|
676
812
|
|
677
|
-
klass.class_eval
|
813
|
+
klass.class_eval { include OSA::EventDispatcher } if real_name == 'application'
|
678
814
|
|
679
815
|
klass.const_set(:REAL_NAME, real_name) unless klass.const_defined?(:REAL_NAME)
|
680
816
|
klass.const_set(:PLURAL, plural == nil ? real_name + 's' : plural) unless klass.const_defined?(:PLURAL)
|
@@ -682,30 +818,45 @@ EOC
|
|
682
818
|
|
683
819
|
app_module.const_set(rubyfy_constant_string(real_name), klass)
|
684
820
|
|
685
|
-
repository[
|
821
|
+
repository[key] = klass
|
686
822
|
end
|
687
823
|
|
688
824
|
return klass
|
689
825
|
end
|
690
826
|
|
827
|
+
def self.type_doc(type, enum_group_codes, app_module)
|
828
|
+
if mod = enum_group_codes[type]
|
829
|
+
mod.to_s
|
830
|
+
elsif md = /^list_of_(.+)$/.match(type)
|
831
|
+
"list of #{type_doc(md[1], enum_group_codes, app_module)}"
|
832
|
+
else
|
833
|
+
up_type = type.upcase
|
834
|
+
begin
|
835
|
+
app_module.const_get(up_type).to_s
|
836
|
+
rescue
|
837
|
+
type
|
838
|
+
end
|
839
|
+
end
|
840
|
+
end
|
841
|
+
|
691
842
|
def self.type_of_parameter(element)
|
692
843
|
type = element['type']
|
693
844
|
if type.nil?
|
694
845
|
etype = element.find_first('type')
|
695
|
-
if etype
|
696
|
-
|
846
|
+
if etype
|
847
|
+
type = etype['type']
|
848
|
+
if type.nil? and (etype2 = etype.find_first('type')) != nil
|
849
|
+
type = etype2['type']
|
850
|
+
end
|
851
|
+
type = "list_of_#{type}" if etype['list'] == 'yes'
|
697
852
|
end
|
698
|
-
type = "list_of_#{type}" if etype['list'] == 'yes'
|
699
853
|
end
|
854
|
+
raise "Parameter #{element} has no type." if type.nil?
|
700
855
|
return type
|
701
856
|
end
|
702
857
|
|
703
|
-
def self.new_element_code(type, varname, enum_group_codes)
|
704
|
-
"#{varname}.is_a?(OSA::Element) ? #{varname} : Element.from_rbobj('#{type}', #{varname}, #{enum_group_codes.keys.inspect})"
|
705
|
-
end
|
706
|
-
|
707
858
|
def self.escape_string(string)
|
708
|
-
string.gsub(/[
|
859
|
+
string.gsub(/[\$\=\s\-\.\/]/, '_').gsub(/&/, 'and')
|
709
860
|
end
|
710
861
|
|
711
862
|
def self.rubyfy_constant_string(string, upcase=false)
|
@@ -751,6 +902,7 @@ EOC
|
|
751
902
|
def self.englishify_sentence(string)
|
752
903
|
return '' if string.nil?
|
753
904
|
string[0] = string[0].chr.upcase
|
905
|
+
string.strip!
|
754
906
|
last = string[-1].chr
|
755
907
|
string << '.' if last != '.' and last != '?' and last != '!'
|
756
908
|
return string
|
@@ -766,7 +918,7 @@ OSA.add_conversion_to_osa('Unicode text') { |value| [OSA.utf8_strings ? 'utf8' :
|
|
766
918
|
# Signed/unsigned integer.
|
767
919
|
OSA.add_conversion_to_ruby('shor', 'long') { |value| value.unpack('l').first }
|
768
920
|
OSA.add_conversion_to_ruby('comp') { |value| value.unpack('q').first }
|
769
|
-
OSA.add_conversion_to_ruby('magn') { |value| value.unpack('d').first }
|
921
|
+
OSA.add_conversion_to_ruby('magn', 'doub') { |value| value.unpack('d').first }
|
770
922
|
OSA.add_conversion_to_osa('integer', 'double integer') { |value| ['magn', [value].pack('l')] }
|
771
923
|
|
772
924
|
# Float
|
@@ -791,14 +943,15 @@ OSA.add_conversion_to_ruby('list') { |value, type, object|
|
|
791
943
|
# File name.
|
792
944
|
# Let's use the 'furl' type here instead of 'alis', as we don't have a way to produce an alias for a file that does not exist yet.
|
793
945
|
OSA.add_conversion_to_osa('alias', 'file') { |value| ['furl', value.to_s] }
|
794
|
-
OSA.add_conversion_to_ruby('alis')
|
946
|
+
OSA.add_conversion_to_ruby('alis') do |value, type, object|
|
947
|
+
URI.unescape(URI.parse(object.__data__('furl')).path)
|
948
|
+
end
|
795
949
|
|
796
950
|
# Hash.
|
797
951
|
OSA.add_conversion_to_ruby('reco') { |value, type, object| object.is_a?(OSA::ElementRecord) ? object.to_hash : value }
|
798
952
|
OSA.add_conversion_to_osa('record') do |value|
|
799
953
|
if value.is_a?(Hash)
|
800
|
-
|
801
|
-
OSA::ElementRecord.__new__(value)
|
954
|
+
OSA::ElementRecord.from_hash(value)
|
802
955
|
else
|
803
956
|
value
|
804
957
|
end
|
@@ -808,7 +961,7 @@ end
|
|
808
961
|
OSA.add_conversion_to_ruby('enum') { |value, type, object| OSA::Enumerator.enum_for_code(object.__data__('TEXT')) or object }
|
809
962
|
|
810
963
|
# Class.
|
811
|
-
OSA.add_conversion_to_osa('type class') { |value| value.is_a?(Class) and value.ancestors.include?(OSA::Element) ? ['type', value::CODE.to_4cc] : value }
|
964
|
+
OSA.add_conversion_to_osa('type class', 'type') { |value| value.is_a?(Class) and value.ancestors.include?(OSA::Element) ? ['type', value::CODE.to_4cc] : value }
|
812
965
|
OSA.add_conversion_to_ruby('type') do |value, type, object|
|
813
966
|
if value == 'msng'
|
814
967
|
# Missing values.
|
@@ -827,5 +980,8 @@ OSA.add_conversion_to_osa('bounding rectangle') { |value| ['qdrt', value.pack('S
|
|
827
980
|
OSA.add_conversion_to_ruby('PICT') { |value, type, object| value[222..-1] } # Removing trailing garbage.
|
828
981
|
OSA.add_conversion_to_osa('picture') { |value| ['PICT', value.to_s] }
|
829
982
|
OSA.add_conversion_to_ruby('imaA') { |value, type, object| value }
|
983
|
+
OSA.add_conversion_to_ruby('TIFF') { |value, type, object| value }
|
830
984
|
OSA.add_conversion_to_osa('Image') { |value| ['imaA', value.to_s] }
|
831
985
|
OSA.add_conversion_to_osa('TIFF picture') { |value| ['TIFF', value.to_s] }
|
986
|
+
|
987
|
+
require 'rbosa_properties'
|