Tag: osx

 

Expanding Outline Views in Cocoa

Thanks to a lengthy commute last week, I’ve been making a toy in Cocoa. It reads an URL, parses some XML and displays it in an NSOutlineView. Simple stuff, but it will hopefully make my life better at work, where I need to do this a fair bit.

By default, when I load the XML into the NSOutlineView, everything is closed up. So all you’re presented with is the root element. I’d like to expand that so it automatically includes all children of the root element. Nice and simple—there’s an expandItem: method.

Except that when I call it from the action that puts the XML into the NSOutlineView, it doesn’t work. Bugger.

After instrumenting my XML data source, I can see that nothing is really happening until after my action. My suspicion is that the NSOutlineView isn’t realising that it has any data until after the first call to display.

I tested this by hooking up the call to expandItem into a secondary action (on another button). And it works great.

So, I need a way to say “call this code back in the next idle period”. And this is where I start to get upset that Objective-C doesn’t have closures.

How to execute code soon isn’t easily determined from the apple docs. My guess is that you use an NSTimer with a very small NSTimeInterval . Let’s try that…

  NSTimer *idle = [NSTimer scheduledTimerWithTimeInterval:0.0
                                                   target:self
                                                 selector:@selector(expandRoot)
                                                 userInfo:nil
                                                  repeats:NO];
  [[NSRunLoop currentRunLoop] addTimer:idle forMode:NSDefaultRunLoopMode];

Well, it works. But! Further investigation finally reveals Deferring the Execution of Operations. This suggests that I should use an NSNotification instead, but posted with a NSPostWhenIdle flag. This means getting involved with the cocoa notifications system

The code now ends up looking like this:

  - (void)awakeFromNib
  {
    // Listen out for notification's we've posted to ourselves.
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(expandRoot:)
                                                 name:@"expandRoot"
                                               object:nil];
  }

  -(IBAction)fetch: (id)sender
  {
    // …
    NSNotification* todo = [NSNotification notificationWithName:@"expandRoot"
                                                         object:self];
    [[NSNotificationQueue defaultQueue] enqueueNotification:todo
                                               postingStyle:NSPostWhenIdle];
  }

  - (void)expandRoot:(NSNotification *)notification
  {
    [outlineView expandItem:[[outlineViewDataSource doc] rootElement]];
  }

Which is quite a bit more code. But it feels more robust doing it this way.

The big take away from all this is how difficult it is to use a non-Open-Source framework. If I had the source to Cocoa, I’d be able to look inside and see what I needed to do simply and quickly. Instead, it took me three train journeys. But there’s still enough to like in Cocoa that I intend to carry on.

iTerm

I’ve tried iTerm a few times before, and not really got on with it. I wandered past today however, and noticed that the new version has a full screen option. Yummy.

So I’m giving it a trial run. It’s taken a little bit of setup to work correctly with the damned Linux boxes at work. Mostly this is ensuring that the backspace key sends a backspace instead of a delete1. I also had to turn on option translating to ESC+key, as my emacs-ingrained fingers know that Option-F is forward-word.

Oh, and turning off the tabs as much as possible. I like tabs in my browser, but in a terminal, I’d rather use screen.

But apart from those (minor) quibbles, it seems to be a good little program. I’ll keep going with it for now. And the full screen mode works a treat. It’s just like PuTTY.

1 I hate doing this, but I can’t be bothered to mess around with the Linux boxes.

TextMate Tip

I got really caught out today. I needed to get some code samples from TextMate into Keynote. Cut’n’paste didn’t copy across the colours correctly. Kind of to be expected, since TextMate is a plain text editor, not a rich text editor.

After having a quick hunt around, I found the “Create HTML from Selection” command, which looked like just the ticket. Except that it produced HTML with lots of classes and no CSS (i.e. losing all the style). I played with it a bit, and the “Create CSS from Current Theme” command, all to no avail.

Eventually, I hopped onto irc and wandered into ##textmate on freenode.net. After a brief chat with several people whilst I explained my problem (badly), Allan Odgaard (textmate’s author) noticed that I had the selection enabled. Getting rid of the selection makes a new command appear, “Create HTML from Document”. And that loads into Safari just fine, from where it can be correctly cut’n’pasted into Keynote. Marvellous!

But more than anything, I can’t help but be impressed by the support that Allan offers. This was the middle of Sunday afternoon, and he personally answered my query to completion within 10 minutes. All I can say is that TextMate is well worth the money.

