<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>RubyCocoa Resources: Recent Changes</title>
    <link>http://www.rubycocoa.com/</link>
    <description>RubyCocoa Resources: Recent Changes</description>
    <language>en-us</language>
    <ttl>40</ttl>
    <item>
      <title>Michael Black: Put it to work</title>
      <description>&lt;p&gt;Our code-to-talk ratio has gotten dangerously low. Let&amp;#8217;s fix that by putting our Apple Remote controller to work.  Put the source from the previous two parts of this chapter into a Ruby file called &amp;#8220;remote.rb&amp;#8221;, start irb from the Terminal, and type the commands in the transcript below:&lt;/p&gt;


&lt;pre&gt;
&amp;gt;&amp;gt; require 'remote'
=&amp;gt; true
&amp;gt;&amp;gt; d = AppleRemoteDelegate.alloc.init
=&amp;gt; #&amp;lt;AppleRemoteDelegate:0x3691e2 class='AppleRemoteDelegate' id=0x5734a0&amp;gt;
&amp;gt;&amp;gt; a = OSX::AppleRemote.alloc.initWithDelegate_(d)
=&amp;gt; #&amp;lt;OSX::AppleRemote:0x367c52 class='AppleRemote' id=0x5773c0&amp;gt;
&amp;gt;&amp;gt; a.startListening 0
=&amp;gt; nil
&amp;gt;&amp;gt; OSX::NSApplication.sharedApplication.run
&lt;/pre&gt;

Next, start pressing buttons on your remote.  You should see something like the following listing.  You can easily use this to find the codes for each button, or if you prefer, go back to Martin&amp;#8217;s &lt;strong&gt;RemoteControl.h&lt;/strong&gt; and look at the &lt;strong&gt;_RemoteControlEventIdentifier&lt;/strong&gt; enum.
&lt;pre&gt;
button 2, pressed 1
button 2, pressed 0
button 2, pressed 1
button 2, pressed 0
button 4, pressed 1
button 4, pressed 0
button 32, pressed 1
button 32, pressed 0
&lt;/pre&gt;

	&lt;p&gt;That&amp;#8217;s it!  There&amp;#8217;s obviously some complicated stuff happening under the covers of the RubyCocoa bridge, and there&amp;#8217;s probably also some ways it can be improved.  But with the right understanding and incantations, the bridge works right now and can be used to do some dramatic things very quickly.  Consider how much more difficult this would have been if Martin&amp;#8217;s package was written in C or C++.  We would have needed to either write the Ruby wrapper ourselves or use a tool like &lt;a href="http://www.swig.org"&gt;&lt;span class="caps"&gt;SWIG&lt;/span&gt;&lt;/a&gt; to generate wrapper glue code.  With Objective-C and RubyCocoa, we were able to use Martin&amp;#8217;s package with &lt;strong&gt;no glue code&lt;/strong&gt; and &lt;strong&gt;no compilation&lt;/strong&gt;.  Everything we needed to do was done at runtime.  Amazing?&lt;/p&gt;</description>
      <pubDate>Mon, 25 Feb 2008 11:32:16 GMT</pubDate>
      <guid>http://www.rubycocoa.com/appleremote/2#page3</guid>
      <link>http://www.rubycocoa.com/appleremote/2#page3</link>
    </item>
    <item>
      <title>Michael Black: Write a delegate</title>
      <description>&lt;p&gt;Next we need to write a delegate class. Here&amp;#8217;s a simple one to get you started.&lt;/p&gt;


	&lt;div class='figure'&gt;
&lt;span class='caption'&gt;Provide a delegate [ruby]&lt;/span&gt;
&lt;div class='body'&gt;&lt;link rel='stylesheet' type='text/css' href='/stylesheets/ruby.css' /&gt;&lt;div class='ruby'&gt;&lt;pre&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;AppleRemoteDelegate&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSObject&lt;/span&gt;

&lt;span class="ident"&gt;addRubyMethod_withType&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;sendRemoteButtonEvent:pressedDown:remoteControl:&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;v@:ii@&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;  

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;sendRemoteButtonEvent_pressedDown_remoteControl&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;buttonIdentifier&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;pressedDown&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;remoteControl&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;button &lt;span class="expr"&gt;#{buttonIdentifier}&lt;/span&gt;, pressed &lt;span class="expr"&gt;#{pressedDown}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;Our delegate has one method of interest, &lt;strong&gt;sendRemoteButtonEvent_pressedDown_remoteControl&lt;/strong&gt;, which simply prints the values passed to it by the controller.  It&amp;#8217;s preceeded by an interesting statement, the &lt;strong&gt;addRubyMethod_withType&lt;/strong&gt; call.  The purpose of this statement is to give the Objective-C runtime the correct signature to use for our delegate method.  Its two arguments are the selector name (a string), and a string containing the encoded signature.  In this case, the signature is six characters long.  The first character indicates that the return value of the method is void.  The next two are superfluous to us, but important to the Objective-C runtime.  The &amp;#8217;@&amp;#8217; means that the message is to be sent to an object of Objective-C type &lt;strong&gt;id&lt;/strong&gt;, and the &amp;#8217;:&amp;#8217; indicates that the message is described by a special Objective-C type called a selector.  These two values are the same for all Cocoa messages.  The next three characters give the types of the three arguments to the method, in this case they are two integers and an &lt;strong&gt;id&lt;/strong&gt; type.&lt;/p&gt;


	&lt;p&gt;You can find a full listing of type codes on Apple&amp;#8217;s Developer Connection web site. Look &lt;a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/chapter_5_section_7.html#//apple_ref/doc/uid/TP30001163-CH9-TPXREF165"&gt;here&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;But why, you may ask, did we need to go to this trouble?  The answer to that is a bit complex.  If you&amp;#8217;d rather not get into it, just skip to the next section, but remember to look back here if you ever write Ruby code that gets called by Objective-C code that is not part of Cocoa.&lt;/p&gt;


	&lt;p&gt;Martin&amp;#8217;s controller is written in Objective-C and uses the Objective-C runtime environment to send messages to its delegate.  When the Objective-C runtime sends a message to an object, it does so with a low-level function that looks for a handler in the method table of the receiving object&amp;#8217;s class.  When the receiving object is an Objective-C wrapper for a RubyCocoa object, normally there&amp;#8217;s no corresponding handler in its method table (with one exception to be explained later).  When no handler is present, that low-level message sending function tries to package the message into an &lt;strong&gt;NSInvocation&lt;/strong&gt; object which it resends to the target object with the &lt;strong&gt;forwardInvocation&lt;/strong&gt; method. Then the target can pass the message along to an object capable of responding to it.  In the case of RubyCocoa, this &lt;strong&gt;NSInvocation&lt;/strong&gt; gets handled by bridge code that makes a corresponding Ruby method call, converts the Ruby return value into the appropriate Objective-C type, and returns control to the message sender.  But for the sender to be able to construct the invocation, a special message must first be sent to the Objective-C wrapper object.  This message is called &lt;strong&gt;methodSignatureForSelector:&lt;/strong&gt; and its purpose is to provide the signature for the message to be sent.&lt;/p&gt;


	&lt;p&gt;In RubyCocoa, there&amp;#8217;s a &lt;strong&gt;methodSignatureForSelector&lt;/strong&gt; defined for Objective-C wrapper objects, but it only knows about selectors associated with Cocoa classes&amp;#8212;the RubyCocoa build process extracts them from Cocoa headers and hard-codes them into the RubyCocoa source files.  (If you&amp;#8217;d like to see them for yourself, look at  &lt;strong&gt;framework/src/objc/DummyProtocolHandler.m&lt;/strong&gt; in the RubyCocoa source distribution.)&lt;/p&gt;


	&lt;p&gt;Martin&amp;#8217;s controller uses a protocol that is unknown to the RubyCocoa bridge.  So when RubyCocoa&amp;#8217;s &lt;strong&gt;methodSignatureForSelector&lt;/strong&gt; gets called, it returns a default signature that assumes that all arguments and the return value are of type &lt;strong&gt;id&lt;/strong&gt; (Objective-C objects). One desperate way to fix this problem is to explicitly add the protocol to &lt;strong&gt;DummyProtocolHandler.m&lt;/strong&gt; and rebuild the RubyCocoa sources, but in most cases, the &lt;strong&gt;addRubyMethod_withType&lt;/strong&gt; makes that unnecessary.&lt;/p&gt;


	&lt;p&gt;The &lt;strong&gt;addRubyMethod_withType&lt;/strong&gt; method doesn&amp;#8217;t do anything to change &lt;strong&gt;methodSignatureForSelector&lt;/strong&gt;.  Instead, it resolves the problem by adding a message handler with the specified signature directly to the Objective-C wrapper class (there&amp;#8217;s a unique Objective-C wrapper class for each wrapped Ruby class).  When it is used to set the correct signature, messages are sent and handled correctly.  If it is used incorrectly or omitted, all kinds of havoc will follow.&lt;/p&gt;


	&lt;p&gt;Whew. That&amp;#8217;s a lot of writing to explain one line of code. But without that line, the invocation would be sent with the wrong signature and our program would behave mysteriously&amp;#8212;and possibly crash.&lt;/p&gt;


	&lt;p&gt;Earlier in this section I wrote that there&amp;#8217;s an exception to the general rule that bridged method calls are handled by invocations.  We actually just saw one exception, when we used &lt;strong&gt;addRubyMethod_withType&lt;/strong&gt; to put an entry into the wrapper class&amp;#8217;s method table.  But the exception I was indicating is &lt;strong&gt;ns_overrides&lt;/strong&gt;, the mysterious function that must be called when any Objective-C method is overridden in a RubyCocoa class.  It is necessary because when messages are sent to RubyCocoa&amp;#8217;s Objective-C wrapper objects, any message handler defined on a superclass will handle the message and prevent it from being wrapped in an &lt;strong&gt;NSInvocation&lt;/strong&gt; and sent to the RubyCocoa class.  &lt;strong&gt;ns_overrides&lt;/strong&gt; prevents this by adding an entry to the wrapper class&amp;#8217;s method table.&lt;/p&gt;</description>
      <pubDate>Mon, 25 Feb 2008 11:27:06 GMT</pubDate>
      <guid>http://www.rubycocoa.com/appleremote/2#page2</guid>
      <link>http://www.rubycocoa.com/appleremote/2#page2</link>
    </item>
    <item>
      <title>Michael Black: Rebuild it as a Framework</title>
      <description>&lt;p&gt;Let&amp;#8217;s begin by creating a framework containing Martin&amp;#8217;s &lt;strong&gt;AppleRemote&lt;/strong&gt; controller.  First, in the &lt;strong&gt;Groups &amp;#38; Files&lt;/strong&gt; pane, expand the &lt;strong&gt;Targets&lt;/strong&gt; item, click on the &lt;strong&gt;AppleRemote&lt;/strong&gt; target to select it, and press the delete key to delete it.  We&amp;#8217;re going to replace it with a new build target with the same name.  To add the new target, first select the &lt;strong&gt;Project-&amp;gt;New Target&amp;#8230;&lt;/strong&gt; menu item.  You&amp;#8217;ll then see a dialog box with a list of different project types.  Choose the &lt;strong&gt;Cocoa-&amp;gt;Framework&lt;/strong&gt; type and press the &lt;strong&gt;Next&lt;/strong&gt; button.  Name the target &amp;#8220;AppleRemote&amp;#8221; (don&amp;#8217;t type the quotes) and click the &lt;strong&gt;Finish&lt;/strong&gt; button.&lt;/p&gt;


	&lt;p&gt;Now you&amp;#8217;ll need to add some files to the new target.  Back in the &lt;strong&gt;Groups &amp;#38; Files&lt;/strong&gt; pane, expand the &lt;strong&gt;AppleRemote&lt;/strong&gt; target to reveal the build steps.  Then expand the &lt;strong&gt;Base Classes&lt;/strong&gt; and &lt;strong&gt;Devices&lt;/strong&gt; folder near the top of the pane and drag &lt;strong&gt;RemoteControl.h&lt;/strong&gt;, &lt;strong&gt;HIDRemoteControlDevice.h&lt;/strong&gt; and &lt;strong&gt;AppleRemote.h&lt;/strong&gt; to the &lt;strong&gt;Copy Headers&lt;/strong&gt; step and &lt;strong&gt;RemoteControl.m&lt;/strong&gt;, &lt;strong&gt;HIDRemoteControlDevice.m&lt;/strong&gt; and &lt;strong&gt;AppleRemote.m&lt;/strong&gt; to the &lt;strong&gt;Compile Sources&lt;/strong&gt; step.  Then expand the &lt;strong&gt;Frameworks&lt;/strong&gt; folder and drag the &lt;strong&gt;IOKit.framework&lt;/strong&gt; and &lt;strong&gt;Carbon.framework&lt;/strong&gt; to the &lt;strong&gt;Link Binary With Libraries&lt;/strong&gt; step.&lt;/p&gt;


	&lt;p&gt;Under the &lt;strong&gt;Project&lt;/strong&gt; menu, set the &lt;strong&gt;Active Build Configuration&lt;/strong&gt; to &lt;strong&gt;Release&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;Next, build the framework.  Here is a picture of my Xcode project window just after my build completed.
