SlideShare uma empresa Scribd logo
1 de 93
Baixar para ler offline
Ruby and Cocoa
 Facilitate development on OSX
About me
About me
Rapperswil
http://www.flickr.com/photos/turtlemom_nancy/4026208166/sizes/l/
huesler informatik
huesler informatik

upstream agile
huesler informatik

upstream agile

co-up.de
Ruby and Cocoa
Ruby
passionate
  http://www.flickr.com/photos/gi/378823/sizes/o/
Apple OSX
passionate
  http://www.flickr.com/photos/gi/378823/sizes/o/
Landscape
 http://www.flickr.com/photos/kiumo/4203883504/sizes/o/
Cocoa
http://www.flickr.com/photos/luder5/4100921399/sizes/l/
Cocoa
Cocoa
•   Core Foundation
Cocoa
•   Core Foundation
•   Appkit
Cocoa
•   Core Foundation
•   Appkit
•   Core * (Audio/Video/Image/Data
    etc.)
Cocoa
•   Core Foundation
•   Appkit
•   Core * (Audio/Video/Image/Data
    etc.)
•   Scripting bridge
Cocoa
•   Core Foundation
•   Appkit
•   Core * (Audio/Video/Image/Data
    etc.)
•   Scripting bridge
•   others
Interface Builder
XCode
Objective-C
NSMutableArray *anArray = [
      [NSMutableArray alloc]   init
    ];
[anArray addObject:@"Element   1"];
[anArray addObject:@"Element   2"];
[anArray addObject:@"Element   3"];

//Use a for each loop to iterate
through the array
for (NSString *s in anArray) {
     NSLog(s);
}
//Release the array
[anArray release]
Ruby And Cocoa
Ruby Cocoa
HotCocoa
picture shamelessly cropped from http://www.slideshare.net/mattetti/macruby-hotcocoa-presentation-by-rich-kilmer
Scripting Bridge
    http://www.flickr.com/photos/bensonkua/2851908095/sizes/l/
Good to know
Good to know
•   Available commands for each
    application are in a .sdef file
Good to know
•   Available commands for each
    application are in a .sdef file
•   Terminal.app/Contents/Resources/
    Terminal.sdef
Good to know
•   Available commands for each
    application are in a .sdef file
•   Terminal.app/Contents/Resources/
    Terminal.sdef
•   gem rb-appscript (native extension
    so not for MacRuby)
1 <command name="do script" code="coredosc"
 2     description="Runs a UNIX shell script or command.">
 3     <cocoa class="TTDoScriptCommand"/>
 4     <direct-parameter type="text"
 5         description="The command to execute." optional="yes"/>
 6     <parameter name="with command"
 7         description="Data to be passed to the Terminal..."
 8         code="cmnd" optional="yes" hidden="yes">
 9         <cocoa key="Command" />
10         <type type="text" />
11         <type type="any" /> <!-- support null case -->
12     </parameter>
13     <parameter name="in"
14         description="The tab in which to execute the command"
15         code="kfil" optional="yes">
16         <cocoa key="Target" />
17         <type type="tab" />
18         <type type="window" />
19         <type type="any" /> <!-- support null case -->
20     </parameter>
21     <result type="tab"
22         description="The tab the command was executed in." />
23 </command>
24
Control Terminal
1 #!/usr/bin/env ruby
    2 require 'rubygems'
    3 require 'appscript'
    4 include Appscript
    5
    6 terminal = app('Terminal')
    7 current_window = terminal.windows.first
    8 current_tab = current_window.tabs.last
    9 process = app("System
Events").application_processes[
   10   "Terminal.app"
   11   ]
   12
   13 process.keystroke('t', :using => :command_down)
   14 terminal.do_script('top', :in => current_tab)
1 #!/usr/bin/env ruby
    2 require 'rubygems'
    3 require 'appscript'
    4 include Appscript
    5
    6 terminal = app('Terminal')
    7 current_window = terminal.windows.first
    8 current_tab = current_window.tabs.last
    9 process = app("System
Events").application_processes[
   10   "Terminal.app"
   11   ]
   12
   13 process.keystroke('t', :using => :command_down)
   14 terminal.do_script('top', :in => current_tab)
1 #!/usr/bin/env ruby
    2 require 'rubygems'
    3 require 'appscript'
    4 include Appscript
    5
    6 terminal = app('Terminal')
    7 current_window = terminal.windows.first
    8 current_tab = current_window.tabs.last
    9 process = app("System
Events").application_processes[
   10   "Terminal.app"
   11   ]
   12
   13 process.keystroke('t', :using => :command_down)
   14 terminal.do_script('top', :in => current_tab)
7 current_window = terminal.windows.first
    8 current_tab = current_window.tabs.last
    9 process = app("System
Events").application_processes[
   10   "Terminal.app"
   11   ]
   12
   13 process.keystroke('t', :using => :command_down)
   14 terminal.do_script('top', :in => current_tab)
Problems with MacRuby
Problems with MacRuby
Problems with MacRuby

•   Some methods don’t seem to be
    available
iTunes
1 #!/usr/bin/env macruby
    2
    3 framework 'ScriptingBridge'
    4
    5 itunes =
SBApplication.applicationWithBundleIdentifier(
    6   "com.apple.iTunes"
    7 )
    8 library = itunes.sources.objectWithName
("Library")
    9
   10 library.userPlaylists.each do |playlist|
   11   puts playlist.name
   12 end
2
    3 framework 'ScriptingBridge'
    4
    5 itunes =
SBApplication.applicationWithBundleIdentifier(
    6   "com.apple.iTunes"
    7 )
    8 library = itunes.sources.objectWithName
("Library")
    9
   10 library.userPlaylists.each do |playlist|
   11   puts playlist.name
   12 end
2
    3 framework 'ScriptingBridge'
    4
    5 itunes =
SBApplication.applicationWithBundleIdentifier(
    6   "com.apple.iTunes"
    7 )
    8 library = itunes.sources.objectWithName
