Archive for the 'ruby' Category

First review draft of RubyCocoa book

I’m ready for people to review the first draft of my RubyCocoa book. Here’s the goal of the book:

With any complex framework, there’s a moment when you realize you finally have a feel for it—when faced with a new problem, you’re able to guess whether the framework addresses it, roughly how it will address it, and where to look to find the details. The aim of this book is to give you that feel for Cocoa and RubyCocoa. […]

You can fetch the most recent draft from http://www.exampler.com/tmp/drafts/current.dmg. It’s 80-some pages and contains the first six chapters:

  • Introduction

  • How Do We Get This Thing Started?: A fast introduction to RubyCocoa.

  • Part 1: Building a Useful App

    • Working with Interface Builder and XCode: Drawing a user interface, putting code behind it, and debugging that code. Text fields and text views.

    • One Good App Observes Another: Extending the app to use interprocess communication to listen to another app. The Cocoa Notification system. Reopening Objective-C classes.

    • A Better User Interface: Buttons (and the default button), combo boxes (and first responders), and a highly decoupled app architecture.

    • Taking Advantage of Ruby: A DSL to make it easier to define actions, delegates, and methods that post or receive notifications.

Here’s what I’d like to hear about:

  • Any parts you have to struggle to understand.

  • Parts that move too slowly or too quickly.

  • Whether the book is taking the right approach, or started with the right approach and has veered off track.

  • Problems with the code samples. Don’t struggle to fix them—let me know and let me fix them.

  • Whether you’d buy the book if the rest is like what you see.

Don’t bother with typos, grammatical errors, or layout problems (like highlighted words that run together or long identifiers that stick past the margins - those will get fixed in due time).

You can send comments to me directly or via the book’s mailing list.

Thank you.

Draft chapter for RubyCocoa book

I’m ready for people to take a look at a chapter. It’s actually the second chapter of the book. The introduction, covering prerequisites, the general plan of the book, its goals, what “Cocoa” is, etc.—that will probably be written last.

But to orient yourselves:

  • I assume you know Ruby, but nothing about Objective-C, Cocoa, or building apps on the Mac.

  • Rather than build the exposition from the outside-in, teaching you first how to draw user interfaces, I’m working from Ruby up. I start with Ruby, start adding Cocoa ideas and tools onto it. The first chapter is very much like that—I’ll let you be the judge of whether it works.

  • Especially in the beginning of the book, I want people to start changing code and seeing what happens. Might as well take advantage of Ruby’s fast edit-run loop.

The chapter and associated code are distributed as a disk image.

What am I looking for? Don’t bother with typos, misspellings, grammar, awkwardly-placed figures, and the like: those will all get changed later. I’m interested in two things:

  1. Did the approach work for you? Did this chapter flow in a pleasing and sensible way? Is there information inexplicably missing?

  2. Where did you get confused or stuck, in either the text or the “try this yourself” sections? Why? What would have helped?

Thanks.

Further announcements will probably go only to the mailing list.

The experience of scripting: a movie

I’ve made a video showing something of what it feels like to script a Mac application using Ruby. It also explains the basics of rb-appscript, one of the two main Ruby frameworks.

I made it after a burst of frustration with how often my scripting runs into wholly unnecessary snags. What I wish I knew is how many people who would love to script iTunes or Mail or whatever won’t because app developers make it too hard.

Perhaps I’ve stumbled into more snags than a normal human would (being a tester curses you that way). Or perhaps I overreact. Both seem to happen a lot. If you have experience with AppleScript or Ruby scripting, and you think so, let me know in comments or mail.

The video is 13 minutes long.

Offer: I’ll write a script for you

As part of working up Ruby Scripting for Leopard, I need to write piles of scripts. If you have a script you’d like to see written, drop me a line. It needs to be a script that controls applications in either /Applications or /System/Library/CoreServices. The application should be one that’s pre-installed or one that most everyone should install anyway (e.g., Quicksilver). You have to be running OS X 1.5 (Leopard).

Controlling iTunes with Ruby (alternate take)

Here’s a different version of the same playlist-generating script. This one uses rb-appscript rather than the built-in Scripting Bridge. (Raw source here.)
(more…)

Controlling iTunes with Ruby

In working on Ruby Scripting Leopard, I’ve been helped by searching for AppleScript examples, such as those at Doug’s AppleScripts for iTunes. To pay it forward, I offer an example to some future searcher after the jump. Since WordPress (or something) is turning quotes into “smart” quotes, follow this link if you want plain text.

This should work on stock Leopard.

I run it via launchd, the replacement for cron(1). Lingon is a convenient way to create a launchd configuration file.
(more…)

Soliciting reviewers and advice-givers

I’ve begun work in earnest on Ruby Scripting for Leopard. I’d like to assemble an audience who can review drafts and tell me what people like them need. I’ve set up a mailing list.

The one sentence description of the book is “How to do anything AppleScript can, but in Ruby.” That is, the main focus will be using Ruby to control other apps like Mail or Safari. It’ll also show you how to write code that makes use of Mac framework features (like sending Growl notifications and putting controllers for your scripts in the status bar). It won’t be your definitive guide to RubyCocoa, though. Most likely I won’t talk about Xcode or Interface Builder at all.

The book will assume no experience scripting Macs (or anything else). I’d like some helpers who fit that category, but also people with lots of experience.

Readers should know Ruby, but I haven’t decided how much. Certainly you needn’t be an expert. Anyone who knows Ruby to the level of my earlier Everyday Scripting with Ruby is definitely in the audience.

Thanks.

Ruby to Growl, with callbacks

