cocoa 0.1.5 → 0.1.6
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.
- checksums.yaml +4 -4
- data/Rakefile +5 -1
- data/VERSION +1 -1
- data/cocoa.gemspec +4 -3
- data/lib/cocoa/extensions.rb +7 -1
- data/lib/cocoa/helpers.rb +56 -11
- data/lib/cocoa/objc.rb +15 -11
- data/lib/cocoa/objc/method_def.rb +5 -4
- data/spec/cocoa/cocoa_spec.rb +15 -2
- data/spec/cocoa/cocoa_spec_r2.rb +18 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f71aa43ea295a1886c05be665d147e1312fb09a
|
4
|
+
data.tar.gz: c33bb6813e008b446256ceec2592d4b1dd897bcc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e655407c657e9e8b7a7bfbdf65fa7cd1f27cdbbaa050183e283c03a6308041abb71f678914e974d7f2a5caf6b8454cf808ce8269bf99b16612b657c3f401fb32
|
7
|
+
data.tar.gz: 4eddefb01fbb2b0bef984084a2adcb0ff50c144614887cf3591a29211cad5ca3fbe4d53471661446b5da273e3edf48c6dded60b20b89f2a50468eb4f089d787b
|
data/Rakefile
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
PROJECT_SPECS =
|
3
|
+
PROJECT_SPECS = if RUBY_VERSION.split.first.to_i >= 2
|
4
|
+
FileList['spec/**/*_spec.rb'] + FileList['spec/**/*_spec_r2.rb']
|
5
|
+
else
|
6
|
+
FileList['spec/**/*_spec.rb']
|
7
|
+
end
|
4
8
|
|
5
9
|
require 'jeweler'
|
6
10
|
Jeweler::Tasks.new do |gem|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.6
|
data/cocoa.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: cocoa 0.1.
|
5
|
+
# stub: cocoa 0.1.6 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "cocoa"
|
9
|
-
s.version = "0.1.
|
9
|
+
s.version = "0.1.6"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Patrick Hanevold"]
|
14
|
-
s.date = "2014-04-
|
14
|
+
s.date = "2014-04-13"
|
15
15
|
s.description = "Ruby FFI bindings for the OSX Cocoa API"
|
16
16
|
s.email = "patrick.hanevold@gmail.com"
|
17
17
|
s.extra_rdoc_files = [
|
@@ -425,6 +425,7 @@ Gem::Specification.new do |s|
|
|
425
425
|
"lib/cocoa/structs/NSRect.rb",
|
426
426
|
"lib/cocoa/structs/NSSize.rb",
|
427
427
|
"spec/cocoa/cocoa_spec.rb",
|
428
|
+
"spec/cocoa/cocoa_spec_r2.rb",
|
428
429
|
"spec/spec_helper.rb",
|
429
430
|
"tasks/bacon.rake",
|
430
431
|
"tasks/generate.rake",
|
data/lib/cocoa/extensions.rb
CHANGED
data/lib/cocoa/helpers.rb
CHANGED
@@ -123,24 +123,27 @@ module Cocoa
|
|
123
123
|
|
124
124
|
def self.attach_method method,*_params
|
125
125
|
return if method==:class
|
126
|
-
|
127
|
-
|
126
|
+
@method_specs ||= {}
|
127
|
+
@method_specs[method] = []
|
128
128
|
[_params].flatten.each do |spec|
|
129
|
-
|
129
|
+
@method_specs[method] << ObjC::MethodDef.new(method,spec)
|
130
130
|
end
|
131
131
|
define_method method do |*args|
|
132
|
+
klass = self.class; klass = klass.superclass while !klass.instance_methods(false).include?(method)
|
133
|
+
spec = klass.instance_variable_get(:@method_specs)[method]
|
134
|
+
|
132
135
|
matching = if args.size <= 1
|
133
|
-
matching =
|
136
|
+
matching = spec.select do |m|
|
134
137
|
m.types.size == args.size
|
135
138
|
end
|
136
139
|
else
|
137
140
|
matching = if args.last.is_a? Hash
|
138
|
-
|
141
|
+
spec.select do |m|
|
139
142
|
args.last.keys == m.names
|
140
143
|
end
|
141
144
|
else
|
142
145
|
raise "hell" unless args.size == 1
|
143
|
-
|
146
|
+
spec.select do |m|
|
144
147
|
m.types.size == 1
|
145
148
|
end
|
146
149
|
end
|
@@ -157,18 +160,26 @@ module Cocoa
|
|
157
160
|
end
|
158
161
|
|
159
162
|
def self.method_defs method
|
160
|
-
|
163
|
+
klass = self
|
164
|
+
method_specs = klass.instance_variable_get(:@method_specs)
|
165
|
+
while klass && (!method_specs || !method_specs[method])
|
166
|
+
klass = klass.superclass
|
167
|
+
method_specs = klass.instance_variable_get(:@method_specs)
|
168
|
+
end
|
169
|
+
return nil unless method_specs
|
170
|
+
|
171
|
+
spec = method_specs[method]
|
161
172
|
params = instance_method(method).parameters
|
162
173
|
keys = params.select{ |param| param.first == :key }.map{ |param| param.last }
|
163
174
|
if params.size > 0 && params.last.first == :rest
|
164
|
-
filtered =
|
175
|
+
filtered = spec.select do |m|
|
165
176
|
((m.types.size == 0 && keys.size == 0) || (m.types.size > keys.size)) &&
|
166
177
|
(m.names[0,keys.size-1] || []) == keys
|
167
178
|
end
|
168
179
|
return nil if filtered.size == 0
|
169
180
|
filtered
|
170
181
|
else
|
171
|
-
filtered =
|
182
|
+
filtered = spec.select do |m|
|
172
183
|
((m.types.size == 0 && keys.size == 0) || (m.types.size == keys.size+1)) &&
|
173
184
|
m.names == keys
|
174
185
|
end
|
@@ -181,18 +192,42 @@ module Cocoa
|
|
181
192
|
def self.method_added(name)
|
182
193
|
return if name == :== # TODO: define as equals or something?
|
183
194
|
return if name.to_s[-1] == '='
|
195
|
+
return if caller[1].split('`').last[0..-2] == 'method_added' # self
|
184
196
|
return if caller.first.split('`').last[0..-2] == 'define_method' # MRI
|
185
197
|
return if caller.first.split('`').last[0..-2] == 'attach_method' # Rubinius
|
186
198
|
|
199
|
+
# define an alias for keyword argument methods such that:
|
200
|
+
# class Foo
|
201
|
+
# def bar whatever, alpha: nil
|
202
|
+
# puts "alpha is: #{alpha}"
|
203
|
+
# end
|
204
|
+
# def bar whatever, omega: nil
|
205
|
+
# puts "omega is: #{omega}"
|
206
|
+
# end
|
207
|
+
# end
|
208
|
+
# Foo.new.bar "hello", omega: "is omega"
|
209
|
+
# Foo.new.bar "hello", alpha: "is alpha"
|
210
|
+
#=>
|
211
|
+
# omega is: is omega
|
212
|
+
# alpha is: is alpha
|
213
|
+
keys = instance_method(name).parameters.select{ |param| param.first == :key }.map{ |param| param.last }
|
214
|
+
ruby_name = name
|
215
|
+
if keys.size > 0
|
216
|
+
ruby_name = "_#{name}_with_#{keys.join('_and_')}".to_sym
|
217
|
+
alias_method ruby_name, name
|
218
|
+
end
|
219
|
+
|
220
|
+
|
187
221
|
defs = method_defs name
|
188
222
|
defs ||= ObjC::MethodDef.new(name, :names => [], :types => ['@'], :retval => 'v') # TODO: generate from method arguments!
|
189
223
|
|
190
224
|
[defs].flatten.each do |m|
|
191
225
|
@callbacks ||= []
|
192
226
|
@callbacks << Proc.new do |this,cmd,*args|
|
227
|
+
m.ruby_name = ruby_name
|
193
228
|
begin
|
194
229
|
instance = Cocoa.instances[this.address]
|
195
|
-
params = instance_method(
|
230
|
+
params = instance_method(ruby_name).parameters
|
196
231
|
m.callback(instance,params,args)
|
197
232
|
rescue => e
|
198
233
|
puts e.message
|
@@ -203,10 +238,20 @@ module Cocoa
|
|
203
238
|
callback_name = "#{self.name.gsub('::','__')}_#{m.selector.gsub(/:/,'_')}".to_sym
|
204
239
|
add_method = "add_#{callback_name}".to_sym
|
205
240
|
|
241
|
+
native_name = begin
|
242
|
+
arr = self.name.split('::')
|
243
|
+
native = if arr.first == 'Cocoa'
|
244
|
+
arr.last
|
245
|
+
else
|
246
|
+
self.name.gsub(/::/,'__')
|
247
|
+
end
|
248
|
+
native
|
249
|
+
end
|
250
|
+
|
206
251
|
ObjC.callback callback_name, [:pointer, :pointer]+m.ffi_types, m.ffi_return_type
|
207
252
|
ObjC.attach_function add_method, :class_addMethod, [:pointer,:pointer,callback_name,:string], :void
|
208
253
|
|
209
|
-
ObjC.send(add_method,ObjC.objc_getClass(
|
254
|
+
ObjC.send(add_method,ObjC.objc_getClass(native_name),ObjC.sel_registerName(m.selector),@callbacks.last,m.objc_types)
|
210
255
|
end
|
211
256
|
end
|
212
257
|
end
|
data/lib/cocoa/objc.rb
CHANGED
@@ -75,19 +75,23 @@ module ObjC
|
|
75
75
|
instance = begin
|
76
76
|
Cocoa::const_get(klass_name).new(true)
|
77
77
|
rescue
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
if
|
82
|
-
|
78
|
+
begin
|
79
|
+
Object.const_get(klass_name.gsub(/__/,'::')).new(true)
|
80
|
+
rescue
|
81
|
+
klass_name = if klass_name =~ /^__NSCF/
|
82
|
+
"NS#{klass_name[6..-1]}"
|
83
|
+
elsif klass_name[0]=='_'
|
84
|
+
if superklass = Cocoa::const_get(NSString_to_String(Cocoa::NSStringFromClass(ObjC.msgSend_pointer(ret,"superclass"))))
|
85
|
+
superklass.name.split('::').last
|
86
|
+
else
|
87
|
+
"FIX_#{klass_name}"
|
88
|
+
end
|
83
89
|
else
|
84
|
-
|
90
|
+
klass_name
|
85
91
|
end
|
86
|
-
|
87
|
-
|
92
|
+
klass = smart_constantize(ret,klass_name)
|
93
|
+
klass.new(true)
|
88
94
|
end
|
89
|
-
klass = smart_constantize(ret,klass_name)
|
90
|
-
klass.new(true)
|
91
95
|
end
|
92
96
|
instance.object = ret
|
93
97
|
instance
|
@@ -119,7 +123,7 @@ module ObjC
|
|
119
123
|
case type
|
120
124
|
when nil
|
121
125
|
default
|
122
|
-
when '@', 'v', 'q', 'Q', '^v'
|
126
|
+
when '@', 'v', 'q', 'Q', '^v', 'B'
|
123
127
|
type
|
124
128
|
when /^{([^=]*)=.*}$/
|
125
129
|
type
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module ObjC
|
2
2
|
class MethodDef
|
3
|
-
attr_accessor :name,:names,:types,:return_type
|
3
|
+
attr_accessor :name,:names,:types,:return_type,:ruby_name
|
4
4
|
|
5
5
|
TYPES = {
|
6
6
|
'c' => :char,
|
@@ -31,6 +31,7 @@ module ObjC
|
|
31
31
|
|
32
32
|
def initialize name,options
|
33
33
|
@name = name.to_sym
|
34
|
+
@ruby_name = name.to_sym
|
34
35
|
@names = options[:names].map(&:to_sym)
|
35
36
|
@types = options[:types]
|
36
37
|
@return_type = options[:retval]
|
@@ -280,12 +281,12 @@ module ObjC
|
|
280
281
|
|
281
282
|
ret = if params.size > 0 && params.last.first == :rest
|
282
283
|
args = args.map{ |arg| Cocoa::instance_for(arg) }
|
283
|
-
instance.send(
|
284
|
+
instance.send(ruby_name, args.first, Hash[*names.zip(args[1..-1]).flatten])
|
284
285
|
elsif keys.size > 0
|
285
286
|
args = args.map{ |arg| Cocoa::instance_for(arg) }
|
286
|
-
instance.send(
|
287
|
+
instance.send(ruby_name, args.first, Hash[*keys.zip(args[1..-1]).flatten])
|
287
288
|
else
|
288
|
-
instance.send(
|
289
|
+
instance.send(ruby_name, *args.map{ |arg| Cocoa::instance_for(arg) })
|
289
290
|
end
|
290
291
|
ffi_return_value(ret)
|
291
292
|
end
|
data/spec/cocoa/cocoa_spec.rb
CHANGED
@@ -17,6 +17,17 @@ describe 'Cocoa' do
|
|
17
17
|
Derived.superclass.name.should == 'Cocoa::NSObject'
|
18
18
|
end
|
19
19
|
|
20
|
+
it 'should provide native names' do
|
21
|
+
class Derived < Cocoa::NSObject
|
22
|
+
end
|
23
|
+
module Scoped; end
|
24
|
+
class Scoped::Derived < Cocoa::NSObject
|
25
|
+
end
|
26
|
+
Cocoa::NSObject.native_name.should == 'NSObject'
|
27
|
+
Derived.native_name.should == 'Derived'
|
28
|
+
Scoped::Derived.native_name.should == 'Scoped__Derived'
|
29
|
+
end
|
30
|
+
|
20
31
|
it 'should provide correct return types for class methods' do
|
21
32
|
Cocoa::NSMutableArray.array.class.name.should == 'Cocoa::NSMutableArray'
|
22
33
|
end
|
@@ -115,6 +126,7 @@ describe 'Cocoa' do
|
|
115
126
|
# fake ruby 2
|
116
127
|
unbound_method = mock('UnboundMethod')
|
117
128
|
Cocoa::NSObject.expects(:instance_method).with(:tableView).at_least_once.returns(unbound_method)
|
129
|
+
Cocoa::NSObject.expects(:instance_method).with(:_tableView_with_objectValueForTableColumn_and_row).at_least_once.returns(unbound_method)
|
118
130
|
unbound_method.expects(:parameters).at_least_once.returns([[:req, :table_view], [:key, :objectValueForTableColumn], [:key, :row]])
|
119
131
|
class Derived < Cocoa::NSObject
|
120
132
|
#def tableView(table_view, objectValueForTableColumn: column, row: i); end
|
@@ -122,7 +134,7 @@ describe 'Cocoa' do
|
|
122
134
|
end
|
123
135
|
|
124
136
|
derived = Derived.new
|
125
|
-
derived.expects(:
|
137
|
+
derived.expects(:_tableView_with_objectValueForTableColumn_and_row).with(
|
126
138
|
Cocoa::NSString.stringWithString("arg1"),
|
127
139
|
objectValueForTableColumn: Cocoa::NSString.stringWithString("arg2"),
|
128
140
|
row: 123
|
@@ -137,6 +149,7 @@ describe 'Cocoa' do
|
|
137
149
|
# fake ruby 2
|
138
150
|
unbound_method = mock('UnboundMethod')
|
139
151
|
Cocoa::NSObject.expects(:instance_method).with(:tableView).at_least_once.returns(unbound_method)
|
152
|
+
Cocoa::NSObject.expects(:instance_method).with(:_tableView_with_objectValueForTableColumn_and_row).at_least_once.returns(unbound_method)
|
140
153
|
unbound_method.expects(:parameters).at_least_once.returns([[:req, :table_view], [:key, :objectValueForTableColumn], [:key, :row]])
|
141
154
|
class Derived < Cocoa::NSObject
|
142
155
|
#def tableView(table_view, objectValueForTableColumn: column, row: i); end
|
@@ -157,7 +170,7 @@ describe 'Cocoa' do
|
|
157
170
|
end
|
158
171
|
|
159
172
|
derived = Derived.new
|
160
|
-
derived.expects(:
|
173
|
+
derived.expects(:_tableView_with_objectValueForTableColumn_and_row).with(
|
161
174
|
Cocoa::NSString.stringWithString("arg1"),
|
162
175
|
objectValueForTableColumn: Cocoa::NSString.stringWithString("arg2"),
|
163
176
|
row: 123
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
require 'cocoa'
|
3
|
+
|
4
|
+
describe 'Cocoa' do
|
5
|
+
# context 'callbacks' do
|
6
|
+
it 'should be able to call overridden methods with keword arguments and return a value' do
|
7
|
+
class Derived < Cocoa::NSObject
|
8
|
+
def tableView(table_view, objectValueForTableColumn: column, row: i)
|
9
|
+
"returned value"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
derived = Derived.new
|
14
|
+
ret = derived.tableView("arg1", objectValueForTableColumn: "arg2", row: 123)
|
15
|
+
ret.to_s.should == "returned value"
|
16
|
+
end
|
17
|
+
# end
|
18
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cocoa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Patrick Hanevold
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -550,6 +550,7 @@ files:
|
|
550
550
|
- lib/cocoa/structs/NSRect.rb
|
551
551
|
- lib/cocoa/structs/NSSize.rb
|
552
552
|
- spec/cocoa/cocoa_spec.rb
|
553
|
+
- spec/cocoa/cocoa_spec_r2.rb
|
553
554
|
- spec/spec_helper.rb
|
554
555
|
- tasks/bacon.rake
|
555
556
|
- tasks/generate.rake
|