("Library")
    9
   10 library.userPlaylists.each do |playlist|
   11   puts playlist.name
   12 end
Core Location
1   #!/usr/bin/env macruby
 2   framework 'CoreLocation'
 3
 4   loc = CLLocationManager.alloc.init
 5   loc.delegate = self
 6   loc.startUpdatingLocation
 7
 8   # keep the script running
 9   NSRunLoop.currentRunLoop.runUntilDate(
10     NSDate.distantFuture
11   )
1   #!/usr/bin/env macruby
 2   framework 'CoreLocation'
 3
 4   loc = CLLocationManager.alloc.init
 5   loc.delegate = self
 6   loc.startUpdatingLocation
 7
 8   # keep the script running
 9   NSRunLoop.currentRunLoop.runUntilDate(
10     NSDate.distantFuture
11   )
1 def locationManager(
2         manager,
3         didUpdateToLocation: new_location,
4         fromLocation: old_location
5   )
6
7   puts "loc: #{new_location.description}"
8 end
2   framework 'CoreLocation'
 3
 4   loc = CLLocationManager.alloc.init
 5   loc.delegate = self
 6   loc.startUpdatingLocation
 7
 8   # keep the script running
 9   NSRunLoop.currentRunLoop.runUntilDate(
10     NSDate.distantFuture
11   )
1   #!/usr/bin/env macruby
 2   framework 'CoreLocation'
 3
 4   def locationManager(manager,
 5                        didUpdateToLocation: new_location,
 6                        fromLocation: old_location
 7                      )
 8     puts "location: #{new_location.description}"
 9   end
10
11   loc = CLLocationManager.alloc.init
12   loc.delegate = self
13   loc.startUpdatingLocation
14
15   # keep the script running
16   NSRunLoop.currentRunLoop.runUntilDate(
17     NSDate.distantFuture
18   )
Grand Central
  Dispatch
Grand Central Dispatch
Grand Central Dispatch
•   MacRuby only
Grand Central Dispatch
•   MacRuby only
•   Synchronous
Grand Central Dispatch
•   MacRuby only
•   Synchronous
•   Asynchronous
Grand Central Dispatch
•   MacRuby only
•   Synchronous
•   Asynchronous
•   Parallel
Grand Central Dispatch
•   MacRuby only
•   Synchronous
•   Asynchronous
•   Parallel
•   Synchronization
Asynchronous
1   #!/usr/bin/env macruby
 2
 3   queue = Dispatch::Queue.new(
 4       'ch.huesler-informatik.scotrubyconf.gcd'
 5     )
 6
 7   queue.async do
 8     puts 'Starting asyn. NONE BLOCKING!'
 9     sleep 2.00
10     puts "Finished asyn"
11   end
12   puts "code not being blocked"
13
14   NSRunLoop.currentRunLoop.runUntilDate(
15       NSDate.distantFuture
16     )
17
1   #!/usr/bin/env macruby
 2
 3   queue = Dispatch::Queue.new(
 4       'ch.huesler-informatik.scotrubyconf.gcd'
 5     )
 6
 7   queue.async do
 8     puts 'Starting asyn. NONE BLOCKING!'
 9     sleep 2.00
10     puts "Finished asyn"
11   end
12   puts "code not being blocked"
13
14   NSRunLoop.currentRunLoop.runUntilDate(
15       NSDate.distantFuture
16     )
17
7   queue.async do
 8     puts 'Starting asyn. NONE BLOCKING!'
 9     sleep 2.00
10     puts "Finished asyn"
11   end
12   puts "code not being blocked"
13
14   NSRunLoop.currentRunLoop.runUntilDate(
15       NSDate.distantFuture
16     )
17
Synchronous
1   #!/usr/bin/env macruby
 2
 3   queue = Dispatch::Queue.new(
 4       'ch.huesler-informatik.scotrubyconf.gcd'
 5     )
 6
 7   queue.sync do
 8     puts 'Starting sync. BLOCKING!'
 9     sleep 3.0
10     puts 'Finished sync'
11   end
12   puts "code being blocked"
13
14   NSRunLoop.currentRunLoop.runUntilDate(
15       NSDate.distantFuture
16     )
17
Synchronized
1   #!/usr/bin/env macruby
 2
 3   worker_queue = Dispatch::Queue.new(
 4       'ch.huesler-informatik.scotrubyconf.gcd'
 5     )
 6   group = Dispatch::Group.new
 7
 8   0.upto(10) do |i|
 9     puts "Dispatch #{i} to GCD"
10     worker_queue.async(group) do
11       puts "working on #{i}"
12     end
13   end
14   puts "waiting for gcd"
15   group.wait
16   puts "done"
17
1   #!/usr/bin/env macruby
 2
 3   worker_queue = Dispatch::Queue.new(
 4       'ch.huesler-informatik.scotrubyconf.gcd'
 5     )
 6   group = Dispatch::Group.new
 7
 8   0.upto(10) do |i|
 9     puts "Dispatch #{i} to GCD"
10     worker_queue.async(group) do
11       puts "working on #{i}"
12     end
13   end
14   puts "waiting for gcd"
15   group.wait
16   puts "done"
17
7
 8   0.upto(10) do |i|
 9     puts "Dispatch #{i} to GCD"
10     worker_queue.async(group) do
11       puts "working on #{i}"
12     end
13   end
14   puts "waiting for gcd"
15   group.wait
16   puts "done"
17
Concurrent
1   #!/usr/bin/env macruby
 2
 3   group = Dispatch::Group.new
 4   result = []
 5   1.upto(10).each do |i|
 6     Dispatch::Queue.concurrent.async(group) do
 7       sleep 2
 8       result << i
 9     end
10   end
11   group.wait
12   puts result.inspect
.plist files
1 #!/usr/bin/env ruby
    2 require "osx/cocoa"
    3 include OSX
    4
    5 file_name = 'Info.plist'
    6 plist =
