WWDC brought us a whirlwind of changes all over Apple's platforms. One interesting announcement was Xcode Source Editor Extensions. These allow us to add commands to Xcode that can work with the contents of the code we're working on. Yes, Apple also announced that Xcode won't load plugins (like Alcatraz, etc.) anymore. Bummer.

Today we'll try to shake off our feels about plugins going away by making our first Source Editor Extension, let's do it!

We're going to make a super-simple Extension that lets us easily "sign" our code comments. Like this:

// - @jakemarsh

We'll start by creating a new macOS app. Then we'll add a new target to it, and choose Xcode Source Editor Extension.

Xcode gives us a nice template of files to start with. We can head into SourceEditorCommand.swift to implement our command.

class SourceEditorCommand: NSObject, XCSourceEditorCommand {
  func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: (NSError?) -> Void ) -> Void {
    guard let selection = invocation.buffer.selections.firstObject as? XCSourceTextRange else { completionHandler(createError()); return }

    let commentText = "// - @\(NSUserName())"

    invocation.buffer.lines.insert(commentText, at: selection.end.line)

    completionHandler(nil)
  }
}

We start by looking at the invocation's selection and guard'ing to make sure there's a valid insertion point for us to append to, then create a new comment using the handy NSUserName() function in macOS.

Finally, we use the provided XCSourceEditorCommandInvocation one more time to insert the new comment text into the buffer. We call the completionHandler with a nil to let Xcode know we've completed our work without any errors, and we're done!

We can customize the name of our command in our Info.plist, like this:

Now, how are we going to test this thing out? Well, Xcode has some nice support built in for debugging these, but first we'll have to endure a little pain to get things working (at least during this first beta, later Xcode 8 releases will hopefully not need these steps).

We'll only need this while running OS X 10.11, macOS 10.12 users can skip this step:

We'll need to run sudo /usr/libexec/xpccachectl in Terminal, then reboot our Mac.

Once it's back up, we can open Xcode 8 again, and Build & Run our Extension. We'll be asked to choose which app we'd like to run it in. We'll choose Xcode 8 (be careful not to choose an older Xcode version as the icons are easy to miss).

Another instance of Xcode 8 will launch in our dock and… Boom! Xcode's dark heart is revealed!

Just kidding, Xcode is displaying itself this way to help us differentiate between the one that we're debugging, and the "real" one.

We can head to the Editor menu to test out our new command. That's not all though, we can go back to the other Xcode instance and set breakpoints, inspect variables, etc. Neat!

Plugins may be gone, but Source Editor Extensions still offer a ton of interesting possibilities. Looking for inspiration? Here's a few on Github already.