rubyosa 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|