Character Info in Textmate

One rather useful feature of vim is that you can pull up information about a character by positioning your cursor over it and hitting ga (get ASCII?). I quite miss this in textmate, so I created a small command to add to the Text bundle. This is “Character Info”, which I’ve assigned to ^⇧I. It takes the selection as input and the information comes back in a tooltip.

  #!/usr/bin/perl
  use strict;
  use warnings;
  use charnames qw( :full );
  binmode( STDIN, ':utf8' );
  foreach my $c (split //, do { local $/; <> }) {
      my $code = ord $c;
      my $name = charnames::viacode( $code ) || "unknown character";
      printf "U+%04X %s\n", $code, $name;
  }
  exit 0;

This is what it looks like.

Character Info in action

The only caveat is that it only works if you’re using UTF-8 for your files. But really, if not, why not?

System Keychain

This morning I was trying to add a new machine to my wireless network. Unfortunately, I’d forgotten the password… To the Keychain Access batcave!

Unfortunately, the “Airport network password” is stored in the system keychain, instead of my login keychain. Whilst I can unlock the system keychain, when I ask it to show me the password for my wireless network, it prompts for a password. Not my password, as it happens. Oh no. System keychain is protected by a 48 random bytes stored in /var/db/SystemKey. It’s created by the systemkeychain utility the first time your mac is booted. More to the point, there’s absolutely no way I can type those bytes.

So, let’s be cunning I thought. I dropped down to the command line and ran:

  % sudo cat /var/db/SystekMey | pbcopy

Then went back to keychain access only to discover that you can’t paste passwords in OS X.

A bit more googling turned up the security command. In particular, the dump-keychain command. Finally, running this spat out the password I was after:

  % security dump-keychain -d ~/Library/Keychains/login.keychain

At this point, I found out that it was the password for my old wireless network, which I’d just stopped using. A closer inspection of my login keychain revealed another “AirPort network password” which just happened to be for the new network. Ah well, at least it surrendered itself willingly.

From googling, it appears that many other people have been unable to recover stuff in their system keychain. So this is good stuff to know.

Keynote Hates Subversion

I’m annoyed. I’ve just coughed up for a full version of keynote. All the other options for doing presentations on the mac are either unusable or too expensive. I used the pre-installed demo a bit, and I quite like it now. But when I installed the purchased copy, I upgraded to Keynote 3.0.1. And it no longer works with subversion.

Keynote (like many OS X things) stores it’s “files” as a directory containing lots of different things. This is annoying, but still manageable using subversion. Unfortunately, the real problem with Keynote 3.0.1 is that it completely blows away the whole directory each time you save. Along with all my .svn directories inside. Damn.

Looks like I’m not the only one: Keynote and Subversion. One of the suggested workarounds is to switch to svk (which doesn’t have any hidden directories), which I might just do. But it’s still bloody annoying.

Spellchecking POD with TextMate

Trelane was asking on irc today about how to get TextMate to spell check POD. It doesn’t by default, which is annoying as it’s clever enough to check the spelling of strings.

The answer is fairly simple. Go into the Bundle Editor (^⌥⌘B) and open up the Perl category. Near the bottom you’ll see a “Comments” preferences item. Click on the plus box at the bottom of the screen and add another preferences item. Name it “Pod” and stick this in it:

    {    spellChecking = 1; }

In the “Scope Selector” field, type in comment.documentation.perl.

At this point, you have to restart TextMate. I’m not sure why, but you do. But afterwards, you should get lots of dotted red lines inside your pod.

Sadly, the Perl language definition inside TextMate doesn’t distinguish bits of pod much, so you’ll have to add words like “head1” to your dictionary (or fix the language definition).

JavaScript on OSX

So, after my little rant a few days ago, I’ve now gotten JavaScript::JSLint up and running. But that involves downloading a lot of Perl modules, and installing SpiderMonkey, which is a none too pleasant task. However, the Mac should already have JavaScript built in—JavaScriptCore, which is part of WebKit, which is used to build Safari.

So, I’ve spent an interesting couple of days learning Objective-C, Cocoa and nosing around the Apple developer documentation in order to see how to get at the JavaScriptCore. And, as far as I can see, you can’t.

The best I came up with is Using JavaScript From Objective-C. Which sounds nice and well, but from what I can make out, it’s predicated on having a window hanging around, which I want to avoid (I want a command line tool). It also doesn’t provide any interfaces to bind your own functions into the JavaScript interpreter.