&lt;img src="/files/appleremote/Xcode_view.png"&gt;&lt;/p&gt;


	&lt;p&gt;Finally, move the result (AppleRemote.framework) from the &lt;strong&gt;build/Release&lt;/strong&gt; directory to &lt;strong&gt;/Library/Frameworks&lt;/strong&gt;.&lt;/p&gt;</description>
      <pubDate>Mon, 25 Feb 2008 11:13:39 GMT</pubDate>
      <guid>http://www.rubycocoa.com/appleremote/1#page2</guid>
      <link>http://www.rubycocoa.com/appleremote/1#page2</link>
    </item>
    <item>
      <title>Michael Black: A quick introduction</title>
      <description>&lt;p&gt;Recently I was planning a presentation on RubyCocoa.  I had prepared a demo application to show during my talk and decided that it would be fun to show my presentation slides from my demo app.  I quickly found that Keynote could export my slides as .png files, and it didn&amp;#8217;t take long to get them loaded into a custom image viewer that used an NSImageView to display the slides.  But one thing was missing: with Keynote, I could control my presentation with my new Apple Remote.  I wanted to be able to do the same thing from Ruby.&lt;/p&gt;


	&lt;p&gt;Thanks to Google, Martin Kahr, Objective-C, and RubyCocoa, less than 30 minutes later I had exactly what I wanted.  A search for &lt;a href="http://www.google.com/search?client=safari&amp;#38;rls=en&amp;#38;q=apple+remote+objective-c&amp;#38;ie=UTF-8&amp;#38;oe=UTF-8"&gt;&amp;#8216;Apple Remote Objective-C&amp;#8217;&lt;/a&gt; took me directly to &lt;a href="http://www.martinkahr.com/source-code"&gt;Martin&amp;#8217;s source code page&lt;/a&gt;, where I found the source for his small demo application.&lt;/p&gt;


	&lt;p&gt;Let&amp;#8217;s switch from past to present and do the rest together.&lt;/p&gt;


	&lt;p&gt;Download the source from Martin&amp;#8217;s web site.  As I write this, &lt;a href="http://www.martinkahr.com/files/source/RemoteControlWrapper_R962.tgz"&gt;here&lt;/a&gt; is the current version of his demo application.  Inside the archive, you&amp;#8217;ll find an Xcode project.  Build and run it.  The result will be an application window like the one below.&lt;/p&gt;


&lt;div style="float:left; margin-right:10px"&gt;
&lt;img src="/files/appleremote/AppleRemoteTest.png"&gt;
&lt;/div&gt;

	&lt;p&gt;Pressing buttons on your remote will cause red circles to appear on the corresponding parts of the image.  In the window shown, I&amp;#8217;m holding the right &amp;#8220;forward&amp;#8221; button down.&lt;/p&gt;


	&lt;p&gt;There are three significant Objective-C classes in the demo application, each with its own pair of header and source files.  &lt;strong&gt;RemoteFeedbackView&lt;/strong&gt; provides the contents of the application window, &lt;strong&gt;AppleRemote&lt;/strong&gt; handles communication with the remote control, and &lt;strong&gt;MainController&lt;/strong&gt; brings the two together.  If you look at its source in &lt;strong&gt;MainController.m&lt;/strong&gt;, you&amp;#8217;ll see that Martin has designed a very easy to use interface that uses a common Objective-C pattern: delegation.  In its &lt;strong&gt;awakeFromNib&lt;/strong&gt; method, the &lt;strong&gt;MainController&lt;/strong&gt; gets a singleton object representing the Apple Remote (using another common Objective-C pattern, the shared object).  Then the controller sets itself as the delegate of the &lt;strong&gt;&amp;#91;AppleRemote sharedRemote&amp;#93;&lt;/strong&gt;. It then waits for button presses, which cause the Apple Remote handler to send an &lt;strong&gt;appleRemoteButton:pressedDown:&lt;/strong&gt; message to the delegate, which displays a status message and forwards the button press information to the view.&lt;/p&gt;


	&lt;p&gt;Feel free to read through the code in &lt;strong&gt;AppleRemote.m&lt;/strong&gt;; it contains some mysterious calls to Apple&amp;#8217;s &lt;span class="caps"&gt;HID&lt;/span&gt; (human interface device) manager that could easily take hours to fully understand.  But by now we already know enough to use Martin&amp;#8217;s Apple Remote interface from Ruby.&lt;br clear="all"/&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 25 Feb 2008 11:09:56 GMT</pubDate>
      <guid>http://www.rubycocoa.com/appleremote/1#page1</guid>
      <link>http://www.rubycocoa.com/appleremote/1#page1</link>
    </item>
    <item>
      <title>Michael Black: A quick introduction</title>
      <description>&lt;p&gt;Recently I was planning a presentation on RubyCocoa.  I had prepared a demo application to show during my talk and decided that it would be fun to show my presentation slides from my demo app.  I quickly found that Keynote could export my slides as .png files, and it didn&amp;#8217;t take long to get them loaded into a custom image viewer that used an NSImageView to display the slides.  But one thing was missing: with Keynote, I could control my presentation with my new Apple Remote.  I wanted to be able to do the same thing from Ruby.&lt;/p&gt;


	&lt;p&gt;Thanks to Google, Martin Kahr, Objective-C, and RubyCocoa, less than 30 minutes later I had exactly what I wanted.  A search for &lt;a href="http://www.google.com/search?client=safari&amp;#38;rls=en&amp;#38;q=apple+remote+objective-c&amp;#38;ie=UTF-8&amp;#38;oe=UTF-8"&gt;&amp;#8216;Apple Remote Objective-C&amp;#8217;&lt;/a&gt; took me directly to &lt;a href="http://www.martinkahr.com/source-code"&gt;Martin&amp;#8217;s source code page&lt;/a&gt;, where I found the source for his small demo application.&lt;/p&gt;


	&lt;p&gt;Let&amp;#8217;s switch from past to present and do the rest together.&lt;/p&gt;


	&lt;p&gt;Download the source from Martin&amp;#8217;s web site.  As I write this, &lt;a href="http://www.martinkahr.com/files/source/AppleRemoteSource_R80.tgz"&gt;here&lt;/a&gt; is the current version of his demo application.  Inside the archive, you&amp;#8217;ll find an Xcode project.  Build and run it.  The result will be an application window like the one below.&lt;/p&gt;