NSDictionary.dictionaryWithContentsOfFile(
    7            file_name
    8          )
    9
   10 plist['CFBundleVersion'] = '2.0.1'
   11
   12 plist.writeToFile_atomically(
   13     file_name,
   14     true
   15   )
1 #!/usr/bin/env ruby
    2 require "osx/cocoa"
    3 include OSX
    4
    5 file_name = 'Info.plist'
    6 plist =
NSDictionary.dictionaryWithContentsOfFile(
    7            file_name
    8          )
    9
   10 plist['CFBundleVersion'] = '2.0.1'
   11
   12 plist.writeToFile_atomically(
   13     file_name,
   14     true
   15   )
3 include OSX
    4
    5 file_name = 'Info.plist'
    6 plist =
NSDictionary.dictionaryWithContentsOfFile(
    7            file_name
    8          )
    9
   10 plist['CFBundleVersion'] = '2.0.1'
   11
   12 plist.writeToFile_atomically(
   13     file_name,
   14     true
   15   )
Keychain
 Access
Details
Details
•   MacRuby has issues with void
    pointer (patch pending)
Details
•   MacRuby has issues with void
    pointer (patch pending)
•   Use objective c wrapper instead
    (dynlib or bundle)
Details
•   MacRuby has issues with void
    pointer (patch pending)
•   Use objective c wrapper instead
    (dynlib or bundle)
•   Generate metadata to make it
    work
Details
•   MacRuby has issues with void
    pointer (patch pending)
•   Use objective c wrapper instead
    (dynlib or bundle)
•   Generate metadata to make it
    work
1 export FILE_PATH = ~/Library/BridgeSupport
    2 export FRAMEWORK_PATH = ~/Library/BridgeSupport/
Security.bridgesupport
    3 mkdir $FILE_PATH
    4 gen_bridge_metadata -f Security -o $FRAMEWORK_PATH
1   require 'osx/cocoa'
 2   include OSX
 3   require_framework 'Security'
 4
 5   # Set up some relevant variables
 6
 7   service = "ch.huesler-informatik.scotrubyconf.keychain"
 8   account = "Highlander"
 9   original_password = "Rrrueby"
10
11   # Add password
12   SecKeychainAddGenericPassword(
13       nil,
14       service.length,
15       service,
16       account.length,
17       account,
18       original_password.length,
19       original_password,
20       nil
21   )
1   require 'osx/cocoa'
 2   include OSX
 3   require_framework 'Security'
 4
 5   # Set up some relevant variables
 6
 7   service = "ch.huesler-informatik.scotrubyconf.keychain"
 8   account = "Highlander"
 9   original_password = "Rrrueby"
10
11   # Add password
12   SecKeychainAddGenericPassword(
13       nil,
14       service.length,
15       service,
16       account.length,
17       account,
18       original_password.length,
19       original_password,
20       nil
21   )
1 # Add password
 2 SecKeychainAddGenericPassword(
 3     nil,
 4     service.length,
 5     service,
 6     account.length,
 7     account,
 8     original_password.length,
 9     original_password,
10     nil
11 )
1 # Query   the keychain
2 status,   *password = SecKeychainFindGenericPassword(
3           nil,
4           service.length,
5           service,
6           account.length,
7           account
8       )
1   # Password-related data. Shifting pointers
2   length = password.shift
3   data = password.shift
4   plain_password = data.bytestr(length)
5
6   puts "Password: #{plain_password}"
That’s all!
Questions?

Mais conteúdo relacionado

Mais procurados

Всеволод Струкчинский: Node.js
Всеволод Струкчинский: Node.jsВсеволод Струкчинский: Node.js
Всеволод Струкчинский: Node.jsYandex
 
Adventures in infrastructure as code
Adventures in infrastructure as codeAdventures in infrastructure as code
Adventures in infrastructure as codeJulian Simpson
 
Speed up web APIs with Expressive and Swoole (PHP Day 2018)
Speed up web APIs with Expressive and Swoole (PHP Day 2018) Speed up web APIs with Expressive and Swoole (PHP Day 2018)
Speed up web APIs with Expressive and Swoole (PHP Day 2018) Zend by Rogue Wave Software
 
YASPS OPENNING
YASPS OPENNINGYASPS OPENNING
YASPS OPENNINGJeen Lee
 
Better detection of what modules are used by some Perl 5 code
Better detection of what modules are used by some Perl 5 codeBetter detection of what modules are used by some Perl 5 code
Better detection of what modules are used by some Perl 5 codecharsbar
 
Release with confidence
Release with confidenceRelease with confidence
Release with confidenceJohn Congdon
 
PL/Perl - New Features in PostgreSQL 9.0 201012
PL/Perl - New Features in PostgreSQL 9.0 201012PL/Perl - New Features in PostgreSQL 9.0 201012
PL/Perl - New Features in PostgreSQL 9.0 201012Tim Bunce
 
How to inspect a RUNNING perl process
How to inspect a RUNNING perl processHow to inspect a RUNNING perl process
How to inspect a RUNNING perl processMasaaki HIROSE
 
SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)Robert Swisher
 
Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)xSawyer
 
DevOpsCon 2021: Go Web Development 101
DevOpsCon 2021: Go Web Development 101DevOpsCon 2021: Go Web Development 101
DevOpsCon 2021: Go Web Development 101Jan Stamer
 
entwickler.de Go Day: Go Web Development 101
entwickler.de Go Day: Go Web Development 101entwickler.de Go Day: Go Web Development 101
entwickler.de Go Day: Go Web Development 101Jan Stamer
 
betterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
betterCode() Go: Einstieg in Go, Standard-Library und ÖkosystembetterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
betterCode() Go: Einstieg in Go, Standard-Library und ÖkosystemJan Stamer
 
DevOps in PHP environment
DevOps in PHP environmentDevOps in PHP environment
DevOps in PHP environmentEvaldo Felipe
 
What you need to remember when you upload to CPAN
What you need to remember when you upload to CPANWhat you need to remember when you upload to CPAN
What you need to remember when you upload to CPANcharsbar
 
