Capitalize script for BBEdit

I think most of us have a few typos that we just can’t shake. No matter how hard we try, our fingers just keep making the same mistakes over and over. The great classic is “teh,” a typo so common its ironic use is a talisman of internet hipsterism.

I don’t type “teh” very often, but its sibling “hte” and cousin “htat” are constant annoyances. Or at least they were constant annoyances until I made TextExpander snippets that corrected them automatically. This is a pretty common use of TextExpander, one that the folks at Smile have encouraged for years.

Unfortunately, one of my most common typing goofs is something TextExpander can’t help: I tend to lift my pinky off the Shift key just a little too soon and end up not capitalizing words I intend to. Sometimes I notice the error while I’m still in the middle of the word that should be capitalized; sometimes I’ve finished the word and hit a space before I notice. Cursoring back to capitalize the first letter is such a pain in the ass I’ve created a macro/script/command to do that for me in every text editor I’ve ever used: Emacs, Vim, NEdit, BBEdit, and TextMate. Here’s the post I wrote about my TextMate macro back in 2006. It served me until I returned to BBEdit late last summer.

What surprised me when I switched back was that my old BBEdit Capitalize script, untouched since 2005, was still sitting in my Application Support folder for BBEdit. And it still worked! Almost. There was one situation in which it didn’t quite do everything I wanted.

If I finished typing the word that should have been capitalized and added a space after it, like this (the red bar indicates the insertion point)

lift my pinky off the shift |

then invoking the script would capitalize the word just fine, but put the insertion point immediately after the word instead of where I’d started

lift my pinky off the Shift| 

and I’d have to cursor over past the space.

I lived with this flaw in the script for months but recently decided enough was enough. Here’s the new script1

 1:  tell application "BBEdit"
 2:    tell window 1
 3:      if selection as text is "" then
 4:        set cursorPoint to characterOffset of selection
 5:        find "\\b\\w" options {search mode:grep, backwards:true} with selecting match
 6:        set selection to (grep substitution of "\\U&")
 7:        select insertion point before character cursorPoint
 8:      else
 9:        change case selection making capitalize words with replacing target
10:      end if
11:    end tell
12:  end tell

Line 4 saves the current insertion point position.2 Line 5 searches backward to find and select the first character of the word before the insertion point. “Word” in this case may not always be what you think. In regular expression syntax, \b represents a word boundary, the location between a non-word character and a word character. Word characters are all the upper- and lower-case letters, the numerals, and underscore; non-word characters are everything else. So if the insertion point is at the end of a word with an apostrophe, like “can’t” or “you’re,” Line 5 will select the letter after the (non-word) apostrophe. This glitch has been in every one of my capitalization macros—it doesn’t get in the way very often.

Before we leave Line 5, I should mention that the backslashes are doubled because AppleScript, like many scripting languages, considers the backslash a special character. To pass a literal backslash on to BBEdit’s regex engine, we need to double it in our AppleScript strings.

Line 6 uses the \U case transformation modifier to switch the letter that was found in Line 5—represented by the &—to upper case. Line 7 then moves the cursor back to where it was.

Line 9 handles a situation that I didn’t mention above. If I invoke the Capitalize script when text is selected, I want all the words in the selection to be capitalized. I don’t do this very often.

I have the Capitalize script bound to ⌃⌘C, the same keystroke shortcut I used in TextMate.3 I use it several times every day, saving me lots of cursor movement and lots of frustration.

  1. If you’re a fan of keybindings, or if you remember that I set up a Capitalize keybinding back in 2011, you might be wondering why I need an AppleScript. Doesn’t that keybinding work in BBEdit? In a word: no. Either BBEdit isn’t using Cocoa text editing (which is what I suspect), or it’s blocked access to keybindings stored in ~/Library/KeyBindings/DefaultKeyBinding.dict. Whatever the reason, I’m probably better off using a script. That keybinding wasn’t handled consistently, even by the applications that could use it. 

  2. Every time I need to move the insertion point around in BBEdit, I refer to this post by Nathan Grigg

  3. The old post says I originally had it bound to F4 in TextMate; that didn’t last long.