&lt;div style="float:left; margin-right:10px"&gt;
&lt;img src="/files/appleremote/AppleRemoteTest.png"&gt;
&lt;/div&gt;

	&lt;p&gt;Pressing buttons on your remote will cause red circles to appear on the corresponding parts of the image.  In the window shown, I&amp;#8217;m holding the right &amp;#8220;forward&amp;#8221; button down.&lt;/p&gt;


	&lt;p&gt;There are three significant Objective-C classes in the demo application, each with its own pair of header and source files.  &lt;strong&gt;RemoteFeedbackView&lt;/strong&gt; provides the contents of the application window, &lt;strong&gt;AppleRemote&lt;/strong&gt; handles communication with the remote control, and &lt;strong&gt;MainController&lt;/strong&gt; brings the two together.  If you look at its source in &lt;strong&gt;MainController.m&lt;/strong&gt;, you&amp;#8217;ll see that Martin has designed a very easy to use interface that uses a common Objective-C pattern: delegation.  In its &lt;strong&gt;awakeFromNib&lt;/strong&gt; method, the &lt;strong&gt;MainController&lt;/strong&gt; gets a singleton object representing the Apple Remote (using another common Objective-C pattern, the shared object).  Then the controller sets itself as the delegate of the &lt;strong&gt;&amp;#91;AppleRemote sharedRemote&amp;#93;&lt;/strong&gt;. It then waits for button presses, which cause the Apple Remote handler to send an &lt;strong&gt;appleRemoteButton:pressedDown:&lt;/strong&gt; message to the delegate, which displays a status message and forwards the button press information to the view.&lt;/p&gt;


	&lt;p&gt;Feel free to read through the code in &lt;strong&gt;AppleRemote.m&lt;/strong&gt;; it contains some mysterious calls to Apple&amp;#8217;s &lt;span class="caps"&gt;HID&lt;/span&gt; (human interface device) manager that could easily take hours to fully understand.  But by now we already know enough to use Martin&amp;#8217;s Apple Remote interface from Ruby.&lt;br clear="all"/&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 25 Feb 2008 11:04:58 GMT</pubDate>
      <guid>http://www.rubycocoa.com/appleremote/1#page1</guid>
      <link>http://www.rubycocoa.com/appleremote/1#page1</link>
    </item>
    <item>
      <title>Michael Black: Rebuild it as a Framework</title>
      <description>&lt;p&gt;Let&amp;#8217;s begin by creating a framework containing Martin&amp;#8217;s &lt;strong&gt;AppleRemote&lt;/strong&gt; controller.  First, in the &lt;strong&gt;Groups &amp;#38; Files&lt;/strong&gt; pane, expand the &lt;strong&gt;Targets&lt;/strong&gt; item, click on the &lt;strong&gt;AppleRemote&lt;/strong&gt; target to select it, and press the delete key to delete it.  We&amp;#8217;re going to replace it with a new build target with the same name.  To add the new target, first select the &lt;strong&gt;Project-&amp;gt;New Target&amp;#8230;&lt;/strong&gt; menu item.  You&amp;#8217;ll then see a dialog box with a list of different project types.  Choose the &lt;strong&gt;Cocoa-&amp;gt;Framework&lt;/strong&gt; type and press the &lt;strong&gt;Next&lt;/strong&gt; button.  Name the target &amp;#8220;AppleRemote&amp;#8221; (don&amp;#8217;t type the quotes) and click the &lt;strong&gt;Finish&lt;/strong&gt; button.&lt;/p&gt;


	&lt;p&gt;Now you&amp;#8217;ll need to add some files to the new target.  Back in the &lt;strong&gt;Groups &amp;#38; Files&lt;/strong&gt; pane, expand the &lt;strong&gt;AppleRemote&lt;/strong&gt; target to reveal the build steps.  Then expand the &lt;strong&gt;Base Classes&lt;/strong&gt; folder near the top of the pane and drag &lt;strong&gt;RemoteControl.h&lt;/strong&gt; to the &lt;strong&gt;Copy Headers&lt;/strong&gt; step and &lt;strong&gt;RemoteControl.m&lt;/strong&gt; to the &lt;strong&gt;Compile Sources&lt;/strong&gt; step.  Then expand the &lt;strong&gt;Frameworks&lt;/strong&gt; folder and drag the &lt;strong&gt;IOKit.framework&lt;/strong&gt; to the &lt;strong&gt;Link Binary With Libraries&lt;/strong&gt; step.&lt;/p&gt;


	&lt;p&gt;Under the &lt;strong&gt;Project&lt;/strong&gt; menu, set the &lt;strong&gt;Active Build Configuration&lt;/strong&gt; to &lt;strong&gt;Release&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;Next, build the framework.  Here is a picture of my Xcode project window just after my build completed.
&lt;img src="/files/appleremote/Xcode_view.png"&gt;&lt;/p&gt;


	&lt;p&gt;Finally, move the result (AppleRemote.framework) from the &lt;strong&gt;build/Release&lt;/strong&gt; directory to &lt;strong&gt;/Library/Frameworks&lt;/strong&gt;.&lt;/p&gt;</description>
      <pubDate>Mon, 25 Feb 2008 10:34:24 GMT</pubDate>
      <guid>http://www.rubycocoa.com/appleremote/1#page2</guid>
      <link>http://www.rubycocoa.com/appleremote/1#page2</link>
    </item>
    <item>
      <title>Michael Black: A quick introduction</title>
      <description>&lt;p&gt;Recently I was planning a presentation on RubyCocoa.  I had prepared a demo application to show during my talk and decided that it would be fun to show my presentation slides from my demo app.  I quickly found that Keynote could export my slides as .png files, and it didn&amp;#8217;t take long to get them loaded into a custom image viewer that used an NSImageView to display the slides.  But one thing was missing: with Keynote, I could control my presentation with my new Apple Remote.  I wanted to be able to do the same thing from Ruby.&lt;/p&gt;


	&lt;p&gt;Thanks to Google, Martin Kahr, Objective-C, and RubyCocoa, less than 30 minutes later I had exactly what I wanted.  A search for &lt;a href="http://www.google.com/search?client=safari&amp;#38;rls=en&amp;#38;q=apple+remote+objective-c&amp;#38;ie=UTF-8&amp;#38;oe=UTF-8"&gt;&amp;#8216;Apple Remote Objective-C&amp;#8217;&lt;/a&gt; took me directly to &lt;a href="http://www.martinkahr.com/source-code"&gt;Martin&amp;#8217;s source code page&lt;/a&gt;, where I found the source for his small demo application.&lt;/p&gt;


	&lt;p&gt;Let&amp;#8217;s switch from past to present and do the rest together.&lt;/p&gt;


	&lt;p&gt;Download the source from Martin&amp;#8217;s web site.  As I write this, &lt;a href="http://www.martinkahr.com/files/source/RemoteControlWrapper_R962.tgz"&gt;here&lt;/a&gt; is the current version of his demo application.  Inside the archive, you&amp;#8217;ll find an Xcode project.  Build and run it.  The result will be an application window like the one below.&lt;/p&gt;