Asynchronous PHP and Real-time Messaging
Asynchronous PHP and Real-time MessagingAsynchronous PHP and Real-time Messaging
Asynchronous PHP and Real-time MessagingSteve Rhoades
 
Php assíncrono com_react_php
Php assíncrono com_react_phpPhp assíncrono com_react_php
Php assíncrono com_react_phpRenato Lucena
 
Perl: Coro asynchronous
Perl: Coro asynchronous Perl: Coro asynchronous
Perl: Coro asynchronous Shmuel Fomberg
 

Mais procurados (20)

Всеволод Струкчинский: Node.js
Всеволод Струкчинский: Node.jsВсеволод Струкчинский: Node.js
Всеволод Струкчинский: Node.js
 
Adventures in infrastructure as code
Adventures in infrastructure as codeAdventures in infrastructure as code
Adventures in infrastructure as code
 
Speed up web APIs with Expressive and Swoole (PHP Day 2018)
Speed up web APIs with Expressive and Swoole (PHP Day 2018) Speed up web APIs with Expressive and Swoole (PHP Day 2018)
Speed up web APIs with Expressive and Swoole (PHP Day 2018)
 
YASPS OPENNING
YASPS OPENNINGYASPS OPENNING
YASPS OPENNING
 
Better detection of what modules are used by some Perl 5 code
Better detection of what modules are used by some Perl 5 codeBetter detection of what modules are used by some Perl 5 code
Better detection of what modules are used by some Perl 5 code
 
Release with confidence
Release with confidenceRelease with confidence
Release with confidence
 
PL/Perl - New Features in PostgreSQL 9.0 201012
PL/Perl - New Features in PostgreSQL 9.0 201012PL/Perl - New Features in PostgreSQL 9.0 201012
PL/Perl - New Features in PostgreSQL 9.0 201012
 
How to inspect a RUNNING perl process
How to inspect a RUNNING perl processHow to inspect a RUNNING perl process
How to inspect a RUNNING perl process
 
SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)
 
Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)
 
DevOpsCon 2021: Go Web Development 101
DevOpsCon 2021: Go Web Development 101DevOpsCon 2021: Go Web Development 101
DevOpsCon 2021: Go Web Development 101
 
entwickler.de Go Day: Go Web Development 101
entwickler.de Go Day: Go Web Development 101entwickler.de Go Day: Go Web Development 101
entwickler.de Go Day: Go Web Development 101
 
betterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
betterCode() Go: Einstieg in Go, Standard-Library und ÖkosystembetterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
betterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
 
DevOps in PHP environment
DevOps in PHP environmentDevOps in PHP environment
DevOps in PHP environment
 
Shell Script
Shell ScriptShell Script
Shell Script
 
What you need to remember when you upload to CPAN
What you need to remember when you upload to CPANWhat you need to remember when you upload to CPAN
What you need to remember when you upload to CPAN
 
Asynchronous PHP and Real-time Messaging
Asynchronous PHP and Real-time MessagingAsynchronous PHP and Real-time Messaging
Asynchronous PHP and Real-time Messaging
 
Php assíncrono com_react_php
Php assíncrono com_react_phpPhp assíncrono com_react_php
Php assíncrono com_react_php
 
Anyevent
AnyeventAnyevent
Anyevent
 
Perl: Coro asynchronous
Perl: Coro asynchronous Perl: Coro asynchronous
Perl: Coro asynchronous
 

Destaque

Edisi 12 Medan
Edisi 12 MedanEdisi 12 Medan
Edisi 12 Medanepaper
 
15jan Aceh
15jan Aceh15jan Aceh
15jan Acehepaper
 
BI Portfolio
BI PortfolioBI Portfolio
BI Portfoliotcomeaux
 
Fvcp Presentation Openoffice
Fvcp Presentation OpenofficeFvcp Presentation Openoffice
Fvcp Presentation OpenofficeStraight North
 
Edisi1oktaceh
Edisi1oktacehEdisi1oktaceh
Edisi1oktacehepaper
 
Credit Its A Brand New Day
Credit Its A Brand New DayCredit Its A Brand New Day
Credit Its A Brand New DayAndre Williams
 
Edisi Nasional 27 Maret
Edisi Nasional 27 MaretEdisi Nasional 27 Maret
Edisi Nasional 27 Maretepaper
 
Edisi 28 Medan
Edisi 28 MedanEdisi 28 Medan
Edisi 28 Medanepaper
 
Edisi 7 Feb 2010
Edisi 7 Feb 2010Edisi 7 Feb 2010
Edisi 7 Feb 2010epaper
 
12jan Aceh
12jan Aceh12jan Aceh
12jan Acehepaper
 
TIM Day in NY
TIM Day in NYTIM Day in NY
TIM Day in NYTIM RI
 
Edisi 2 Maret Medan
Edisi 2 Maret MedanEdisi 2 Maret Medan
Edisi 2 Maret Medanepaper
 
2 Des Aceh
2 Des Aceh2 Des Aceh
2 Des Acehepaper
 
Skapa en sökmotorvänlig webbplats!
Skapa en sökmotorvänlig webbplats!Skapa en sökmotorvänlig webbplats!
Skapa en sökmotorvänlig webbplats!Guava Sweden
 
Edisi 1 Maret Medan
Edisi 1 Maret MedanEdisi 1 Maret Medan
Edisi 1 Maret Medanepaper
 
Top Flex 7 Unit One- phrasal verbs
Top Flex 7 Unit One- phrasal verbsTop Flex 7 Unit One- phrasal verbs
Top Flex 7 Unit One- phrasal verbsDaniela Lyra Cardoso
 
Webinarium affiliate
Webinarium affiliateWebinarium affiliate
Webinarium affiliateGuava Sweden
 

Destaque (20)

Edisi 12 Medan
Edisi 12 MedanEdisi 12 Medan
Edisi 12 Medan
 
15jan Aceh
15jan Aceh15jan Aceh
15jan Aceh
 