I wanted to write a script that used Growl to notify a user. That user could click on the Growl sidle-up, and that would make the script do something. It took me a while to figure out callbacks from Growl to the originating app, so I thought I’d write it down.
(more…)

Emacs: jump to Ruby source

While I’m talking about Ruby in Emacs, here’s a handy emacs function I wrote way back when. Suppose you’ve just run a test and it’s failed. I’ve highlighted the location of the failing assertion below. If you navigate to that line and type ^h^h, you’ll jump to that line in the other window.

^H^h

^h^h isn’t specific to either tests or shell-mode. It works anywhere there’s a line in Kernel#caller format.

Here’s the code:


(defun ruby-visit-source ()
  "If the current line contains text like '../src/program.rb:34', visit
that file in the other window and position point on that line."
  (interactive)
  (let* ((start-boundary (save-excursion (beginning-of-line) (point)))
         (regexp (concat "\([ tnr\"'([< {]\|^\)" ; non file chars or
                                                      ; effective
                                                      ; beginning of file
                         "\(.+\.rb\):\([0-9]+\)")) ; file.rb:NNN
         (matchp (save-excursion
                  (end-of-line)
                  ;; if two matches on line, the second is most likely
                  ;; to be useful, so search backward.
                  (re-search-backward regexp start-boundary t))))
    (cond (matchp
           (let ((file (buffer-substring (match-beginning 2)
                                         (match-end 2)))
                 (line (buffer-substring (match-beginning 3)
                                         (match-end 3))))
             ; Windows: Find-file doesn't seem to work with Cygwin
             ; /// format or the odd /cygdrive// format
             (if (or (string-match “//\(.\)\(.*\)” file)
                     (string-match “/cygdrive/\(.\)\(.*\)” file))
                 (setq file
                       (concat (substring file
                                          (match-beginning 1)
                                          (match-end 1))
                               “:”
                               (substring file
                                          (match-beginning 2)
                                          (match-end 2)))))

             (find-file-other-window file)
             (goto-line (string-to-int line))))
          (t
           (error “No ruby location on line.”)))))

;; I bind the above to ^h^h, an odd choice, because that’s easy to
;; type after reaching the line with ^p or ^n.
(global-set-key “^h^h” ‘ruby-visit-source)    

My Ruby IDE

I’ve decided to use the Intellij IDEA Ruby plugin as my Ruby IDE when working on larger projects and use Aquamacs Emacs for quick work. I think you should all buy IDEA too, so that they are encouraged to make it as good a Ruby editor as it is a Java editor.

Some people use Emacs for large projects. I’m handicapped in doing that because I have an unusually bad short-term memory. So I will often want two or three windows of code plus one shell/test window open. Or at least, I will want wicked fast ways of switching to recently used files. I’ve never found an Emacs workflow that makes having more than two visible buffers comfortable. And Emacs has a more cumbersome way of flipping to recent files than IDEA, plus it doesn’t have the convenient navigational sidebar of modern tools.

I should note that my Emacs skills froze more than a decade ago, so I may be unaware of today’s goodness. In fact, looking in my .emacs file, I see this:


(setq shell-mode-hook
      '(lambda ()
	 (my-shell-setup)
	 (setq mode-line-format
	       (list "%b--" 'default-directory "---%M---%3p---%[(%m: %s)%]%-"))
	 (local-set-key "^j" 'shell-send-input) ; stupid Bridge box
))

The “stupid Bridge box” is a terminal concentrator from around 1987.

I tried TextMate for a couple of months. I approve of the idea, but in practice I had two problems. There’s something about the logic of the key combinations that doesn’t work for me. The way similar commands are organized into related key groups (variants of key modifiers) will not stick in my head, so I was constantly trying control-shift-meta-cokebottle, getting the wrong result, trying shift-control-cokebottle, etc. (And one of the wrong key combinations I often picked—I forget which—made a not-obvious change to the file that would surprise me next time I ran the tests.) Also, the seams kept showing: globalish commands that don’t work because I’m in the sidebar not a source file, the way my tabs kept filling up with files that I’d never intentionally visited, and the like. And the current lack of window splitting is a deal-killer.

I gave NetBeans a shorter trial, and I can’t remember why I didn’t like it.

IDEA has the advantage that I use it for Java, so many of my reflexes carry over. And I always found it had some of that mystical goodness that originally made me prefer Ruby to Python: when I guessed at how something would work, most often I was right.

Still: besides the fact that an upgrade cost me USD 149 (5 euros), it has some disadvantages.

  • The Ruby plugin is beta. I haven’t found too many bugs, but features are incomplete. It’s missing many of TextMate’s nice little Rails features. (But at least you don’t have to install a hack to rerun the last test from anywhere you are.)

  • Because it’s a Ruby IDE wedged into a Java IDE, it may be confusing for people unfamiliar with Java (and, perhaps, Java in IDEA). For example, the General Preferences has these entries: Project JDK (”Ruby SDK 1.8.6″), Project Language Level (irrelevant for Ruby, but on my machine I could choose 1.3, 1.4, or 5.0), and Project Compiler Output (irrelevant).
    (Project setup doesn’t push Java in your face quite that much.)

  • The worst is that it sometimes decides to spend a lot of memory and CPU doing something. When my pokey little MacBook (1.83Ghz, 2G memory) is trying to drive both its screen and a 24 inch external monitor, Time Machine has decided to kick in, and I’ve got various other things running (like Safari, which also likes to suck down CPU while doing nothing visible), IDEA can get slow. I’ll end up typing faster than it can echo characters.

Despite those things, I find IDEA somehow hits a sweet spot where I’m actually working with the code, not the editor (the old ready-to-hand vs. present-to-hand distinction). With other tools, I felt more friction.