Now, JavaScriptCore happens to be one of the Open Source parts of OSX. So, I can just download it, build my own wrapper, and so on. But it is annoying that I have to do so when the system comes with a perfectly good JavaScript interpreter of its own. Not only that, but it’s an alternative implementation to spidermonkey (based on KJS from KDE). And more implementations usually leads to a healthier ecosystem for a programming language.

In the meantime, anybody wanting (relatively) quick access to a lint for JavaScript on osx should probably look at javascriptlint instead. It still needs compiling, but it produces a single file which has no dependencies.

Mind you, I’m still glad at the time I’ve spent. Objective-C is rather nice (apart from the lack of garbage collection—refcounts make me nervous). And Interface Builder is the nicest GUI builder I’ve yet seen. Or at least it’s the only one that didn’t make me run away screaming.

Update: Looks like I missed JavaScript OSA. But that doesn’t look like it’s been updated in years.

osx2x

If you’ve more than one computer at your desk, and one of them is a Mac, you need osx2x. It lets you use all the other computers via VNC or X-Windows connections, using only the one mouse and keyboard. Shiny.

Sadly, the download link on the main site is broken. This is a bit of a pain as it doesn’t appear to be mirrored anywhere.

Luckily, I found one chap who had created a fresh distribution from the (still available) source: osx2x Mac OS 10.4 (Tiger) Universal Binary. I’ve installed that version and it’s working great. My sincere thanks to jamesotron.

Update: Annoyingly, I can’t figure out how to right click when talking to the windows box. That’s a bit annoying.

Terminal, zsh & [Process Completed]

This is mostly a “me too!” post, but it’s been bugging me. Every other time I open a new Terminal window (under OS X Tiger, anyway), I get a [Process Completed] message instead of my shell. According to other people, this happens more if you use zsh, and especially if you close the window using ⌘-W. Interestingly, the same problem occurs in iTerm.

Well, I spent some time with ktrace, zsh, bash and Terminal. Sadly, the results aren’t terribly informative (so far).

First of all, I traced both bash and zsh exiting when ⌘-W was pressed. Neither was particularly interesting. There were no cleanups that one performed that the other did not.

Next, I traced Terminal (and its child processes) when starting up zsh. Twice. The first time everything worked, the second time everything broke. Now the trace makes the point of breakage plainly clear. The broken one gets stuck in a loop reading EOF from file descriptor 17, whereas the working one does not.

Looking back through the trace, file descriptor 17 is opened to /dev/ptyp4. According to pty, that’s a master pseudo terminal. It’s opened inside the Terminal process itself, which then forks, dup2’s the master pty to fd 0 (stdin) and then exec’s /usr/libexec/pt_chown (pt_chown source in FreeBSD should be similiar, judging by strings output).

We don’t see any output for pt_chown as it’s setuid root. But Terminal waits for it to finish, after it’s presumably corrected the ownership of the slave tty. Next, fd 18 is opened by Terminal as the slave tty4, Terminal forks and it’s then dup’d to stdin, stdout and stderr. fd 17 is then closed in that process and login is called.

At this point, Terminal’s got pty4 open, and login’s got tty4 and it’s basically a pipe between the two processes. Except that the kernel is making it look like a genuine 70’s era serial connection to the slave.

Anyway, it’s here that the two traces diverge (coming back to the original problem). The good session reads from the master pty, and then calls stat(2) on tty4. But it’s weird as the trace shows no return value for the read call. OTOH, the broken trace just shows a return value of EOF (0 bytes read) and loops around doing that for a few thousand times.

Funnily enough, the trace looks pretty much identical to that which would be produced by program 19.3 in Rich Steven’s APUE (best book I ever bought).

Sadly, it still hasn’t gotten me to the bottom of the problem. But I have refreshed my memory about how pseudo-terminals work. 🙂 I suspect that to make further progress, I’d have to run login under ktrace as well. I imagine that something is going wrong in there causing it to exit early, which is why the read in the parent returns EOF. Even then, I’m not sure if running it all as root would affect the outcome. Probably is my guess…

And no, I will not stop using zsh!

Update: A useful tip for debugging what your shell is doing at startup under osx. Add these lines to the top of ~/.zshrc (or ~/.bashrc if you’re a luddite 😉 ):

  lsof -p $$ > ~/lsof.out.$$
  ktrace -p $$ -f ~/ktrace.out.$$

This still doesn’t capture what’s going on in the parent process (login), but it does give you an idea of what the shell is getting up to.