BI Portfolio
BI PortfolioBI Portfolio
BI Portfolio
 
Fvcp Presentation Openoffice
Fvcp Presentation OpenofficeFvcp Presentation Openoffice
Fvcp Presentation Openoffice
 
Edisi1oktaceh
Edisi1oktacehEdisi1oktaceh
Edisi1oktaceh
 
Credit Its A Brand New Day
Credit Its A Brand New DayCredit Its A Brand New Day
Credit Its A Brand New Day
 
Ocean lifeguard expo 2010
Ocean lifeguard expo 2010Ocean lifeguard expo 2010
Ocean lifeguard expo 2010
 
Edisi Nasional 27 Maret
Edisi Nasional 27 MaretEdisi Nasional 27 Maret
Edisi Nasional 27 Maret
 
Edisi 28 Medan
Edisi 28 MedanEdisi 28 Medan
Edisi 28 Medan
 
Severe Weather2010 Mar12
Severe Weather2010 Mar12Severe Weather2010 Mar12
Severe Weather2010 Mar12
 
Edisi 7 Feb 2010
Edisi 7 Feb 2010Edisi 7 Feb 2010
Edisi 7 Feb 2010
 
12jan Aceh
12jan Aceh12jan Aceh
12jan Aceh
 
TIM Day in NY
TIM Day in NYTIM Day in NY
TIM Day in NY
 
Stres
StresStres
Stres
 
Edisi 2 Maret Medan
Edisi 2 Maret MedanEdisi 2 Maret Medan
Edisi 2 Maret Medan
 
2 Des Aceh
2 Des Aceh2 Des Aceh
2 Des Aceh
 
Skapa en sökmotorvänlig webbplats!
Skapa en sökmotorvänlig webbplats!Skapa en sökmotorvänlig webbplats!
Skapa en sökmotorvänlig webbplats!
 
Edisi 1 Maret Medan
Edisi 1 Maret MedanEdisi 1 Maret Medan
Edisi 1 Maret Medan
 
Top Flex 7 Unit One- phrasal verbs
Top Flex 7 Unit One- phrasal verbsTop Flex 7 Unit One- phrasal verbs
Top Flex 7 Unit One- phrasal verbs
 
Webinarium affiliate
Webinarium affiliateWebinarium affiliate
Webinarium affiliate
 

Semelhante a Fun with Ruby and Cocoa

From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016
From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016
From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016Susan Potter
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slidesharetomcopeland
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxbobmcwhirter
 
Advanced JavaScript Development
Advanced JavaScript DevelopmentAdvanced JavaScript Development
Advanced JavaScript DevelopmentJussi Pohjolainen
 
Bulding a reactive game engine with Spring 5 & Couchbase
Bulding a reactive game engine with Spring 5 & CouchbaseBulding a reactive game engine with Spring 5 & Couchbase
Bulding a reactive game engine with Spring 5 & CouchbaseAlex Derkach
 
DevOps in PHP environment
DevOps in PHP environment DevOps in PHP environment
DevOps in PHP environment Evaldo Felipe
 
Node.js basics
Node.js basicsNode.js basics
Node.js basicsBen Lin
 
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf Conference
 
Node Boot Camp
Node Boot CampNode Boot Camp
Node Boot CampTroy Miles
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends旻琦 潘
 
Getting Started with iBeacons (Designers of Things 2014)
Getting Started with iBeacons (Designers of Things 2014)Getting Started with iBeacons (Designers of Things 2014)
Getting Started with iBeacons (Designers of Things 2014)Daniel Luxemburg
 
Splunk n-box-splunk conf-2017
Splunk n-box-splunk conf-2017Splunk n-box-splunk conf-2017
Splunk n-box-splunk conf-2017Mohamad Hassan
 
Continuous Delivery: The Next Frontier
Continuous Delivery: The Next FrontierContinuous Delivery: The Next Frontier
Continuous Delivery: The Next FrontierCarlos Sanchez
 
MINCS - containers in the shell script (Eng. ver.)
MINCS - containers in the shell script (Eng. ver.)MINCS - containers in the shell script (Eng. ver.)
MINCS - containers in the shell script (Eng. ver.)Masami Hiramatsu
 
Présentation "Docker + Kubernetes" @ Pastis.tech #2
Présentation "Docker + Kubernetes" @ Pastis.tech #2Présentation "Docker + Kubernetes" @ Pastis.tech #2
Présentation "Docker + Kubernetes" @ Pastis.tech #2Blue Forest
 
Node.js - async for the rest of us.
Node.js - async for the rest of us.Node.js - async for the rest of us.
Node.js - async for the rest of us.Mike Brevoort
 
No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010Ilya Grigorik
 

Semelhante a Fun with Ruby and Cocoa (20)

From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016
From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016
From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBox
 
Advanced JavaScript Development
Advanced JavaScript DevelopmentAdvanced JavaScript Development
Advanced JavaScript Development
 
infra-as-code
infra-as-codeinfra-as-code
infra-as-code
 
Bulding a reactive game engine with Spring 5 & Couchbase
Bulding a reactive game engine with Spring 5 & CouchbaseBulding a reactive game engine with Spring 5 & Couchbase
Bulding a reactive game engine with Spring 5 & Couchbase
 
DevOps in PHP environment
DevOps in PHP environment DevOps in PHP environment
DevOps in PHP environment
 
Node.js basics
Node.js basicsNode.js basics
Node.js basics
 
Vagrant for real
Vagrant for realVagrant for real
Vagrant for real
 
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
 
Node Boot Camp
Node Boot CampNode Boot Camp
Node Boot Camp
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
 
Getting Started with iBeacons (Designers of Things 2014)
Getting Started with iBeacons (Designers of Things 2014)Getting Started with iBeacons (Designers of Things 2014)
Getting Started with iBeacons (Designers of Things 2014)
 
Splunk n-box-splunk conf-2017
Splunk n-box-splunk conf-2017Splunk n-box-splunk conf-2017
Splunk n-box-splunk conf-2017
 