&lt;div style="float:left; margin-right:10px"&gt;
&lt;img src="/files/appleremote/AppleRemoteTest.png"&gt;
&lt;/div&gt;

	&lt;p&gt;Pressing buttons on your remote will cause red circles to appear on the corresponding parts of the image.  In the window shown, I&amp;#8217;m holding the right &amp;#8220;forward&amp;#8221; button down.&lt;/p&gt;


	&lt;p&gt;There are three significant Objective-C classes in the demo application, each with its own pair of header and source files.  &lt;strong&gt;RemoteFeedbackView&lt;/strong&gt; provides the contents of the application window, &lt;strong&gt;AppleRemote&lt;/strong&gt; handles communication with the remote control, and &lt;strong&gt;MainController&lt;/strong&gt; brings the two together.  If you look at its source in &lt;strong&gt;MainController.m&lt;/strong&gt;, you&amp;#8217;ll see that Martin has designed a very easy to use interface that uses a common Objective-C pattern: delegation.  In its &lt;strong&gt;awakeFromNib&lt;/strong&gt; method, the &lt;strong&gt;MainController&lt;/strong&gt; gets a singleton object representing the Apple Remote (using another common Objective-C pattern, the shared object).  Then the controller sets itself as the delegate of the &lt;strong&gt;&amp;#91;AppleRemote sharedRemote&amp;#93;&lt;/strong&gt;. It then waits for button presses, which cause the Apple Remote handler to send an &lt;strong&gt;appleRemoteButton:pressedDown:&lt;/strong&gt; message to the delegate, which displays a status message and forwards the button press information to the view.&lt;/p&gt;


	&lt;p&gt;Feel free to read through the code in &lt;strong&gt;AppleRemote.m&lt;/strong&gt;; it contains some mysterious calls to Apple&amp;#8217;s &lt;span class="caps"&gt;HID&lt;/span&gt; (human interface device) manager that could easily take hours to fully understand.  But by now we already know enough to use Martin&amp;#8217;s Apple Remote interface from Ruby.&lt;br clear="all"/&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 25 Feb 2008 10:32:50 GMT</pubDate>
      <guid>http://www.rubycocoa.com/appleremote/1#page1</guid>
      <link>http://www.rubycocoa.com/appleremote/1#page1</link>
    </item>
    <item>
      <title>Michael Black: A RubyCocoa console</title>
      <description>&lt;p&gt;The code for our console is below.  To use it, download it from &lt;a href="/files/mastering-cocoa/console.rb"&gt;this link&lt;/a&gt;, put it in your project directory and restart your application (be sure to also remove the code for the dummy console from the previous chapter). I&amp;#8217;ll discuss the console&amp;#8217;s implementation in the following section, but if you want to play with it first, just go on to the &lt;a href="/mastering-cocoa-with-ruby/4"&gt;next chapter&lt;/a&gt;.&lt;/p&gt;


	&lt;div class='figure'&gt;
&lt;span class='caption'&gt;console.rb (final version) [ruby]&lt;/span&gt;
&lt;div class='body'&gt;&lt;link rel='stylesheet' type='text/css' href='/stylesheets/ruby.css' /&gt;&lt;div class='ruby'&gt;&lt;pre&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;irb&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;ConsoleWindowController&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSObject&lt;/span&gt;
  &lt;span class="ident"&gt;attr_accessor&lt;/span&gt; &lt;span class="symbol"&gt;:window&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:textview&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:console&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initWithFrame&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;init&lt;/span&gt;
    &lt;span class="ident"&gt;styleMask&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSTitledWindowMask&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSClosableWindowMask&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt;
    &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSMiniaturizableWindowMask&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSResizableWindowMask&lt;/span&gt;
    &lt;span class="attribute"&gt;@window&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSWindow&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;alloc&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;initWithContentRect_styleMask_backing_defer&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
    &lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;styleMask&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSBackingStoreBuffered&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@textview&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSTextView&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;alloc&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;initWithFrame&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@console&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;RubyConsole&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;alloc&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;initWithTextView&lt;/span&gt; &lt;span class="attribute"&gt;@textview&lt;/span&gt;
    &lt;span class="ident"&gt;with&lt;/span&gt; &lt;span class="attribute"&gt;@window&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;w&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;w&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setContentView&lt;/span&gt; &lt;span class="ident"&gt;scrollableView&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;w&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setTitle&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;RubyCocoa Console&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="ident"&gt;w&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setDelegate&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;
      &lt;span class="ident"&gt;w&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;center&lt;/span&gt;
      &lt;span class="ident"&gt;w&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;makeKeyAndOrderFront&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="constant"&gt;self&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;run&lt;/span&gt;
    &lt;span class="attribute"&gt;@console&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;performSelector_withObject_afterDelay&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;run:&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;windowWillClose&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;notification&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSApplication&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;sharedApplication&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;terminate&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;windowShouldClose&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;notification&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@alert&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSAlert&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;alloc&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;init&lt;/span&gt;
    &lt;span class="ident"&gt;with&lt;/span&gt; &lt;span class="attribute"&gt;@alert&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setMessageText&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Do you really want to close this console?&lt;span class="escape"&gt;\n&lt;/span&gt;Your application will exit.&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
      &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setAlertStyle&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSCriticalAlertStyle&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;addButtonWithTitle&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;OK&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
      &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;addButtonWithTitle&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Cancel&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
      &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;beginSheetModalForWindow_modalDelegate_didEndSelector_contextInfo&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
      &lt;span class="ident"&gt;window&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;alertDidEnd:returnCode:contextInfo:&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="constant"&gt;false&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;alertDidEnd_returnCode_contextInfo&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;alert&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;code&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;contextInfo&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;window&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;close&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;code&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="number"&gt;1000&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;x&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;yield&lt;/span&gt; &lt;span class="ident"&gt;x&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;block_given?&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="ident"&gt;x&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="keyword"&gt;not&lt;/span&gt; &lt;span class="keyword"&gt;defined?&lt;/span&gt; &lt;span class="ident"&gt;with&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;scrollableView&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;content&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;scrollview&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSScrollView&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;alloc&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;initWithFrame&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;content&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;clipview&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSClipView&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;alloc&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;initWithFrame&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;scrollview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;scrollview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setContentView&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;clipview&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;scrollview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setDocumentView&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;content&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;clipview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setDocumentView&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;content&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;content&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setFrame&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;clipview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;frame&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;scrollview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setHasVerticalScroller&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;scrollview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setHasHorizontalScroller&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;scrollview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setAutohidesScrollers&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;resizingMask&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSViewWidthSizable&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSViewHeightSizable&lt;/span&gt;
  &lt;span class="ident"&gt;content&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setAutoresizingMask&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;resizingMask&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;clipview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setAutoresizingMask&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;resizingMask&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;scrollview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setAutoresizingMask&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;resizingMask&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;scrollview&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;RubyCocoaInputMethod&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;IRB&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;StdioInputMethod&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initialize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;console&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;super&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt; &lt;span class="comment"&gt;# superclass method has no arguments&lt;/span&gt;
    &lt;span class="attribute"&gt;@console&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;console&lt;/span&gt;
    &lt;span class="attribute"&gt;@history_index&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="attribute"&gt;@continued_from_line&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;gets&lt;/span&gt;
    &lt;span class="ident"&gt;m&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="attribute"&gt;@prompt&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;(&lt;span class="escape"&gt;\d&lt;/span&gt;+)[&amp;gt;*]&lt;/span&gt;&lt;span class="punct"&gt;/)&lt;/span&gt;
    &lt;span class="ident"&gt;level&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;m&lt;/span&gt; &lt;span class="punct"&gt;?&lt;/span&gt; &lt;span class="ident"&gt;m&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;to_i&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;level&lt;/span&gt; &lt;span class="punct"&gt;&amp;gt;&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
      &lt;span class="attribute"&gt;@continued_from_line&lt;/span&gt; &lt;span class="punct"&gt;||=&lt;/span&gt; &lt;span class="attribute"&gt;@line_no&lt;/span&gt;
    &lt;span class="keyword"&gt;elsif&lt;/span&gt; &lt;span class="attribute"&gt;@continued_from_line&lt;/span&gt;
      &lt;span class="ident"&gt;mergeLastNLines&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@line_no&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="attribute"&gt;@continued_from_line&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="attribute"&gt;@continued_from_line&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="attribute"&gt;@console&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;write&lt;/span&gt; &lt;span class="attribute"&gt;@prompt&lt;/span&gt;&lt;span class="punct"&gt;+&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;  &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;*&lt;/span&gt;&lt;span class="ident"&gt;level&lt;/span&gt;
    &lt;span class="ident"&gt;string&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="attribute"&gt;@console&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;readLine&lt;/span&gt;
    &lt;span class="attribute"&gt;@line_no&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="attribute"&gt;@history_index&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="attribute"&gt;@line_no&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="attribute"&gt;@line&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="attribute"&gt;@line_no&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;string&lt;/span&gt;
    &lt;span class="ident"&gt;string&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;mergeLastNLines&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt; &lt;span class="punct"&gt;&amp;gt;&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="ident"&gt;range&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;..-&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="attribute"&gt;@line&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;range&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="attribute"&gt;@line&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;range&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;map&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;l&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;l&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;chomp&lt;/span&gt;&lt;span class="punct"&gt;}.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="escape"&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@line_no&lt;/span&gt; &lt;span class="punct"&gt;-=&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;-&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@history_index&lt;/span&gt; &lt;span class="punct"&gt;-=&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;-&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;prevCmd&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="attribute"&gt;@line_no&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
    &lt;span class="attribute"&gt;@history_index&lt;/span&gt; &lt;span class="punct"&gt;-=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt; &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="attribute"&gt;@history_index&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="attribute"&gt;@line&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="attribute"&gt;@history_index&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;nextCmd&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@line_no&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;or&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@history_index&lt;/span&gt; &lt;span class="punct"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="attribute"&gt;@line_no&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@history_index&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="attribute"&gt;@line&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="attribute"&gt;@history_index&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="comment"&gt;# this is an output handler for IRB &lt;/span&gt;
