Archive for the 'UndocumentedGoodness' Category

Colorized man pages: Understood and customized

Monday, August 15th, 2016
man() {
    env \
        LESS_TERMCAP_mb=$(printf "\e[1;31m") \
        LESS_TERMCAP_md=$(printf "\e[1;31m") \
        LESS_TERMCAP_me=$(printf "\e[0m") \
        LESS_TERMCAP_se=$(printf "\e[0m") \
        LESS_TERMCAP_so=$(printf "\e[1;44;33m") \
        LESS_TERMCAP_ue=$(printf "\e[0m") \
        LESS_TERMCAP_us=$(printf "\e[1;32m") \
            man "$@"

Screenshot of Terminal showing the zsh manpage with the above customizations.

Pretty neat, right? Let’s tear it apart, see what it’s doing, and think about how we might customize it to suit ourselves.


Setting the iPhone API documentation to iPad display mode on your Mac

Monday, April 5th, 2010

Those who’ve bought iPads have noticed that the iPhone API documentation comes in a special iPad-optimized flavor:

Basically, like an iPhone app for viewing the iPhone documentation. Here's a screenshot of the page in Safari on my Mac.

Yes, that’s desktop Safari showing it.

Contrary to my expectation, it does not use user-agent sniffing to detect an iPad. In fact, it’s detected by a JavaScript script (credit) when you go to an iPad-specific front page.

The code has a debugging feature, which they left in and you can (for now) enable to use the iPad display mode in your WebKit-based browser. Here’s how to enable it:

  1. Open any page on
  2. Open this URL:

    javascript:localStorage.setItem('debugSawtooth', 'true')
  3. Go to the iPad documentation list.

There are actually two interfaces, corresponding to the two orientations of a physical iPad. The one I showed above, with the API tree in a sidebar, is the landscape orientation; portrait moves the API tree into a pop-over, under a button labeled “Library”. The page chooses one or the other by the aspect ratio of the window.

“Sawtooth” has some drawbacks:

  • On a Mac, your scroll wheel (or two fingers) won’t work; you must drag the interface instead, which corresponds to finger-dragging on the actual device.
  • Once the interface loads, its size and orientation are fixed; it won’t adapt to a window resize until you reload. This, too, is only a problem on a Mac (you can’t resize your iPad).
  • There’s no way to copy a link to a specific document, unless you can find an internal link (the API-tree table view doesn’t count). This can be a problem if you want to link to, say, a framework reference.
  • You can’t get the Sawtooth interface unless you go through the iPad front page. If you go to a framework reference, class reference, programming guide, or other more specific page, you’ll get the regular interface. Same thing when going through the regular front page.

Even so, it’s pretty spiffy. I wish I had a version with all of the above problems fixed for viewing Mac API documentation.

* Credit: JR Ignacio found the JavaScript code and excerpted it into a GitHub paste.

Undocumented Goodness: CGSSetSystemDefinedCursor

Saturday, April 3rd, 2010

As with all undocumented private APIs, this one may change or go away any time. Use with extreme caution or, better yet, not at all.

As you’d expect from a CGS function, you’ll need a CGSConnection to use this one:

typedef void *CGSConnectionRef;
extern CGSConnectionRef _CGSDefaultConnection(void);
extern unsigned CGSSetSystemDefinedCursor(CGSConnectionRef connection, unsigned cursorID);

(I am, of course, not sure of the correct type for cursorID, although it is 32-bit.)

The valid cursor IDs range from 0 to 8; for anything else, CGSSetSystemDefinedCursor returns kCGErrorIllegalArgument. You’ll also get that error if you pass a bogus connection ref.

Here are the cursor IDs, as I’ve named them:

enum {

IBeamComposite is the normal I-beam cursor. IBeamInvert is a variation that inverts what’s underneath it, instead of compositing over it. The benefit is that this shows up well on dark backgrounds (it appears white), whereas IBeamComposite blends in.

Link and Copy are the Mac OS 8.5 versions of those cursors, not the larger full-color ones introduced in Mac OS X 10.2.

ArrowWhite is exactly what it says on the box: A white-with-black-outline version of the standard Mac arrow cursor. The colors of the Windows arrow cursor with the stem length of the Mac arrow cursor.

ContextualMenu is my rough interpretation, as the stack of white rectangles next to the (black) arrow cursor looks only vaguely like a series of menu items. To my eyes, it looks more like a stack of giant hard disk platters (like the standard icon for a database that has become common recently) than a contextual menu, but I doubt that this was what they meant. This is not the contextual menu cursor from Mac OS 8 and 9.

Pinwheel is exactly what it says on the box. It’s even animated. This is the prize of the collection: If you ever want to deliberately put on the pinwheel cursor (which you should NEVER EVER DO), this is the way to do it.

Hidden is also exactly what it says on the box: A fully-transparent cursor image.

So, there you go, for your information, entertainment, and hopefully not use.

Capture Cursor

Saturday, March 13th, 2010

Most people don’t know how to get the cursor that’s currently on the screen—a useful ability, especially if you’re writing screenshot or screen-recording software. I’ve written an app that demonstrates the technique, or at least tries to.

It’s a bit flaky. The API it uses, IOFramebuffer, doesn’t tell me how many frames there are or what format they’re in, so the app assumes ARGB in native byte-order and doesn’t worry about frames. This gives wrong results more of the time than I like.

I’ve filed a request for a higher-level API, which would make the task much easier and the app much shorter.

I’ve posted a build in the repository’s downloads area, in case you’d like to see it in action. If you want to build it yourself, you’ll need to download SGHotKeysLib and put the source where the Capture Cursor Xcode project expects it to be.

UPDATE 2010-08-28: I’ve pushed a change, [9cbec7dd5169], that deletes the IOFramebuffer-based category method and uses Snow Leopard’s new, far more reliable [NSCursor currentSystemCursor] instead. I suggest you do the same.