MyShell - English
MyShell - EnglishMyShell - English
MyShell - English
 
Continuous Delivery: The Next Frontier
Continuous Delivery: The Next FrontierContinuous Delivery: The Next Frontier
Continuous Delivery: The Next Frontier
 
MINCS - containers in the shell script (Eng. ver.)
MINCS - containers in the shell script (Eng. ver.)MINCS - containers in the shell script (Eng. ver.)
MINCS - containers in the shell script (Eng. ver.)
 
Présentation "Docker + Kubernetes" @ Pastis.tech #2
Présentation "Docker + Kubernetes" @ Pastis.tech #2Présentation "Docker + Kubernetes" @ Pastis.tech #2
Présentation "Docker + Kubernetes" @ Pastis.tech #2
 
Node.js - async for the rest of us.
Node.js - async for the rest of us.Node.js - async for the rest of us.
Node.js - async for the rest of us.
 
No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010
 

Mais de Patrick Huesler

Technical Challenges of Developing a Facebook Game
Technical Challenges of Developing a Facebook GameTechnical Challenges of Developing a Facebook Game
Technical Challenges of Developing a Facebook GamePatrick Huesler
 
Culerity and Headless Full Stack Integration Testing
Culerity and Headless Full Stack Integration TestingCulerity and Headless Full Stack Integration Testing
Culerity and Headless Full Stack Integration TestingPatrick Huesler
 
Client Side Optimization
Client Side OptimizationClient Side Optimization
Client Side OptimizationPatrick Huesler
 
Building and deploying Cocoa applications with ChocTop
Building and deploying Cocoa applications with ChocTopBuilding and deploying Cocoa applications with ChocTop
Building and deploying Cocoa applications with ChocTopPatrick Huesler
 
Choctop Lightning talk EuRuKo 2010
Choctop Lightning talk EuRuKo 2010Choctop Lightning talk EuRuKo 2010
Choctop Lightning talk EuRuKo 2010Patrick Huesler
 
Small Cocoa Apps with MacRuby
Small Cocoa Apps with MacRubySmall Cocoa Apps with MacRuby
Small Cocoa Apps with MacRubyPatrick Huesler
 

Mais de Patrick Huesler (9)

Technical Challenges of Developing a Facebook Game
Technical Challenges of Developing a Facebook GameTechnical Challenges of Developing a Facebook Game
Technical Challenges of Developing a Facebook Game
 
Culerity and Headless Full Stack Integration Testing
Culerity and Headless Full Stack Integration TestingCulerity and Headless Full Stack Integration Testing
Culerity and Headless Full Stack Integration Testing
 
Client Side Optimization
Client Side OptimizationClient Side Optimization
Client Side Optimization
 
Building and deploying Cocoa applications with ChocTop
Building and deploying Cocoa applications with ChocTopBuilding and deploying Cocoa applications with ChocTop
Building and deploying Cocoa applications with ChocTop
 
Choctop Lightning talk EuRuKo 2010
Choctop Lightning talk EuRuKo 2010Choctop Lightning talk EuRuKo 2010
Choctop Lightning talk EuRuKo 2010
 
Small Cocoa Apps with MacRuby
Small Cocoa Apps with MacRubySmall Cocoa Apps with MacRuby
Small Cocoa Apps with MacRuby
 
Erlang, an overview
Erlang, an overviewErlang, an overview
Erlang, an overview
 
Migrating legacy data
Migrating legacy dataMigrating legacy data
Migrating legacy data
 
Active Record No No's
Active Record No No'sActive Record No No's
Active Record No No's
 

Último

Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkPixlogix Infotech
 
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical InfrastructureVarsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructureitnewsafrica
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 

Último (20)

Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App Framework
 
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical InfrastructureVarsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 