&lt;span class="comment"&gt;# and a delegate and controller for an NSTextView&lt;/span&gt;
&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;RubyConsole&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSObject&lt;/span&gt;
  &lt;span class="ident"&gt;attr_accessor&lt;/span&gt; &lt;span class="symbol"&gt;:textview&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:inputMethod&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initWithTextView&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;textview&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;init&lt;/span&gt;
    &lt;span class="attribute"&gt;@textview&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;textview&lt;/span&gt;
    &lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setDelegate&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;
    &lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setRichText&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;false&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setContinuousSpellCheckingEnabled&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;false&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@inputMethod&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;RubyCocoaInputMethod&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@context&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Kernel&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="ident"&gt;binding&lt;/span&gt;
    &lt;span class="attribute"&gt;@startOfInput&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
    &lt;span class="constant"&gt;self&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;run&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;sender&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;window&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;makeKeyAndOrderFront&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="constant"&gt;IRB&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;startInConsole&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSApplication&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;sharedApplication&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;terminate&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;write&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;object&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;string&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;object&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;
    &lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;textStorage&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;insertAttributedString_atIndex&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
      &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSAttributedString&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;alloc&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;initWithString&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;string&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt; &lt;span class="attribute"&gt;@startOfInput&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@startOfInput&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="ident"&gt;string&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;
    &lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;scrollRangeToVisible&lt;/span&gt;&lt;span class="punct"&gt;([&lt;/span&gt;&lt;span class="ident"&gt;lengthOfTextView&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;
    &lt;span class="ident"&gt;handleEvents&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSApplication&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;sharedApplication&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;isRunning&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;moveAndScrollToIndex&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;range&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSRange&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;scrollRangeToVisible&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;range&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setSelectedRange&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;range&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;lengthOfTextView&lt;/span&gt;
    &lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;textStorage&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;mutableString&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;currentLine&lt;/span&gt;
    &lt;span class="ident"&gt;text&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;textStorage&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;mutableString&lt;/span&gt;
    &lt;span class="ident"&gt;text&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;substringWithRange&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
      &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSRange&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@startOfInput&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;text&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="attribute"&gt;@startOfInput&lt;/span&gt;&lt;span class="punct"&gt;)).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;readLine&lt;/span&gt;
    &lt;span class="ident"&gt;app&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSApplication&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;sharedApplication&lt;/span&gt;
    &lt;span class="attribute"&gt;@startOfInput&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lengthOfTextView&lt;/span&gt;
    &lt;span class="ident"&gt;loop&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="ident"&gt;event&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;app&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;nextEventMatchingMask_untilDate_inMode_dequeue&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
        &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSAnyEventMask&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; 
        &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSDate&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;distantFuture&lt;/span&gt;&lt;span class="punct"&gt;(),&lt;/span&gt; 
        &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSDefaultRunLoopMode&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; 
        &lt;span class="constant"&gt;true&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;event&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;oc_type&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSKeyDown&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt; 
         &lt;span class="ident"&gt;event&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;window&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt; 
         &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;event&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;window&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;isEqual?&lt;/span&gt; &lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;window&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="keyword"&gt;break&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;event&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;characters&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="escape"&gt;\r&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
        &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;event&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;modifierFlags&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSControlKeyMask&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;!=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
          &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="ident"&gt;event&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;keyCode&lt;/span&gt;
          &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;  &lt;span class="ident"&gt;moveAndScrollToIndex&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@startOfInput&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;     &lt;span class="comment"&gt;# control-a&lt;/span&gt;
          &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="number"&gt;14&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="ident"&gt;moveAndScrollToIndex&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;lengthOfTextView&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;  &lt;span class="comment"&gt;# control-e&lt;/span&gt;
          &lt;span class="keyword"&gt;end&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="ident"&gt;app&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;sendEvent&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;event&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;lineToReturn&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;currentLine&lt;/span&gt;
    &lt;span class="attribute"&gt;@startOfInput&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lengthOfTextView&lt;/span&gt;
    &lt;span class="ident"&gt;write&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="escape"&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;lineToReturn&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="escape"&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;handleEvents&lt;/span&gt;
    &lt;span class="ident"&gt;app&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSApplication&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;sharedApplication&lt;/span&gt;
    &lt;span class="ident"&gt;event&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;app&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;nextEventMatchingMask_untilDate_inMode_dequeue&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
      &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSAnyEventMask&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
      &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSDate&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;dateWithTimeIntervalSinceNow&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;0.01&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt;
      &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSDefaultRunLoopMode&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
      &lt;span class="constant"&gt;true&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;event&lt;/span&gt;
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;event&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;oc_type&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSKeyDown&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt;
        &lt;span class="ident"&gt;event&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;window&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt;
        &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;event&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;window&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;isEqualTo&lt;/span&gt; &lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;window&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt;
        &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;event&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;charactersIgnoringModifiers&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;c&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt;
        &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;event&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;modifierFlags&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSControlKeyMask&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="keyword"&gt;raise&lt;/span&gt; &lt;span class="constant"&gt;IRB&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Abort&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;abort, then interrupt!!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="comment"&gt;# that's what IRB says...&lt;/span&gt;
      &lt;span class="keyword"&gt;else&lt;/span&gt;
        &lt;span class="ident"&gt;app&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;sendEvent&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;event&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;replaceLineWithHistory&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;s&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;range&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSRange&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@startOfInput&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;lengthOfTextView&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="attribute"&gt;@startOfInput&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;textStorage&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;replaceCharactersInRange_withAttributedString&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
    &lt;span class="ident"&gt;range&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSAttributedString&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;alloc&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;initWithString&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;s&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;chomp&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
    &lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;scrollRangeToVisible&lt;/span&gt;&lt;span class="punct"&gt;([&lt;/span&gt;&lt;span class="ident"&gt;lengthOfTextView&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;
    &lt;span class="constant"&gt;true&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="comment"&gt;# delegate methods&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;textView_shouldChangeTextInRange_replacementString&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
        &lt;span class="ident"&gt;textview&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;range&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;replacement&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;range&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;location&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="attribute"&gt;@startOfInput&lt;/span&gt;
    &lt;span class="ident"&gt;replacement&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;replacement&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;gsub&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="escape"&gt;\r&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="escape"&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;replacement&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt; &lt;span class="punct"&gt;&amp;gt;&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt; &lt;span class="ident"&gt;replacement&lt;/span&gt;&lt;span class="punct"&gt;[-&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;chr&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="escape"&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="attribute"&gt;@textview&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;textStorage&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;appendAttributedString&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
        &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSAttributedString&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;alloc&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;initWithString&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;replacement&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;currentLine&lt;/span&gt; &lt;span class="punct"&gt;!=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="attribute"&gt;@startOfInput&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lengthOfTextView&lt;/span&gt;
      &lt;span class="constant"&gt;false&lt;/span&gt; &lt;span class="comment"&gt;# don't insert replacement text because we've already inserted it&lt;/span&gt;
    &lt;span class="keyword"&gt;else&lt;/span&gt;
      &lt;span class="constant"&gt;true&lt;/span&gt;  &lt;span class="comment"&gt;# caller should insert replacement text&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;textView_willChangeSelectionFromCharacterRange_toCharacterRange&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
       &lt;span class="ident"&gt;textview&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;oldRange&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;newRange&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;oldRange&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;newRange&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt;
                       &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;newRange&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;location&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="attribute"&gt;@startOfInput&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;newRange&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;textView_doCommandBySelector&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;textview&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;selector&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="ident"&gt;selector&lt;/span&gt;
    &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;moveUp:&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="ident"&gt;replaceLineWithHistory&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@inputMethod&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;prevCmd&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;moveDown:&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="ident"&gt;replaceLineWithHistory&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@inputMethod&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;nextCmd&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;else&lt;/span&gt;
      &lt;span class="constant"&gt;false&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;IRB&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;IRB.startInConsole&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;console&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="constant"&gt;IRB&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setup&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;nil&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@CONF&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:PROMPT_MODE&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="symbol"&gt;:DEFAULT&lt;/span&gt;
    &lt;span class="attribute"&gt;@CONF&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:VERBOSE&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt;
    &lt;span class="attribute"&gt;@CONF&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:ECHO&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;
    &lt;span class="ident"&gt;irb&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Irb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;nil&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;console&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;inputMethod&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@CONF&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:IRB_RC&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;irb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;context&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="attribute"&gt;@CONF&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:IRB_RC&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
    &lt;span class="attribute"&gt;@CONF&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:MAIN_CONTEXT&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;irb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;context&lt;/span&gt;
    &lt;span class="ident"&gt;trap&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;SIGINT&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="ident"&gt;irb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;signal_handle&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;old_stdout&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;old_stderr&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="global"&gt;$stdout&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="global"&gt;$stderr&lt;/span&gt;
    &lt;span class="global"&gt;$stdout&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="global"&gt;$stderr&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;console&lt;/span&gt;
    &lt;span class="ident"&gt;catch&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:IRB_EXIT&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="ident"&gt;loop&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
        &lt;span class="keyword"&gt;begin&lt;/span&gt;
          &lt;span class="ident"&gt;irb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;eval_input&lt;/span&gt;
        &lt;span class="keyword"&gt;rescue&lt;/span&gt; &lt;span class="constant"&gt;Exception&lt;/span&gt;
          &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Error: &lt;span class="expr"&gt;#{$!}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="global"&gt;$stdout&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="global"&gt;$stderr&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;old_stdout&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;old_stderr&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Context&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;prompting?&lt;/span&gt;
      &lt;span class="constant"&gt;true&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;ApplicationDelegate&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSObject&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;applicationDidFinishLaunching&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;sender&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="global"&gt;$consoleWindowController&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;ConsoleWindowController&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;alloc&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;
       &lt;span class="ident"&gt;initWithFrame&lt;/span&gt;&lt;span class="punct"&gt;([&lt;/span&gt;&lt;span class="number"&gt;50&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;50&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;600&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;300&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;
    &lt;span class="global"&gt;$consoleWindowController&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;run&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="comment"&gt;# set up the application delegate&lt;/span&gt;
&lt;span class="global"&gt;$delegate&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;ApplicationDelegate&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;alloc&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;init&lt;/span&gt;
&lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSApplication&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;sharedApplication&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setDelegate&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="global"&gt;$delegate&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;</description>
      <pubDate>Mon, 25 Feb 2008 10:04:32 GMT</pubDate>
      <guid>http://www.rubycocoa.com/mastering-cocoa-with-ruby/3#page2</guid>
      <link>http://www.rubycocoa.com/mastering-cocoa-with-ruby/3#page2</link>
    </item>
    <item>
      <title>Michael Black: Do this and your software will thank you</title>
      <description>&lt;p&gt;The first step is to convert our Objective-C Cocoa application into a RubyCocoa application.  Our application will need to have a Ruby interpreter and the RubyCocoa bridge code built into it.  To get them, make the following changes:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Add the RubyCocoa framework to your project.
	&lt;ul&gt;
	&lt;li&gt;In the &amp;#8216;Groups &amp;#38; Files&amp;#8217; section on the left side of the Project window, expand the &amp;#8216;Frameworks&amp;#8217; group,&lt;/li&gt;
		&lt;li&gt;Right-click (or Ctrl-click) on the &amp;#8216;Linked Frameworks&amp;#8217; group, and choose &amp;#8216;Add -&amp;gt; Existing Frameworks&amp;#8230;&amp;#8217;&lt;/li&gt;
		&lt;li&gt;Find and add &amp;#8217;/System/Frameworks/RubyCocoa.framework&amp;#8217;&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Replace &lt;strong&gt;main.m&lt;/strong&gt; with the following code:&lt;/li&gt;
	&lt;/ul&gt;


	&lt;div class='figure'&gt;
&lt;span class='caption'&gt;main.m [Objective-C]&lt;/span&gt;
&lt;div class='body'&gt;&lt;link rel='stylesheet' type='text/css' href='/stylesheets/Objective-C.css' /&gt;&lt;div class='Objective-C'&gt;&lt;pre&gt;#import &amp;lt;RubyCocoa/RBRuntime.h&amp;gt;

int main(int argc, const char *argv[])
{
    return RBApplicationMain(&amp;quot;rb_main.rb&amp;quot;, argc, argv);
}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;ul&gt;
	&lt;li&gt;Add a new file to your project named &lt;strong&gt;rb_main.rb&lt;/strong&gt;.  Give it the following contents:&lt;/li&gt;
	&lt;/ul&gt;


	&lt;div class='figure'&gt;
&lt;span class='caption'&gt;rb_main.rb [ruby]&lt;/span&gt;
&lt;div class='body'&gt;&lt;link rel='stylesheet' type='text/css' href='/stylesheets/ruby.css' /&gt;&lt;div class='ruby'&gt;&lt;pre&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;osx/cocoa&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;rb_main_init&lt;/span&gt;
  &lt;span class="ident"&gt;path&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;NSBundle&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;mainBundle&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;resourcePath&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;fileSystemRepresentation&lt;/span&gt;
  &lt;span class="ident"&gt;rbfiles&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Dir&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;entries&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;path&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;select&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;x&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;&lt;span class="escape"&gt;\.&lt;/span&gt;rb&lt;span class="escape"&gt;\z&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="punct"&gt;=~&lt;/span&gt; &lt;span class="ident"&gt;x&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="ident"&gt;rbfiles&lt;/span&gt; &lt;span class="punct"&gt;-=&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;basename&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;__FILE__&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;]&lt;/span&gt;
  &lt;span class="ident"&gt;rbfiles&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;path&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;require&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;basename&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;path&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="global"&gt;$0&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="constant"&gt;__FILE__&lt;/span&gt; &lt;span class="keyword"&gt;then&lt;/span&gt;
  &lt;span class="ident"&gt;rb_main_init&lt;/span&gt;
  &lt;span class="constant"&gt;OSX&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;NSApplicationMain&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;nil&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;Now build and test your application.  Everything should work just as before, but your application now has a hidden and very special power&amp;#8212;it can run Ruby code.  We&amp;#8217;ll use this in the next three chapters to convert the three classes &lt;strong&gt;Controller&lt;/strong&gt;, &lt;strong&gt;CustomWindow&lt;/strong&gt;, and &lt;strong&gt;CustomView&lt;/strong&gt; one-by-one into Ruby, and then in the next chapter to make some fun and easy enhancements.  We&amp;#8217;ll convert the classes one at a time so that we can catch any problems that appear along the way.&lt;/p&gt;</description>
      <pubDate>Mon, 25 Feb 2008 09:43:01 GMT</pubDate>
      <guid>http://www.rubycocoa.com/the-rubification-of-rtw/2#page1</guid>
      <link>http://www.rubycocoa.com/the-rubification-of-rtw/2#page1</link>
    </item>
    <item>
      <title>Michael Black: Set up the document nib file</title>
      <description>&lt;p&gt;Open &lt;strong&gt;Game.nib&lt;/strong&gt; from within Xcode.  Interface Builder will open the file. In the document window, delete the &amp;#8220;Your document contents here&amp;#8221; message and replace it with a &lt;strong&gt;CustomView&lt;/strong&gt; object from the palette.&lt;/p&gt;


&lt;div style="float:right; width:300px; margin-left:20px; padding: 10px"&gt;&lt;img src="/files/ruby-rocks/nswindow_inspector.jpg"&gt;&lt;/div&gt;

	&lt;p&gt;Select the &lt;strong&gt;Window&lt;/strong&gt; object in the &lt;strong&gt;Game.nib&lt;/strong&gt; main view and then use Command-3 to inspect its size properties.  Set its width and height to 800&amp;#215;600 and click the &amp;#8220;lock&amp;#8221; checkbox.  Then go to the window inspector with Command-1 and uncheck the &amp;#8220;Zoom (and resize)&amp;#8221; box (see the image at right).  This will give the game world a fixed size.  Now size the &lt;strong&gt;CustomView&lt;/strong&gt; object so that it fills the window.&lt;/p&gt;


&lt;div style="float: right; width: 290px; margin-left:20px; padding: 10px; background:#ddd"&gt;
&lt;strong&gt;Hang in there!&lt;/strong&gt; In my opinion, this is the most tedious part of the whole tutorial, so don&amp;#8217;t get discouraged.  Cocoa and NeXTSTEP mavens like to talk about how great it is to use Interface Builder (and compared with their previous alternatives, they&amp;#8217;re probably right).  But like Carl Jung, most of them have never used Ruby.
&lt;/div&gt; 

	&lt;p&gt;With the &lt;strong&gt;CustomView&lt;/strong&gt; still selected, use Command-6 to bring up its Identity inspector.  Change the class to &lt;strong&gt;GameView&lt;/strong&gt; and add an outlet to your &lt;strong&gt;GameView&lt;/strong&gt; class named &lt;strong&gt;game&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;In the main Interface Builder window, select the &lt;strong&gt;File&amp;#8217;s Owner&lt;/strong&gt; object and use Command-6 to verify that its class is &lt;strong&gt;Game&lt;/strong&gt;.  Connect the &lt;strong&gt;GameView&lt;/strong&gt;&amp;#8217;s &lt;strong&gt;game&lt;/strong&gt; outlet to the &lt;strong&gt;File&amp;#8217;s Owner&lt;/strong&gt; object.&lt;/p&gt;


	&lt;p&gt;Save the nib and exit Interface Builder.  Run the application.  You should now get an empty window and a warning message in the run log:&lt;/p&gt;


	&lt;p&gt;&lt;tt&gt;Unknown class &amp;#8216;GameView&amp;#8217; in nib file, using `NSView&amp;#8217; instead.&lt;/tt&gt;&lt;/p&gt;


	&lt;p&gt;It&amp;#8217;s time to create the &lt;strong&gt;GameView&lt;/strong&gt;.  And from here on, it&amp;#8217;s all Ruby.&lt;/p&gt;</description>
      <pubDate>Mon, 25 Feb 2008 08:59:58 GMT</pubDate>
      <guid>http://www.rubycocoa.com/ruby-rocks/2#page3</guid>
      <link>http://www.rubycocoa.com/ruby-rocks/2#page3</link>
    </item>
    <item>
      <title>Michael Black: Set up the document nib file</title>
      <description>&lt;p&gt;Open &lt;strong&gt;Game.nib&lt;/strong&gt; from within Xcode.  Interface Builder will open the file. In the document window, delete the &amp;#8220;Your document contents here&amp;#8221; message and replace it with a &lt;strong&gt;CustomView&lt;/strong&gt; object from the palette.&lt;/p&gt;


&lt;div style="float:right; width:300px; margin-left:20px; padding: 10px"&gt;&lt;img src="/files/ruby-rocks/nswindow_inspector.jpg"&gt;&lt;/div&gt;

	&lt;p&gt;Select the &lt;strong&gt;Window&lt;/strong&gt; object in the &lt;strong&gt;Game.nib&lt;/strong&gt; main view and then use Command-3 to inspect its size properties.  Set its width and height to 800&amp;#215;600 and click the &amp;#8220;lock&amp;#8221; checkbox.  Then go to the window inspector with Command-1 and uncheck the &amp;#8220;Zoom (and resize)&amp;#8221; box (see the image at right).  This will give the game world a fixed size.  Now size the &lt;strong&gt;CustomView&lt;/strong&gt; object so that it fills the window.&lt;/p&gt;


&lt;div style="float: right; width: 290px; margin-left:20px; padding: 10px; background:#ddd"&gt;
&lt;strong&gt;Hang in there!&lt;/strong&gt; In my opinion, this is the most tedious part of the whole tutorial, so don&amp;#8217;t get discouraged.  Cocoa and NeXTSTEP mavens like to talk about how great it is to use Interface Builder (and compared with their previous alternatives, they&amp;#8217;re probably right).  But like Carl Jung, most of them have never used Ruby.
&lt;/div&gt; 

	&lt;p&gt;With the &lt;strong&gt;CustomView&lt;/strong&gt; still selected, use Command-6 to bring up its class inspector.  Change the class to &lt;strong&gt;GameView&lt;/strong&gt; and add an outlet to your &lt;strong&gt;GameView&lt;/strong&gt; class named &lt;strong&gt;game&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;In the main Interface Builder window, select the &lt;strong&gt;File&amp;#8217;s Owner&lt;/strong&gt; object and use Command-6 to verify that its class is &lt;strong&gt;Game&lt;/strong&gt;.  Connect the &lt;strong&gt;GameView&lt;/strong&gt;&amp;#8217;s &lt;strong&gt;game&lt;/strong&gt; outlet to the &lt;strong&gt;File&amp;#8217;s Owner&lt;/strong&gt; object.&lt;/p&gt;


	&lt;p&gt;Save the nib and exit Interface Builder.  Run the application.  You should now get an empty window and a warning message in the run log:&lt;/p&gt;


	&lt;p&gt;&lt;tt&gt;Unknown class &amp;#8216;GameView&amp;#8217; in nib file, using `NSView&amp;#8217; instead.&lt;/tt&gt;&lt;/p&gt;


	&lt;p&gt;It&amp;#8217;s time to create the &lt;strong&gt;GameView&lt;/strong&gt;.  And from here on, it&amp;#8217;s all Ruby.&lt;/p&gt;</description>
      <pubDate>Mon, 25 Feb 2008 08:58:06 GMT</pubDate>
      <guid>http://www.rubycocoa.com/ruby-rocks/2#page3</guid>
      <link>http://www.rubycocoa.com/ruby-rocks/2#page3</link>
    </item>
    <item>
      <title>Michael Black: Set up the document nib file</title>
      <description>&lt;p&gt;Open &lt;strong&gt;Game.nib&lt;/strong&gt; from within Xcode.  Interface Builder will open the file. In the document window, delete the &amp;#8220;Your document contents here&amp;#8221; message and replace it with a &lt;strong&gt;CustomView&lt;/strong&gt; object from the palette.&lt;/p&gt;


&lt;div style="float:right; width:300px; margin-left:20px; padding: 10px"&gt;&lt;img src="/files/ruby-rocks/nswindow_inspector.jpg"&gt;&lt;/div&gt;

	&lt;p&gt;Select the &lt;strong&gt;Window&lt;/strong&gt; object in the &lt;strong&gt;Game.nib&lt;/strong&gt; main view and then use Command-3 to inspect its size properties.  Set its width and height to 800&amp;#215;600 and click the &amp;#8220;lock&amp;#8221; checkbox.  Then go to the window inspector with Command-1 and uncheck the &amp;#8220;Zoom (and resize)&amp;#8221; box (see the image at right).  This will give the game world a fixed size.  Now size the &lt;strong&gt;CustomView&lt;/strong&gt; object so that it fills the window.&lt;/p&gt;


&lt;div style="float: right; width: 290px; margin-left:20px; padding: 10px; background:#ddd"&gt;
&lt;strong&gt;Hang in there!&lt;/strong&gt; In my opinion, this is the most tedious part of the whole tutorial, so don&amp;#8217;t get discouraged.  Cocoa and NeXTSTEP mavens like to talk about how great it is to use Interface Builder (and compared with their previous alternatives, they&amp;#8217;re probably right).  But like Carl Jung, most of them have never used Ruby.
&lt;/div&gt;
We need to tell Interface Builder about two classes.  We&amp;#8217;ll call them &lt;strong&gt;Game&lt;/strong&gt; and &lt;strong&gt;GameView&lt;/strong&gt;.  &lt;strong&gt;Game&lt;/strong&gt; represents our document and &lt;strong&gt;GameView&lt;/strong&gt; is the view. In the Classes view, find &lt;strong&gt;MyDocument&lt;/strong&gt; (it&amp;#8217;s a subclass of &lt;strong&gt;NSDocument&lt;/strong&gt;) and rename it to &lt;strong&gt;Game&lt;/strong&gt;.  Then find &lt;strong&gt;NSView&lt;/strong&gt; (it&amp;#8217;s a subclass of &lt;strong&gt;NSResponder&lt;/strong&gt;) and create a subclass called &lt;strong&gt;GameView&lt;/strong&gt; (right- or control-click on &lt;strong&gt;NSView&lt;/strong&gt; for a pop-up menu).  Add an outlet to your &lt;strong&gt;GameView&lt;/strong&gt; class named &lt;strong&gt;game&lt;/strong&gt;.

	&lt;p&gt;Go back to the window object and select the &lt;strong&gt;CustomView&lt;/strong&gt;. Use Command-6 to bring up its class inspector.  Change the class to &lt;strong&gt;GameView&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;In the main Interface Builder window, select the &lt;strong&gt;File&amp;#8217;s Owner&lt;/strong&gt; object and use Command-6 to verify that its class is &lt;strong&gt;Game&lt;/strong&gt;.  Connect the &lt;strong&gt;GameView&lt;/strong&gt;&amp;#8217;s &lt;strong&gt;game&lt;/strong&gt; outlet to the &lt;strong&gt;File&amp;#8217;s Owner&lt;/strong&gt; object.&lt;/p&gt;


	&lt;p&gt;Save the nib and exit Interface Builder.  Run the application.  You should now get an empty window and a warning message in the run log:&lt;/p&gt;


	&lt;p&gt;&lt;tt&gt;Unknown class &amp;#8216;GameView&amp;#8217; in nib file, using `NSView&amp;#8217; instead.&lt;/tt&gt;&lt;/p&gt;


	&lt;p&gt;It&amp;#8217;s time to create the &lt;strong&gt;GameView&lt;/strong&gt;.  And from here on, it&amp;#8217;s all Ruby.&lt;/p&gt;</description>
      <pubDate>Mon, 25 Feb 2008 08:47:29 GMT</pubDate>
      <guid>http://www.rubycocoa.com/ruby-rocks/2#page3</guid>
      <link>http://www.rubycocoa.com/ruby-rocks/2#page3</link>
    </item>
    <item>
      <title>Michael Black: Create the Xcode project</title>
      <description>&lt;p&gt;In Xcode, use &lt;strong&gt;File-&amp;gt;New Project&amp;#8230;&lt;/strong&gt; to create a new project.
In the dialog that appears, select &amp;#8220;Cocoa-Ruby Document-based Application&amp;#8221; as the project type.  Name the project &amp;#8220;rubyrocks&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;The project tempate specifies that the application&amp;#8217;s document class is &lt;strong&gt;MyDocument&lt;/strong&gt;.  Let&amp;#8217;s change that to &lt;strong&gt;Game&lt;/strong&gt;.  In the Groups &amp;#38; Files pane on the left side of the project window, open the Classes and Resources groups.   Make these changes:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Rename &lt;strong&gt;MyDocument.nib&lt;/strong&gt; to &lt;strong&gt;Game.nib&lt;/strong&gt;.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Rename &lt;strong&gt;MyDocument.rb&lt;/strong&gt; to &lt;strong&gt;RubyRocks.rb&lt;/strong&gt; (we&amp;#8217;ll put all of our Ruby code in this file).  In &lt;strong&gt;RubyRocks.rb&lt;/strong&gt;, change the name of the &lt;strong&gt;MyDocument&lt;/strong&gt; class to &lt;strong&gt;Game&lt;/strong&gt;.  Find the &lt;strong&gt;windowNibName&lt;/strong&gt; function; change it to return &lt;strong&gt;Game&lt;/strong&gt;.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Now build and run your project.  You should get an error: an alert box should appear with the message &amp;#8220;No document could be created.&amp;#8221;  This is because the application is still looking for a class named &lt;strong&gt;MyDocument&lt;/strong&gt;.   To change this, find the &lt;strong&gt;Targets&lt;/strong&gt; group in your Xcode main project window.  Click on the triangle to its left to expose the &lt;strong&gt;rubyrocks&lt;/strong&gt; target.  Double-click on the target icon to edit the target&amp;#8217;s build properties.  In the &lt;strong&gt;Document Types&lt;/strong&gt; table, double-click the value in the &lt;strong&gt;Class&lt;/strong&gt; column and change it from &lt;strong&gt;MyDocument&lt;/strong&gt; to &lt;strong&gt;Game&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;Now when you run your project, you should see a new window appear with the words &amp;#8220;Your document contents here.&amp;#8221; That&amp;#8217;s your document view.  To get it ready, we need to make some changes to &lt;strong&gt;Game.nib&lt;/strong&gt;.&lt;/p&gt;</description>
      <pubDate>Mon, 25 Feb 2008 08:35:44 GMT</pubDate>
      <guid>http://www.rubycocoa.com/ruby-rocks/2#page2</guid>
      <link>http://www.rubycocoa.com/ruby-rocks/2#page2</link>
    </item>
    <item>
      <title>Administrator: Background</title>
      <description>&lt;p&gt;Ruby is a powerful language and is loaded with features, but for some applications, Ruby programmers face a limitation.  It might be a performance problem caused by the slowness of interpreted languages. Or it might be that a critical function or &lt;span class="caps"&gt;API&lt;/span&gt; is only available in a lower-level language like C or C+&amp;#43;.  To address this, Ruby provides a way for developers to write extensions of Ruby in C.&lt;/p&gt;


	&lt;p&gt;The extension process is described in the &lt;a href="http://www.rubycentral.com/pickaxe/ext_ruby.html"&gt;pickaxe book&lt;/a&gt;.  It is simpler than the processes required by some other scripting languages, but it still requires programmers to write custom &amp;#8220;glue code&amp;#8221; for every C function or C+&amp;#43; object that we need to make available to Ruby.&lt;/p&gt;


	&lt;p&gt;There is a popular tool called &lt;a href="http://www.swig.org"&gt;&lt;span class="caps"&gt;SWIG&lt;/span&gt;&lt;/a&gt; that can help generate this code.  &lt;span class="caps"&gt;SWIG&lt;/span&gt; reads C and C+&amp;#43; source files and automatically writes the glue code that wraps C functions for Ruby (and lots of other languages).  Wrapping C+&amp;#43; objects is  also possible, but is more tricky due to the complexity of C+&amp;#43;.&lt;/p&gt;


	&lt;p&gt;At some point, one eventually wonders &amp;#8220;why is all this glue code necessary?&amp;#8221;  The answer to that lies in the C and C+&amp;#43; compilation process, which converts a lot of very high level information about objects and functions into lots more very low level information, mainly the machine instructions that directly implement each function.  But all the high level information that Ruby needs about objects, types, methods, and interfaces is discarded in the compilation of C and C+&amp;#43; programs (and sometimes recovered by &lt;span class="caps"&gt;SWIG&lt;/span&gt;).&lt;/p&gt;


	&lt;p&gt;This is where Ruby programmers begin to love Objective-C.  The tables that Objective-C uses for dynamic message handling contain exactly the information that is needed to interface with Ruby.  Because they are kept in the compiled object files, they are available at runtime.  As a result, to interface Objective-C objects with Ruby, &lt;em&gt;no custom glue code is needed!&lt;/em&gt; All the translation that we need is in handlers that are built right into the RubyCocoa framework.&lt;/p&gt;


	&lt;p&gt;This gives us direct access to Cocoa and a lot more: any Objective-C classes and objects can be accessed through RubyCocoa.  What&amp;#8217;s more, RubyCocoa also contains a bridge that makes certain kinds of Ruby objects available in Objective-C code.  We&amp;#8217;ll go into detail about all this in the rest of this chapter.&lt;/p&gt;</description>
      <pubDate>Wed, 19 Dec 2007 11:36:47 GMT</pubDate>
      <guid>http://www.rubycocoa.com/an-introduction-to-rubycocoa/4#page1</guid>
      <link>http://www.rubycocoa.com/an-introduction-to-rubycocoa/4#page1</link>
    </item>
    <item>
      <title>Administrator: Downloading and Installing RubyCocoa</title>
      <description>&lt;p&gt;RubyCocoa distributions are downloadable from 
&lt;a href="http://sourceforge.net/project/showfiles.php?group_id=44114"&gt;this page on SourceForge&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;The current version is 0.13 (released November 24, 2007).  It&amp;#8217;s a universal binary that works great on Intel iMacs and Mac Books.  If you&amp;#8217;re using the Apple-installed ruby (the one at /usr/bin/ruby), then you probably want to download and install the disk image&amp;#8212;it&amp;#8217;s the file whose name ends in &amp;#8221;.dmg&amp;#8221;.  After downloading it, double click on it and the installation will begin.&lt;/p&gt;


If you have built a newer version of ruby and installed it somewhere else (probably /usr/local/bin/ruby), then you&amp;#8217;ll need to instead download the source code distribution and build RubyCocoa yourself.  To do so, download the file ending in &amp;#8221;.tgz&amp;#8221;. To build, simply run the following in the unpacked directory:
&lt;pre&gt;
ruby install.rb config
ruby install.rb setup
sudo ruby install.rb install
&lt;/pre&gt;</description>
      <pubDate>Wed, 19 Dec 2007 11:33:27 GMT</pubDate>
      <guid>http://www.rubycocoa.com/an-introduction-to-rubycocoa/3#page2</guid>
      <link>http://www.rubycocoa.com/an-introduction-to-rubycocoa/3#page2</link>
    </item>
    <item>
      <title>Administrator: Building and Installing RubyCocoa from Subversion</title>
      <description>&lt;p&gt;To keep up with the latest developments and bug fixes, you can download and build RubyCocoa directly from the subversion repository.
The latest versions of RubyCocoa can be checked out with the following subversion command:&lt;/p&gt;


&lt;pre&gt;
svn co https://rubycocoa.svn.sourceforge.net/svnroot/rubycocoa/trunk rubycocoa
&lt;/pre&gt;

Recently (Fall 2006), there have been a lot of bleeding-edge changes on a branch that you can check out with this:
&lt;pre&gt;
svn co https://rubycocoa.svn.sourceforge.net/svnroot/rubycocoa/branches/apple-unstable rubycocoa
&lt;/pre&gt;

If you get an error message like the following, you probably are running with an old version of subversion:
&lt;pre&gt;
% svn co https://rubycocoa.svn.sourceforge.net/svnroot/rubycocoa/trunk rubycocoa
svn: SSL is not supported
&lt;/pre&gt;

	&lt;p&gt;Download and install a new subversion client from &lt;a href="http://metissian.com/projects/macosx/subversion"&gt;Matthew Porter&amp;#8217;s archive on metissian.com&lt;/a&gt;.  Be sure to use version 1.3.1 or later to get a universal binary and &lt;span class="caps"&gt;SSL&lt;/span&gt; support.&lt;/p&gt;</description>
      <pubDate>Wed, 19 Dec 2007 11:32:19 GMT</pubDate>
      <guid>http://www.rubycocoa.com/an-introduction-to-rubycocoa/3#page3</guid>
      <link>http://www.rubycocoa.com/an-introduction-to-rubycocoa/3#page3</link>
    </item>
    <item>
      <title>Administrator: rubycocoa-talk</title>
      <description>&lt;p&gt;&lt;strong&gt;rubycocoa-talk&lt;/strong&gt; is an email list for discussion of RubyCocoa.  It currently is also the official channel for discussing bugs and submitting patches.
&lt;strong&gt;rubycocoa-talk&lt;/strong&gt; is archived at &lt;a href="http://sourceforge.net/mailarchive/forum.php?forum_name=rubycocoa-talk"&gt;SourceForge&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Wed, 19 Dec 2007 11:17:00 GMT</pubDate>
      <guid>http://www.rubycocoa.com/an-introduction-to-rubycocoa/7#page1</guid>
      <link>http://www.rubycocoa.com/an-introduction-to-rubycocoa/7#page1</link>
    </item>
  </channel>
</rss>
