Mark Alldritt has posted a memory of his 20 years developing LateNight Software’s flagship product, Script Debugger. This generated a thread of further memories and thoughts from users on the SD-Talk email group, including mine. The email group is private, though, so I decided it might be nice to reproduce my email here, in public.
It all started for me in 1995 when I took over as editor of MacTech. LateNight was an advertiser, so Gerry got in touch with me. MacTech needed some heavy AppleScript tasks and I used SD to develop them. When I left MacTech I got heavily into Frontier, for which SD was an “external editor”, and I documented its use for that purpose in my Frontier book.
However, my close association with LateNight and Mark didn’t start until 2000, when Mark asked me to step in and supply some chapters of the documentation. I hammered Mark with questions and criticisms which he took in very good humor, implementing many of my suggestions, and starting a major Gilbert-and-Sullivan type collaboration; I don’t think most people are aware of my work over the years as a primary bug-finder and interface-tweak-suggester for Script Debugger, and this is when it started. We both worked very hard and I supplied the documentation in record time while he had worked on SD at the same time.
My memory of the time I minded the booth at Macworld Expo is a little different from Mark’s. What I remember is that I made a sale! (To Brian Shin.) By that time, we had the Explorer, and when I got to that part of my demonstration Brian’s jaw dropped and he whipped out his wallet. To anyone who had spent any time trying to write AppleScript code, Script Debugger sold itself!
My collaboration with Mark got even tighter in 2005. A lot of things happened at once; Mark was working on a new version of Script Debugger (v. 4, the first version in Cocoa) and he was taking over FaceSpan — and I got the contract to write my AppleScript book. That book would have been totally impossible without Script Debugger and, even more important, Mark’s unbelievable knowledge of AppleScript under the hood. For several months I was hammering Mark with email questions about SD or AppleScript every day! After I finished the book I turned my attention full time to the documentation (which was still being produced with Frontier). It all came together in early 2006 and I wrote this article to announce it all.
Script Debugger continued to develop, plus in 2007 I added FaceSpan to my list of things I was helping Mark with. Things got hot and heavy again in 2008. Frontier was getting creaky and I had spent some months developing a replacement written in Ruby, which I call RubyFrontier. Its primary purpose was to allow me to keep producing documentation for Mark, and in early 2008 I was able to build the docs with it. It’s the Frontier / RubyFrontier documentation system that I developed that accounts for the astonishing navigation and interlinking of the Script Debugger documentation, which persists to this day.
And RubyFrontier didn’t come into the world a moment too soon, because we were soon embarked on Script Debugger 4.5 and its amazing beta process, which I commented on in my TidBITS article when it was released at the end of the year.
In 2012 we were on to Script Debugger 5, and by about May I had finished the documentation and was adding something new — the videos. These have been received well, I believe, and I’m still always excited about Script Debugger when I watch them.
I’ve gone into all this detail (and I could say much more about what was happening in 2007-9 with FaceSpan) to show how important Script Debugger and Mark personally have been in my life. Mark has been my employer, my technical guru, my inspiration as a programmer, and my friend. Working for him kept me going during some lean years, and I wouldn’t be who I am today without him!
An iOS device (an iPhone or iPad) should just chug along, doing its thing, but instead it turns out to need some care and feeding — which is not at all easy, seeing that its contents are pretty much opaque. In particular, every once in a while, everyone should probably be fighting “space creep,” a phenomenon where the amount of free space on the device shrinks unaccountably over time.
On my 16GB iPad, I just went from this:
My free space almost doubled, from about 2.5GB to nearly 5GB. Most of the reclaimed space comes from the mysterious “Other” usage category, a category that Apple, as far as I know, has never satisfactorily explained. Oddly, though, some of the Apps space has also been reclaimed, even though it’s the same set of apps with the same sandboxed data; perhaps the difference can be attributed to inefficiencies in caching policies of individual apps.
Although TextMate has been around for a long time (in computer years) and many language bundles exist, it is startling to find that the process of writing a language grammar remains poorly documented. Having recently managed to write a grammar of my own for the first time, here are some things I learned along the way.
Some of my earlier thoughts here have described my adventures with different versions of Ruby, especially in connection with RubyFrontier. So it’s only right to mention that at this point I’m not playing around with Ruby versions at all. I’m working under Mac OS X 10.9 “Mavericks”, which effectively force-upgrades you to Ruby 2.0. So at the moment I’m not using
rbenv: I’m just using the default system Ruby that Mavericks provides.
This combination (RubyFrontier and Ruby 2.0 on Mavericks) works fine with TextMate 2, which is currently open source and free. That is the combination I’m currently using for all my writing. (There was some trouble, under TextMate 2, with the AsciiDoc bundle that I’ve been using for years to write the several editions of my iOS programming book; but I solved that by creating my own AsciiDoc bundle.)
I should also mention that TextMate 2 is remarkably easy to build on your own, if downloading the prebuilt binary doesn’t satisfy your DIY urges. Just follow the simple directions. You will need Xcode and HomeBrew. Disregard the paragraph in the instructions that says you don’t need to install
hg — you do. Also, beware of Xcode 5.1, which includes a new version of
clang that breaks the build process; stick with Xcode 5.0.2.
Snow Leopard (Mac OS X 10.6) was the last Mac system I really liked; I detested Lion (10.7), but could live with Mountain Lion (10.8) long enough to use it temporarily when necessary — as when writing my books, where I needed to be using the latest version of Xcode. This situation I managed by maintaining an internal hard disk with two partitions, one with Snow Leopard installed, the other with Mountain Lion. By rebooting, I could switch systems.
But this situation could not endure forever. The computer was never entirely happy with it; booting into the Snow Leopard partition, for example, tended to damage the Spotlight index on the Mountain Lion partition, and vice versa. Much more significant, one day the Mountain Lion partition was damaged and had to be erased — at which point I installed Mavericks (10.9) on it — and this got me thinking: my computer is four years old, and if I buy a new one, it won’t run Snow Leopard at all.
I therefore decided to experiment with virtualizing Snow Leopard. The idea is that if I can get Snow Leopard installed and running as a virtual machine now, on a computer where installation of Snow Leopard is still permitted, then in the future, on some other computer, that virtual machine might continue working.
I was able to install Ruby 2.0 on Mountain Lion (Mac OS X 10.8.3) very easily, but I’m afraid I didn’t actually learn anything in the process.
The problem is that there is something wrong with Mountain Lion’s OpenSSL installation. This bites you when you try to use the
gem command. Working around the problem when compiling Ruby 2.0 is very tricky — so tricky that I wasn’t able to figure out how to do it.
So I cheated: I let ruby-build do it for me.
I’m already using rbenv to switch among ruby versions, so installing ruby-build into it as a plug-in is a no-brainer and a one-liner:
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
After that, you just say this:
$ rbenv install 2.0.0-p0
ruby-build takes care of downloading and building a new version of OpenSSL (which I had already done) and of building ruby while pointing at that new version (which I had tried to do but somehow failed). The result is a working ruby 2.0. I’m afraid I didn’t turn on verbose logging so I don’t what ruby-build actually did, but it is evidently smarter than I am.
It never ceases to astound me how developers will very generously provide source code and at the same time very shabbily and stingily fail to provide instructions for compiling or using it. I think this is probably a form of misguided intellectual snobbery, a way of saying “I’m smart, and if you’re also smart you’ll also be able to figure this out from the sparse and vague hints I’ve left lying around, and if you’re not smart you don’t deserve to use my software anyway.” A case in point is Mike Adbullah’s libssh2_sftp-Cocoa-wrapper, a set of Cocoa classes and a dynamic library for doing SFTP in a Cocoa application. This is a wonderful library of code, and I certainly couldn’t possibly do SFTP in Cocoa without it. But to get started with it, I had to spend about a week banging my head against the wall, so here, in hopes that it may assist someone else, is what I eventually discovered.
I’ve long been an admirer of the film music of Bernard Herrmann, whom I regard as one of our greatest classical composers. He did with film music what a classical composer would have done with concert-hall orchestral music. Like Ginger Rogers, who did everything Fred Astaire did plus she did it backwards wearing high heels, Herrmann did what Aaron Copland or Igor Stravinsky or Kurt Weill did, within the curious confines of film and television (and radio). Plus he wrote for a lot more films than most people probably realize.
Listening attentively recently to the score of Citizen Kane (I think what I was hearing was this recording), I was struck suddenly by a fact that had previously eluded me: almost the entire score is a massive fantasia on a four-note theme, and that theme is the first four notes of the Dies Irae. He shifts the pitches a bit, he inverts them, he turns them inside-out, but they are there in practically every measure. I’m not the first person to notice this, and indeed it was no secret, but it was a shock and joy discovering it for myself, and of course it made me hear and appreciate the music in a whole new way.
My mother, whose iMac and iPad I maintain and support at a transcontinental distance, phoned me today with a weird problem. Her iPad was showing that some apps had updates waiting for her at the App Store, but when she tried to use the Updates section of the App Store app, a dialog said, uninformatively, that the iPad couldn’t connect with the iTunes Store. We tried re-entering her iCloud username and password, but to no avail.
In desperation I googled “ipad can’t connect to iTunes store” and found, quite consistently over several different sites, the following improbable suggestion: turn off automatic setting of the iPad’s date and time, set the date manually to a year several years in the future, attempt to update the apps again, then turn automatic setting of the iPad’s date and time back on. Working through the process on my own iPad, so that I could give her gesture-by-gesture instructions, I had her do that and — it worked. When she went back to the App Store app once again after the whole procedure was finished, it worked normally and she could update her apps.
I suspect that the problem has something to do with some sort of bad certificate. Setting the date into the future and attempting to connect caused the certificate to be thrown away, thus allowing a new certificate to be obtained from the App Store the next time. But that’s just a wild hunch. What messing with the date really has to do with connecting to the App Store is really anybody’s guess. This is another good example of the totally uninformative error messages produced by the iPad.
I’m still discovering the effects upon RubyFrontier caused by the (still experimental) switch from Ruby 1.8.7 to Ruby 1.9.3. One of the chief effects has been that RubyFrontier is way slower! The difference is visible chiefly when rebuilding the autoglossary.
Running a profile with ruby-prof led me to suspect that the source of the slowdown might by YAML. A quick googling session seemed to confirm this suspicion. So I added this line right after my initial YAML require:
YAML::ENGINE.yamler = 'syck'
This swaps out the use of the Psych library and uses the old Syck library instead. The result is that the time needed, for example, to rebuild the autoglossary for the Script Debugger 5 help dropped from 14 seconds to 7 seconds! Kind of a big difference. In fact, that 7 seconds is a second or two faster than the same task under Ruby 1.8.7. This entire affair is particularly ironic given the fact that Ruby 1.9.3 is so demanding about finding the Psych library present when you build it; if it’s missing,
gem and YAML both complain every time you use them.
Either Psych needs to work decently or
gem and YAML should shut the hell up.
In other news, the output format of
Time#to_s changed in Ruby 1.9, breaking some more of my code. These Ruby people really don’t care what they break, do they?
Having established a way of switching between Ruby versions, I began to concern myself with trying to get RubyFrontier to work under Ruby 1.9.3. I wasn’t expecting it to work right out of the box, so I tried to prepare myself by guessing what sorts of problem might arise. A lot of interesting Ruby 1.9 features are of course not backward-compatible with Ruby 1.8, but my problem was the converse: what aspects of Ruby 1.9 are likely to break what I’m already doing?
Don’t get the wrong idea; I’m not actually writing this in RubyFrontier from within Ruby 1.9.3. RubyFrontier isn’t ready for Ruby 1.9! But in order for RubyFrontier ever to have even a chance of becoming ready for Ruby 1.9, clearly I would sooner or later have to install Ruby 1.9. The problem, of course, is that I’m already using Ruby 1.8.7, and I need it for production work (like for using RubyFrontier and my various rb-appscript scripts); so the only way I can install Ruby 1.9 is if I have an easy way of switching back and forth between Ruby versions. I needed a Ruby version management system; and the much-ballyhooed RVM was not going to be it. Everything about RVM — the way it works under the hood, the zillions of posts about the issues it raises and the trickery needed to work around them — was opposed by every fibre of my intuition.
Then a few days ago I learned of rbenv, and I knew I wanted to try it right away. The simplicity and elegance of rbenv is simply breathtaking. It doesn’t do any of the scary, skanky things that RVM does. There’s a folder full of shim scripts masquerading as binary files such as
ruby, which you add to the start of your
PATH; that’s basically all. You install a version of Ruby into an ordinary folder in your .rbenv directory, and rbenv detects this. When you tell rbenv which version of Ruby you want to use, it changes the contents of a one-line configuration file called version. When you try to execute one of the binaries, what runs is the shim file, which creates an environment where the desired Ruby folder is now at the start of your
PATH, and runs the real binary in that environment. For extra convenience you can also add a line to your
.bash_profile to make certain things automatic, but they are all things you could equally have done yourself; no magic or swizzling is involved.
From Paolo Perrotta, Metaprogramming Ruby, Pragmatic Programmers, 2010, p. 114f.:
You can detach a method from its object with
Method#unbind(), which returns an UnboundMethod object. You can’t execute an UnboundMethod, but you can turn it back into a Method by binding it to an object… Good luck finding a good reason to use this exotic stuff in real life!
Okay, so you explicitly dismiss UnboundMethod as useless — when it’s the basis for one of the most flexible forms of monkeypatching, as well as the all-important BlankSlate class? I can’t tell whether this is because you’re deliberately being shallow (to spare the reader the technical details) or you’re merely ignorant of UnboundMethod’s importance, but it hardly matters, because I just threw your book out the window. In a book that claims to be about metaprogramming Ruby, this sort of omission-by-dismissal is unforgivable.
This page prepared
December 5, 2014
by Matt Neuburg, phd = matt at tidbits dot com,
RubyFrontier is a port, written in the Ruby language,
of the Web-site-creation features of UserLand Frontier.
Works just like Frontier, but written in Ruby!
Download RubyFrontier from GitHub.