Fun with Ruby and Cocoa

  • 1. Ruby and Cocoa Facilitate development on OSX
  • 10. Ruby
  • 13.
  • 17. Cocoa
  • 18. Cocoa • Core Foundation
  • 19. Cocoa • Core Foundation • Appkit
  • 20. Cocoa • Core Foundation • Appkit • Core * (Audio/Video/Image/Data etc.)
  • 21. Cocoa • Core Foundation • Appkit • Core * (Audio/Video/Image/Data etc.) • Scripting bridge
  • 22. Cocoa • Core Foundation • Appkit • Core * (Audio/Video/Image/Data etc.) • Scripting bridge • others
  • 24. XCode
  • 26. NSMutableArray *anArray = [ [NSMutableArray alloc] init ]; [anArray addObject:@"Element 1"]; [anArray addObject:@"Element 2"]; [anArray addObject:@"Element 3"]; //Use a for each loop to iterate through the array for (NSString *s in anArray) { NSLog(s); } //Release the array [anArray release]
  • 27.
  • 29.
  • 31.
  • 32. HotCocoa picture shamelessly cropped from http://www.slideshare.net/mattetti/macruby-hotcocoa-presentation-by-rich-kilmer
  • 33. Scripting Bridge http://www.flickr.com/photos/bensonkua/2851908095/sizes/l/
  • 35. Good to know • Available commands for each application are in a .sdef file
  • 36. Good to know • Available commands for each application are in a .sdef file • Terminal.app/Contents/Resources/ Terminal.sdef
  • 37. Good to know • Available commands for each application are in a .sdef file • Terminal.app/Contents/Resources/ Terminal.sdef • gem rb-appscript (native extension so not for MacRuby)
  • 38. 1 <command name="do script" code="coredosc" 2 description="Runs a UNIX shell script or command."> 3 <cocoa class="TTDoScriptCommand"/> 4 <direct-parameter type="text" 5 description="The command to execute." optional="yes"/> 6 <parameter name="with command" 7 description="Data to be passed to the Terminal..." 8 code="cmnd" optional="yes" hidden="yes"> 9 <cocoa key="Command" /> 10 <type type="text" /> 11 <type type="any" /> <!-- support null case --> 12 </parameter> 13 <parameter name="in" 14 description="The tab in which to execute the command" 15 code="kfil" optional="yes"> 16 <cocoa key="Target" /> 17 <type type="tab" /> 18 <type type="window" /> 19 <type type="any" /> <!-- support null case --> 20 </parameter> 21 <result type="tab" 22 description="The tab the command was executed in." /> 23 </command> 24
  • 39.
  • 41. 1 #!/usr/bin/env ruby 2 require 'rubygems' 3 require 'appscript' 4 include Appscript 5 6 terminal = app('Terminal') 7 current_window = terminal.windows.first 8 current_tab = current_window.tabs.last 9 process = app("System Events").application_processes[ 10 "Terminal.app" 11 ] 12 13 process.keystroke('t', :using => :command_down) 14 terminal.do_script('top', :in => current_tab)
  • 42. 1 #!/usr/bin/env ruby 2 require 'rubygems' 3 require 'appscript' 4 include Appscript 5 6 terminal = app('Terminal') 7 current_window = terminal.windows.first 8 current_tab = current_window.tabs.last 9 process = app("System Events").application_processes[ 10 "Terminal.app" 11 ] 12 13 process.keystroke('t', :using => :command_down) 14 terminal.do_script('top', :in => current_tab)
  • 43. 1 #!/usr/bin/env ruby 2 require 'rubygems' 3 require 'appscript' 4 include Appscript 5 6 terminal = app('Terminal') 7 current_window = terminal.windows.first 8 current_tab = current_window.tabs.last 9 process = app("System Events").application_processes[ 10 "Terminal.app" 11 ] 12 13 process.keystroke('t', :using => :command_down) 14 terminal.do_script('top', :in => current_tab)
  • 44. 7 current_window = terminal.windows.first 8 current_tab = current_window.tabs.last 9 process = app("System Events").application_processes[ 10 "Terminal.app" 11 ] 12 13 process.keystroke('t', :using => :command_down) 14 terminal.do_script('top', :in => current_tab)
  • 47. Problems with MacRuby • Some methods don’t seem to be available
  • 49. 1 #!/usr/bin/env macruby 2 3 framework 'ScriptingBridge' 4 5 itunes = SBApplication.applicationWithBundleIdentifier( 6 "com.apple.iTunes" 7 ) 8 library = itunes.sources.objectWithName ("Library") 9 10 library.userPlaylists.each do |playlist| 11 puts playlist.name 12 end
  • 50. 2 3 framework 'ScriptingBridge' 4 5 itunes = SBApplication.applicationWithBundleIdentifier( 6 "com.apple.iTunes" 7 ) 8 library = itunes.sources.objectWithName ("Library") 9 10 library.userPlaylists.each do |playlist| 11 puts playlist.name 12 end
  • 51. 2 3 framework 'ScriptingBridge' 4 5 itunes = SBApplication.applicationWithBundleIdentifier( 6 "com.apple.iTunes" 7 ) 8 library = itunes.sources.objectWithName ("Library") 9 10 library.userPlaylists.each do |playlist| 11 puts playlist.name 12 end
  • 53. 1 #!/usr/bin/env macruby 2 framework 'CoreLocation' 3 4 loc = CLLocationManager.alloc.init 5 loc.delegate = self 6 loc.startUpdatingLocation 7 8 # keep the script running 9 NSRunLoop.currentRunLoop.runUntilDate( 10 NSDate.distantFuture 11 )
  • 54. 1 #!/usr/bin/env macruby 2 framework 'CoreLocation' 3 4 loc = CLLocationManager.alloc.init 5 loc.delegate = self 6 loc.startUpdatingLocation 7 8 # keep the script running 9 NSRunLoop.currentRunLoop.runUntilDate( 10 NSDate.distantFuture 11 )
  • 55. 1 def locationManager( 2 manager, 3 didUpdateToLocation: new_location, 4 fromLocation: old_location 5 ) 6 7 puts "loc: #{new_location.description}" 8 end
  • 56. 2 framework 'CoreLocation' 3 4 loc = CLLocationManager.alloc.init 5 loc.delegate = self 6 loc.startUpdatingLocation 7 8 # keep the script running 9 NSRunLoop.currentRunLoop.runUntilDate( 10 NSDate.distantFuture 11 )
  • 57. 1 #!/usr/bin/env macruby 2 framework 'CoreLocation' 3 4 def locationManager(manager, 5 didUpdateToLocation: new_location, 6 fromLocation: old_location 7 ) 8 puts "location: #{new_location.description}" 9 end 10 11 loc = CLLocationManager.alloc.init 12 loc.delegate = self 13 loc.startUpdatingLocation 14 15 # keep the script running 16 NSRunLoop.currentRunLoop.runUntilDate( 17 NSDate.distantFuture 18 )
  • 58. Grand Central Dispatch
  • 61. Grand Central Dispatch • MacRuby only • Synchronous
  • 62. Grand Central Dispatch • MacRuby only • Synchronous • Asynchronous
  • 63. Grand Central Dispatch • MacRuby only • Synchronous • Asynchronous • Parallel
  • 64. Grand Central Dispatch • MacRuby only • Synchronous • Asynchronous • Parallel • Synchronization
  • 66. 1 #!/usr/bin/env macruby 2 3 queue = Dispatch::Queue.new( 4 'ch.huesler-informatik.scotrubyconf.gcd' 5 ) 6 7 queue.async do 8 puts 'Starting asyn. NONE BLOCKING!' 9 sleep 2.00 10 puts "Finished asyn" 11 end 12 puts "code not being blocked" 13 14 NSRunLoop.currentRunLoop.runUntilDate( 15 NSDate.distantFuture 16 ) 17
  • 67. 1 #!/usr/bin/env macruby 2 3 queue = Dispatch::Queue.new( 4 'ch.huesler-informatik.scotrubyconf.gcd' 5 ) 6 7 queue.async do 8 puts 'Starting asyn. NONE BLOCKING!' 9 sleep 2.00 10 puts "Finished asyn" 11 end 12 puts "code not being blocked" 13 14 NSRunLoop.currentRunLoop.runUntilDate( 15 NSDate.distantFuture 16 ) 17
  • 68. 7 queue.async do 8 puts 'Starting asyn. NONE BLOCKING!' 9 sleep 2.00 10 puts "Finished asyn" 11 end 12 puts "code not being blocked" 13 14 NSRunLoop.currentRunLoop.runUntilDate( 15 NSDate.distantFuture 16 ) 17
  • 70. 1 #!/usr/bin/env macruby 2 3 queue = Dispatch::Queue.new( 4 'ch.huesler-informatik.scotrubyconf.gcd' 5 ) 6 7 queue.sync do 8 puts 'Starting sync. BLOCKING!' 9 sleep 3.0 10 puts 'Finished sync' 11 end 12 puts "code being blocked" 13 14 NSRunLoop.currentRunLoop.runUntilDate( 15 NSDate.distantFuture 16 ) 17
  • 72. 1 #!/usr/bin/env macruby 2 3 worker_queue = Dispatch::Queue.new( 4 'ch.huesler-informatik.scotrubyconf.gcd' 5 ) 6 group = Dispatch::Group.new 7 8 0.upto(10) do |i| 9 puts "Dispatch #{i} to GCD" 10 worker_queue.async(group) do 11 puts "working on #{i}" 12 end 13 end 14 puts "waiting for gcd" 15 group.wait 16 puts "done" 17
  • 73. 1 #!/usr/bin/env macruby 2 3 worker_queue = Dispatch::Queue.new( 4 'ch.huesler-informatik.scotrubyconf.gcd' 5 ) 6 group = Dispatch::Group.new 7 8 0.upto(10) do |i| 9 puts "Dispatch #{i} to GCD" 10 worker_queue.async(group) do 11 puts "working on #{i}" 12 end 13 end 14 puts "waiting for gcd" 15 group.wait 16 puts "done" 17
  • 74. 7 8 0.upto(10) do |i| 9 puts "Dispatch #{i} to GCD" 10 worker_queue.async(group) do 11 puts "working on #{i}" 12 end 13 end 14 puts "waiting for gcd" 15 group.wait 16 puts "done" 17
  • 76. 1 #!/usr/bin/env macruby 2 3 group = Dispatch::Group.new 4 result = [] 5 1.upto(10).each do |i| 6 Dispatch::Queue.concurrent.async(group) do 7 sleep 2 8 result << i 9 end 10 end 11 group.wait 12 puts result.inspect
  • 78. 1 #!/usr/bin/env ruby 2 require "osx/cocoa" 3 include OSX 4 5 file_name = 'Info.plist' 6 plist = NSDictionary.dictionaryWithContentsOfFile( 7 file_name 8 ) 9 10 plist['CFBundleVersion'] = '2.0.1' 11 12 plist.writeToFile_atomically( 13 file_name, 14 true 15 )
  • 79. 1 #!/usr/bin/env ruby 2 require "osx/cocoa" 3 include OSX 4 5 file_name = 'Info.plist' 6 plist = NSDictionary.dictionaryWithContentsOfFile( 7 file_name 8 ) 9 10 plist['CFBundleVersion'] = '2.0.1' 11 12 plist.writeToFile_atomically( 13 file_name, 14 true 15 )
  • 80. 3 include OSX 4 5 file_name = 'Info.plist' 6 plist = NSDictionary.dictionaryWithContentsOfFile( 7 file_name 8 ) 9 10 plist['CFBundleVersion'] = '2.0.1' 11 12 plist.writeToFile_atomically( 13 file_name, 14 true 15 )
  • 83. Details • MacRuby has issues with void pointer (patch pending)
  • 84. Details • MacRuby has issues with void pointer (patch pending) • Use objective c wrapper instead (dynlib or bundle)
  • 85. Details • MacRuby has issues with void pointer (patch pending) • Use objective c wrapper instead (dynlib or bundle) • Generate metadata to make it work
  • 86. Details • MacRuby has issues with void pointer (patch pending) • Use objective c wrapper instead (dynlib or bundle) • Generate metadata to make it work
  • 87. 1 export FILE_PATH = ~/Library/BridgeSupport 2 export FRAMEWORK_PATH = ~/Library/BridgeSupport/ Security.bridgesupport 3 mkdir $FILE_PATH 4 gen_bridge_metadata -f Security -o $FRAMEWORK_PATH
  • 88. 1 require 'osx/cocoa' 2 include OSX 3 require_framework 'Security' 4 5 # Set up some relevant variables 6 7 service = "ch.huesler-informatik.scotrubyconf.keychain" 8 account = "Highlander" 9 original_password = "Rrrueby" 10 11 # Add password 12 SecKeychainAddGenericPassword( 13 nil, 14 service.length, 15 service, 16 account.length, 17 account, 18 original_password.length, 19 original_password, 20 nil 21 )
  • 89. 1 require 'osx/cocoa' 2 include OSX 3 require_framework 'Security' 4 5 # Set up some relevant variables 6 7 service = "ch.huesler-informatik.scotrubyconf.keychain" 8 account = "Highlander" 9 original_password = "Rrrueby" 10 11 # Add password 12 SecKeychainAddGenericPassword( 13 nil, 14 service.length, 15 service, 16 account.length, 17 account, 18 original_password.length, 19 original_password, 20 nil 21 )
  • 90. 1 # Add password 2 SecKeychainAddGenericPassword( 3 nil, 4 service.length, 5 service, 6 account.length, 7 account, 8 original_password.length, 9 original_password, 10 nil 11 )
  • 91. 1 # Query the keychain 2 status, *password = SecKeychainFindGenericPassword( 3 nil, 4 service.length, 5 service, 6 account.length, 7 account 8 )
  • 92. 1 # Password-related data. Shifting pointers 2 length = password.shift 3 data = password.shift 4 plain_password = data.bytestr(length) 5 6 puts "Password: #{plain_password}"